diff -Nru vboot-utils-0~R88-13597.B/Android.mk vboot-utils-0~R99-14469.B/Android.mk --- vboot-utils-0~R88-13597.B/Android.mk 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/Android.mk 2022-02-11 14:46:09.000000000 +0000 @@ -54,7 +54,6 @@ firmware/lib/gpt_misc.c \ firmware/lib/utility_string.c \ firmware/lib/vboot_api_kernel.c \ - firmware/lib/vboot_audio.c \ firmware/lib/vboot_display.c \ firmware/lib/vboot_kernel.c \ firmware/lib/region-kernel.c \ @@ -62,7 +61,6 @@ VBINIT_SRCS += \ firmware/stub/tpm_lite_stub.c \ firmware/stub/utility_stub.c \ - firmware/stub/vboot_api_stub_init.c \ firmware/stub/vboot_api_stub_region.c VBSF_SRCS += \ diff -Nru vboot-utils-0~R88-13597.B/cgpt/cgpt_common.c vboot-utils-0~R99-14469.B/cgpt/cgpt_common.c --- vboot-utils-0~R88-13597.B/cgpt/cgpt_common.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/cgpt/cgpt_common.c 2022-02-11 14:46:09.000000000 +0000 @@ -9,7 +9,7 @@ #include #include #include -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #include #include #endif @@ -295,7 +295,7 @@ if (fstat(fd, &stat) == -1) { return -1; } -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) if ((stat.st_mode & S_IFMT) != S_IFREG) { if (ioctl(fd, BLKGETSIZE64, size) < 0) { return -1; @@ -325,7 +325,7 @@ memset(drive, 0, sizeof(struct drive)); drive->fd = open(drive_path, mode | -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) O_LARGEFILE | #endif O_NOFOLLOW); @@ -672,6 +672,8 @@ const Guid guid_chromeos_reserved = GPT_ENT_TYPE_CHROMEOS_RESERVED; const Guid guid_efi = GPT_ENT_TYPE_EFI; const Guid guid_unused = GPT_ENT_TYPE_UNUSED; +const Guid guid_chromeos_minios = GPT_ENT_TYPE_CHROMEOS_MINIOS; +const Guid guid_chromeos_hibernate = GPT_ENT_TYPE_CHROMEOS_HIBERNATE; const static struct { const Guid *type; @@ -686,6 +688,8 @@ {&guid_chromeos_reserved, "reserved", "ChromeOS reserved"}, {&guid_efi, "efi", "EFI System Partition"}, {&guid_unused, "unused", "Unused (nonexistent) partition"}, + {&guid_chromeos_minios, "minios", "ChromeOS miniOS"}, + {&guid_chromeos_hibernate, "hibernate", "ChromeOS hibernate"}, }; /* Resolves human-readable GPT type. diff -Nru vboot-utils-0~R88-13597.B/cgpt/cgpt_find.c vboot-utils-0~R99-14469.B/cgpt/cgpt_find.c --- vboot-utils-0~R88-13597.B/cgpt/cgpt_find.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/cgpt/cgpt_find.c 2022-02-11 14:46:09.000000000 +0000 @@ -96,19 +96,6 @@ EntryDetails(entry, partnum - 1, params->numeric); } -// This handles the MTD devices. ChromeOS uses /dev/mtdX for kernel partitions, -// /dev/ubiblockX_0 for root partitions, and /dev/ubiX for stateful partition. -static void chromeos_mtd_show(CgptFindParams *params, const char *filename, - int partnum, GptEntry *entry) { - if (GuidEqual(&guid_chromeos_kernel, &entry->type)) { - printf("/dev/mtd%d\n", partnum); - } else if (GuidEqual(&guid_chromeos_rootfs, &entry->type)) { - printf("/dev/ubiblock%d_0\n", partnum); - } else { - printf("/dev/ubi%d_0\n", partnum); - } -} - // This returns true if a GPT partition matches the search criteria. If a match // isn't found (or if the file doesn't contain a GPT), it returns false. The // filename and partition number that matched is left in a global, since we @@ -214,51 +201,29 @@ return 0; } -// This scans all the physical devices it can find, looking for a match. It -// returns true if any matches were found, false otherwise. -static int scan_real_devs(CgptFindParams *params) { +#ifdef GPT_SPI_NOR +// This handles the MTD devices. ChromeOS uses /dev/mtdX for kernel partitions, +// /dev/ubiblockX_0 for root partitions, and /dev/ubiX for stateful partition. +static void chromeos_mtd_show(CgptFindParams *params, const char *filename, + int partnum, GptEntry *entry) { + if (GuidEqual(&guid_chromeos_kernel, &entry->type)) { + printf("/dev/mtd%d\n", partnum); + } else if (GuidEqual(&guid_chromeos_rootfs, &entry->type)) { + printf("/dev/ubiblock%d_0\n", partnum); + } else { + printf("/dev/ubi%d_0\n", partnum); + } +} + +static int scan_spi_gpt(CgptFindParams *params) { int found = 0; char partname[MAX_PARTITION_NAME_LEN]; - char partname_prev[MAX_PARTITION_NAME_LEN]; FILE *fp; - char *pathname; - - fp = fopen(PROC_PARTITIONS, "re"); - if (!fp) { - perror("can't read " PROC_PARTITIONS); - return found; - } - size_t line_length = 0; char *line = NULL; - partname_prev[0] = '\0'; - while (getline(&line, &line_length, fp) != -1) { - int ma, mi; - long long unsigned int sz; - - if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4) - continue; - - /* Only check devices that have partitions under them. - * We can tell by checking that an entry like "sda" is immediately - * followed by one like "sda0". */ - if (!strncmp(partname_prev, partname, strlen(partname_prev)) && - strlen(partname_prev)) { - if ((pathname = is_wholedev(partname_prev))) { - if (do_search(params, pathname)) { - found++; - } - } - } - - strcpy(partname_prev, partname); - } - - fclose(fp); fp = fopen(PROC_MTD, "re"); if (!fp) { - free(line); return found; } @@ -299,6 +264,60 @@ free(line); return found; } +#else +// Stub +static int scan_spi_gpt(CgptFindParams *params) { + return 0; +} +#endif + +// This scans all the physical devices it can find, looking for a match. It +// returns true if any matches were found, false otherwise. +static int scan_real_devs(CgptFindParams *params) { + int found = 0; + char partname[MAX_PARTITION_NAME_LEN]; + char partname_prev[MAX_PARTITION_NAME_LEN]; + FILE *fp; + char *pathname; + + fp = fopen(PROC_PARTITIONS, "re"); + if (!fp) { + perror("can't read " PROC_PARTITIONS); + return found; + } + + size_t line_length = 0; + char *line = NULL; + partname_prev[0] = '\0'; + while (getline(&line, &line_length, fp) != -1) { + int ma, mi; + long long unsigned int sz; + + if (sscanf(line, " %d %d %llu %127[^\n ]", &ma, &mi, &sz, partname) != 4) + continue; + + /* Only check devices that have partitions under them. + * We can tell by checking that an entry like "sda" is immediately + * followed by one like "sda0". */ + if (!strncmp(partname_prev, partname, strlen(partname_prev)) && + strlen(partname_prev)) { + if ((pathname = is_wholedev(partname_prev))) { + if (do_search(params, pathname)) { + found++; + } + } + } + + strcpy(partname_prev, partname); + } + + fclose(fp); + free(line); + + found += scan_spi_gpt(params); + + return found; +} void CgptFind(CgptFindParams *params) { diff -Nru vboot-utils-0~R88-13597.B/cgpt/cgpt.h vboot-utils-0~R99-14469.B/cgpt/cgpt.h --- vboot-utils-0~R88-13597.B/cgpt/cgpt.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/cgpt/cgpt.h 2022-02-11 14:46:09.000000000 +0000 @@ -7,7 +7,7 @@ #define VBOOT_REFERENCE_CGPT_H_ #include -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #include #endif #include diff -Nru vboot-utils-0~R88-13597.B/cgpt/cgpt_nor.c vboot-utils-0~R99-14469.B/cgpt/cgpt_nor.c --- vboot-utils-0~R88-13597.B/cgpt/cgpt_nor.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/cgpt/cgpt_nor.c 2022-02-11 14:46:09.000000000 +0000 @@ -24,6 +24,7 @@ #include "cgpt.h" #include "cgpt_nor.h" +#include "subprocess.h" static const char FLASHROM_PATH[] = "/usr/sbin/flashrom"; @@ -48,6 +49,7 @@ return ret; } +// TODO(b:184812319): Remove these functions and use subprocess_run everywhere. int ForkExecV(const char *cwd, const char *const argv[]) { pid_t pid = fork(); if (pid == -1) { @@ -68,7 +70,7 @@ return status; } -int ForkExecL(const char *cwd, const char *cmd, ...) { +static int ForkExecL(const char *cwd, const char *cmd, ...) { int argc; va_list ap; va_start(ap, cmd); @@ -200,6 +202,7 @@ // Read RW_GPT from NOR flash to "rw_gpt" in a temp dir |temp_dir_template|. // |temp_dir_template| is passed to mkdtemp() so it must satisfy all // requirements by mkdtemp. +// TODO(b:184812319): Replace this function with flashrom_read. int ReadNorFlash(char *temp_dir_template) { int ret = 0; @@ -212,27 +215,40 @@ // Read RW_GPT section from NOR flash to "rw_gpt". ret++; - int fd_flags = fcntl(1, F_GETFD); - // Close stdout on exec so that flashrom does not muck up cgpt's output. - if (0 != fcntl(1, F_SETFD, FD_CLOEXEC)) - Warning("Can't stop flashrom from mucking up our output\n"); - if (ForkExecL(temp_dir_template, FLASHROM_PATH, "-i", "RW_GPT:rw_gpt", "-r", - NULL) != 0) { + + char *cwd = getcwd(NULL, 0); + if (!cwd) { + Error("Cannot get current directory.\n"); + return ret; + } + if (chdir(temp_dir_template) < 0) { + Error("Cannot change directory.\n"); + goto out_free; + } + const char *const argv[] = {FLASHROM_PATH, "-i", "RW_GPT:rw_gpt", "-r"}; + // Redirect stdout to /dev/null so that flashrom does not muck up cgpt's + // output. + if (subprocess_run(argv, &subprocess_null, &subprocess_null, NULL) != 0) { Error("Cannot exec flashrom to read from RW_GPT section.\n"); RemoveDir(temp_dir_template); } else { ret = 0; } + if (chdir(cwd) < 0) { + Error("Cannot change directory back to original.\n"); + goto out_free; + } - // Restore stdout flags - if (0 != fcntl(1, F_SETFD, fd_flags)) - Warning("Can't restore stdout flags\n"); +out_free: + free(cwd); return ret; } // Write "rw_gpt" back to NOR flash. We write the file in two parts for safety. +// TODO(b:184812319): Replace this function with flashrom_write. int WriteNorFlash(const char *dir) { int ret = 0; + ret++; if (split_gpt(dir, "rw_gpt") != 0) { Error("Cannot split rw_gpt in two.\n"); @@ -240,26 +256,43 @@ } ret++; int nr_fails = 0; - int fd_flags = fcntl(1, F_GETFD); - // Close stdout on exec so that flashrom does not muck up cgpt's output. - if (0 != fcntl(1, F_SETFD, FD_CLOEXEC)) - Warning("Can't stop flashrom from mucking up our output\n"); - if (ForkExecL(dir, FLASHROM_PATH, "-i", "RW_GPT_PRIMARY:rw_gpt_1", - "-w", "--fast-verify", NULL) != 0) { + + char *cwd = getcwd(NULL, 0); + if (!cwd) { + Error("Cannot get current directory.\n"); + return ret; + } + if (chdir(dir) < 0) { + Error("Cannot change directory.\n"); + goto out_free; + } + const char *const argv1[] = {FLASHROM_PATH, "-i", "RW_GPT_PRIMARY:rw_gpt_1", + "-w", "--noverify-all"}; + // Redirect stdout to /dev/null so that flashrom does not muck up cgpt's + // output. + if (subprocess_run(argv1, &subprocess_null, &subprocess_null, NULL) != 0) { Warning("Cannot write the 1st half of rw_gpt back with flashrom.\n"); nr_fails++; } - if (ForkExecL(dir, FLASHROM_PATH, "-i", "RW_GPT_SECONDARY:rw_gpt_2", - "-w", "--fast-verify", NULL) != 0) { + const char *const argv2[] = {FLASHROM_PATH, "-i", "RW_GPT_SECONDARY:rw_gpt_2", + "-w", "--noverify-all"}; + // Redirect stdout to /dev/null so that flashrom does not muck up cgpt's + // output. + if (subprocess_run(argv2, &subprocess_null, &subprocess_null, NULL) != 0) { Warning("Cannot write the 2nd half of rw_gpt back with flashrom.\n"); nr_fails++; } - if (0 != fcntl(1, F_SETFD, fd_flags)) - Warning("Can't restore stdout flags\n"); + if (chdir(cwd) < 0) { + Error("Cannot change directory back to original.\n"); + goto out_free; + } switch (nr_fails) { case 0: ret = 0; break; case 1: Warning("It might still be okay.\n"); break; case 2: Error("Cannot write both parts back with flashrom.\n"); break; } + +out_free: + free(cwd); return ret; } diff -Nru vboot-utils-0~R88-13597.B/.checkpatch.conf vboot-utils-0~R99-14469.B/.checkpatch.conf --- vboot-utils-0~R88-13597.B/.checkpatch.conf 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/.checkpatch.conf 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,21 @@ +# Not Linux, so don't expect a Linux tree. +--no-tree + +# Ignore aspects we don't follow here. +--ignore BLOCK_COMMENT_STYLE +--ignore C99_COMMENTS +--ignore CAMELCASE +--ignore CONFIG_DESCRIPTION +--ignore GLOBAL_INITIALISERS +--ignore INITIALISED_STATIC +--ignore LINE_SPACING +--ignore MACRO_WITH_FLOW_CONTROL +--ignore NEW_TYPEDEFS +--ignore OPEN_BRACE +--ignore PREFER_ALIGNED +--ignore PREFER_PACKED +--ignore PREFER_PRINTF +--ignore SPACING +--ignore SPDX_LICENSE_TAG +--ignore SPLIT_STRING +--ignore TRAILING_STATEMENTS diff -Nru vboot-utils-0~R88-13597.B/debian/changelog vboot-utils-0~R99-14469.B/debian/changelog --- vboot-utils-0~R88-13597.B/debian/changelog 2021-11-24 11:07:14.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/changelog 2022-02-14 13:32:56.000000000 +0000 @@ -1,8 +1,14 @@ -vboot-utils (0~R88-13597.B-1build1) jammy; urgency=medium +vboot-utils (0~R99-14469.B-1) unstable; urgency=medium - * No-change rebuild against openssl3 + * New upstream version 0~R99-14469.B + * Refresh patches + * Update debian/copyright + * Add missing build-dep libflashrom-dev + * Upgrade to use llvm-toolchain-13 (Closes: #1000916) + * Bump Standards-Version to 4.6.0 + * Use debhelper-compat 13 - -- Simon Chopin Wed, 24 Nov 2021 12:07:14 +0100 + -- Sophie Brun Mon, 14 Feb 2022 14:32:56 +0100 vboot-utils (0~R88-13597.B-1) unstable; urgency=medium diff -Nru vboot-utils-0~R88-13597.B/debian/control vboot-utils-0~R99-14469.B/debian/control --- vboot-utils-0~R88-13597.B/debian/control 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/control 2022-02-14 13:32:56.000000000 +0000 @@ -3,8 +3,9 @@ Priority: optional Maintainer: Sophie Brun Uploaders: RaphaĆ«l Hertzog -Build-Depends: debhelper-compat (= 12), - clang-11, +Build-Depends: debhelper-compat (= 13), + clang-13, + libflashrom-dev, libfuzzer-11-dev, liblzma-dev, libssl-dev, @@ -15,7 +16,7 @@ bc, # tests/external_rsa_signer.sh openssl -Standards-Version: 4.5.1 +Standards-Version: 4.6.0 Vcs-Git: https://salsa.debian.org/debian/vboot-utils.git Vcs-Browser: https://salsa.debian.org/debian/vboot-utils Homepage: https://chromium.googlesource.com/chromiumos/platform/vboot_reference diff -Nru vboot-utils-0~R88-13597.B/debian/copyright vboot-utils-0~R99-14469.B/debian/copyright --- vboot-utils-0~R88-13597.B/debian/copyright 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/copyright 2022-02-14 13:32:56.000000000 +0000 @@ -3,7 +3,7 @@ Source: https://chromium.googlesource.com/chromiumos/platform/vboot_reference/ Files: * -Copyright: (c) 2010-2019 The Chromium OS Authors. All rights reserved. +Copyright: (c) 2010-2021 The Chromium OS Authors. All rights reserved. License: BSD-3-clause Files: firmware/lib/cgptlib/crc32.c @@ -38,7 +38,7 @@ Files: debian/* Copyright: 2012 Antonio Terceiro 2012 Marcin Juszkiewicz - 2020 Sophie Brun + 2020-2022 Sophie Brun License: BSD-3-clause License: BSD-3-clause diff -Nru vboot-utils-0~R88-13597.B/debian/patches/0002-reduce-uname-down.patch vboot-utils-0~R99-14469.B/debian/patches/0002-reduce-uname-down.patch --- vboot-utils-0~R88-13597.B/debian/patches/0002-reduce-uname-down.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/0002-reduce-uname-down.patch 2022-02-14 13:32:56.000000000 +0000 @@ -11,10 +11,10 @@ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile -index f508a38..fd91c1d 100644 +index 4f0dee4..218437f 100644 --- a/Makefile +++ b/Makefile -@@ -84,6 +84,12 @@ endif +@@ -86,6 +86,12 @@ endif # Architecture detection _machname := $(shell uname -m) diff -Nru vboot-utils-0~R88-13597.B/debian/patches/0006-add-CPPFLAGS-LDFLAGS.patch vboot-utils-0~R99-14469.B/debian/patches/0006-add-CPPFLAGS-LDFLAGS.patch --- vboot-utils-0~R88-13597.B/debian/patches/0006-add-CPPFLAGS-LDFLAGS.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/0006-add-CPPFLAGS-LDFLAGS.patch 2022-02-14 13:32:56.000000000 +0000 @@ -9,10 +9,10 @@ 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile -index fd91c1d..9e64fd7 100644 +index 218437f..acb379d 100644 --- a/Makefile +++ b/Makefile -@@ -140,6 +140,7 @@ COMMON_FLAGS := -pipe ${WERROR} -Wall -Wstrict-prototypes -Wtype-limits \ +@@ -142,6 +142,7 @@ COMMON_FLAGS := -pipe ${WERROR} -Wall -Wstrict-prototypes -Wtype-limits \ # FIRMWARE_ARCH is defined if compiling for a firmware target # (coreboot or depthcharge). @@ -20,7 +20,7 @@ ifeq (${FIRMWARE_ARCH},arm) CC ?= armv7a-cros-linux-gnueabihf-gcc CFLAGS ?= -march=armv5 -fno-common -ffixed-r8 -mfloat-abi=hard -marm -@@ -1110,11 +1111,11 @@ ${BUILD}/%: ${BUILD}/%.o ${OBJS} ${LIBS} +@@ -1137,11 +1138,11 @@ ${BUILD}/%: ${BUILD}/%.o ${OBJS} ${LIBS} ${BUILD}/%.o: %.c @${PRINTF} " CC $(subst ${BUILD}/,,$@)\n" diff -Nru vboot-utils-0~R88-13597.B/debian/patches/0008-fix-building-on-arm64.patch vboot-utils-0~R99-14469.B/debian/patches/0008-fix-building-on-arm64.patch --- vboot-utils-0~R88-13597.B/debian/patches/0008-fix-building-on-arm64.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/0008-fix-building-on-arm64.patch 2022-02-14 13:32:56.000000000 +0000 @@ -11,10 +11,10 @@ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile -index 9e64fd7..fa0d512 100644 +index acb379d..6f13643 100644 --- a/Makefile +++ b/Makefile -@@ -87,6 +87,9 @@ _machname := $(shell uname -m) +@@ -89,6 +89,9 @@ _machname := $(shell uname -m) ifneq (,$(findstring arm,${_machname})) override _machname := arm endif diff -Nru vboot-utils-0~R88-13597.B/debian/patches/0012-fix-spelling-errors.patch vboot-utils-0~R99-14469.B/debian/patches/0012-fix-spelling-errors.patch --- vboot-utils-0~R88-13597.B/debian/patches/0012-fix-spelling-errors.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/0012-fix-spelling-errors.patch 2022-02-14 13:32:56.000000000 +0000 @@ -10,10 +10,10 @@ 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c -index 83a76f8..822a06c 100644 +index 7268bee..f4964f1 100644 --- a/futility/cmd_vbutil_kernel.c +++ b/futility/cmd_vbutil_kernel.c -@@ -111,7 +111,7 @@ static const char usage[] = +@@ -110,7 +110,7 @@ static const char usage[] = " --signprivate Private key to sign kernel data,\n" " in .vbprivk format\n" " --oldblob Previously packed kernel blob\n" diff -Nru vboot-utils-0~R88-13597.B/debian/patches/add-missing-flags-pie.patch vboot-utils-0~R99-14469.B/debian/patches/add-missing-flags-pie.patch --- vboot-utils-0~R88-13597.B/debian/patches/add-missing-flags-pie.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/add-missing-flags-pie.patch 2022-02-14 13:32:56.000000000 +0000 @@ -2,21 +2,21 @@ Date: Tue, 11 Feb 2020 17:02:17 +0100 Subject: Add missing flags pie -Last-Update: 2020-02-11 +Last-Update: 2022-02-11 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile -index 1aa4974..c675709 100644 +index 85e36a8..c75c10f 100644 --- a/Makefile +++ b/Makefile -@@ -139,7 +139,7 @@ COMMON_FLAGS := -pipe -Wall -Wstrict-prototypes -Wtype-limits \ - -Wundef -Wmissing-prototypes -Wno-trigraphs -Wredundant-decls -Wshadow \ - -Wwrite-strings -Wstrict-aliasing -Wdate-time -Wno-unknown-warning \ - -Wno-address-of-packed-member -ffunction-sections -fdata-sections \ -- -Wimplicit-fallthrough -Wformat -Wno-format-security ${DEBUG_FLAGS} -+ -Wimplicit-fallthrough -Wformat -Wno-format-security -pie ${DEBUG_FLAGS} +@@ -181,7 +181,7 @@ COMMON_FLAGS += $(call test_ccflag,-Wno-address-of-packed-member) + COMMON_FLAGS += $(call test_ccflag,-Wno-unknown-warning) - # FIRMWARE_ARCH is defined if compiling for a firmware target - # (coreboot or depthcharge). + # Needs -Wl because LD is actually set to CC by default. +-LDFLAGS += -Wl,--gc-sections ++LDFLAGS += -Wl,--gc-sections -pie + + ifneq ($(filter-out 0,${DEBUG})$(filter-out 0,${TEST_PRINT}),) + CFLAGS += -DVBOOT_DEBUG diff -Nru vboot-utils-0~R88-13597.B/debian/patches/dont-build-with-werror.patch vboot-utils-0~R99-14469.B/debian/patches/dont-build-with-werror.patch --- vboot-utils-0~R88-13597.B/debian/patches/dont-build-with-werror.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/dont-build-with-werror.patch 2022-02-14 13:32:56.000000000 +0000 @@ -8,15 +8,15 @@ 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile -index fa0d512..1aa4974 100644 +index 6f13643..85e36a8 100644 --- a/Makefile +++ b/Makefile -@@ -135,7 +135,7 @@ endif - DEBUG_FLAGS := $(if ${DEBUG},-g -O0,-g -Os) +@@ -137,7 +137,7 @@ endif + DEBUG_FLAGS := $(if $(filter-out 0,${DEBUG}),-g -Og,-g -Os) WERROR := -Werror FIRMWARE_FLAGS := -nostdinc -ffreestanding -fno-builtin -fno-stack-protector -COMMON_FLAGS := -pipe ${WERROR} -Wall -Wstrict-prototypes -Wtype-limits \ +COMMON_FLAGS := -pipe -Wall -Wstrict-prototypes -Wtype-limits \ -Wundef -Wmissing-prototypes -Wno-trigraphs -Wredundant-decls -Wshadow \ - -Wwrite-strings -Wstrict-aliasing -Wdate-time -Wno-unknown-warning \ - -Wno-address-of-packed-member -ffunction-sections -fdata-sections \ + -Wwrite-strings -Wstrict-aliasing -Wdate-time \ + -ffunction-sections -fdata-sections \ diff -Nru vboot-utils-0~R88-13597.B/debian/patches/treat-i386-as-x86.patch vboot-utils-0~R99-14469.B/debian/patches/treat-i386-as-x86.patch --- vboot-utils-0~R88-13597.B/debian/patches/treat-i386-as-x86.patch 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/patches/treat-i386-as-x86.patch 2022-02-14 13:32:56.000000000 +0000 @@ -12,10 +12,10 @@ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile -index c675709..2ff6de8 100644 +index c75c10f..8930eb0 100644 --- a/Makefile +++ b/Makefile -@@ -93,6 +93,9 @@ endif +@@ -95,6 +95,9 @@ endif ifneq (,$(findstring i686,${_machname})) override _machname := x86 endif diff -Nru vboot-utils-0~R88-13597.B/debian/rules vboot-utils-0~R99-14469.B/debian/rules --- vboot-utils-0~R88-13597.B/debian/rules 2020-12-01 09:59:21.000000000 +0000 +++ vboot-utils-0~R99-14469.B/debian/rules 2022-02-14 13:32:56.000000000 +0000 @@ -1,7 +1,7 @@ #!/usr/bin/make -f export DEB_BUILD_MAINT_OPTIONS = hardening=+all -export CC = clang-11 +export CC = clang-13 export _machname = $(DEB_HOST_ARCH) override_dh_auto_build: diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2api.c vboot-utils-0~R99-14469.B/firmware/2lib/2api.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2api.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2api.c 2022-02-11 14:46:09.000000000 +0000 @@ -15,7 +15,6 @@ #include "2sha.h" #include "2sysincludes.h" #include "2tpm_bootmode.h" -#include "vb2_common.h" vb2_error_t vb2api_fw_phase1(struct vb2_context *ctx) { @@ -60,28 +59,19 @@ if (rv) vb2api_fail(ctx, VB2_RECOVERY_GBB_HEADER, rv); + /* Check for dev switch */ + rv = vb2_check_dev_switch(ctx); + if (rv) + vb2api_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv); + /* * Check for recovery. Note that this function returns void, since any * errors result in requesting recovery. That's also why we don't - * return error from failures in the preceding two steps; those - * failures simply cause us to detect recovery mode here. + * return error from failures in the preceding steps; those failures + * simply cause us to detect recovery mode here. */ vb2_check_recovery(ctx); - /* Check for dev switch */ - rv = vb2_check_dev_switch(ctx); - if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { - /* - * Error in dev switch processing, and we weren't already - * headed for recovery mode. Reboot into recovery mode, since - * it's too late to handle those errors this boot, and we need - * to take a different path through the dev switch checking - * code in that case. - */ - vb2api_fail(ctx, VB2_RECOVERY_DEV_SWITCH, rv); - return rv; - } - /* * Check for possible reasons to ask the firmware to make display * available. VB2_CONTEXT_RECOVERY_MODE may have been set above by @@ -99,6 +89,9 @@ if (ctx->flags & VB2_CONTEXT_DISPLAY_INIT) sd->flags |= VB2_SD_FLAG_DISPLAY_AVAILABLE; + /* Decide the boot mode */ + vb2_set_boot_mode(ctx); + /* Return error if recovery is needed */ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { /* Always clear RAM when entering recovery mode */ @@ -276,7 +269,7 @@ sd->hash_tag = tag; sd->hash_remaining_size = pre->body_signature.data_size; - if (!(pre->flags & VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO)) { + if (vb2_hwcrypto_allowed(ctx)) { vb2_error_t rv = vb2ex_hwcrypto_digest_init( key.hash_alg, pre->body_signature.data_size); if (!rv) { @@ -291,7 +284,7 @@ VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n", key.hash_alg); } else { - VB2_DEBUG("HW crypto forbidden by preamble, using SW\n"); + VB2_DEBUG("HW crypto forbidden by TPM flag, using SW\n"); } return vb2_digest_init(dc, key.hash_alg); @@ -355,7 +348,7 @@ vb2_member_of(sd, sd->data_key_offset), sd->data_key_size)); - key.allow_hwcrypto = vb2_hwcrypto_rsa_allowed(ctx); + key.allow_hwcrypto = vb2_hwcrypto_allowed(ctx); /* * Check digest vs. signature. Note that this destroys the signature. diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2auxfw_sync.c vboot-utils-0~R99-14469.B/firmware/2lib/2auxfw_sync.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2auxfw_sync.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2auxfw_sync.c 2022-02-11 14:46:09.000000000 +0000 @@ -28,40 +28,6 @@ } /** - * Update the specified auxfw and verify the update succeeded. - * - * @param ctx Vboot2 context - * @return VB2_SUCCESS, or non-zero error code. - */ -static vb2_error_t update_auxfw(struct vb2_context *ctx) -{ - vb2_error_t rv; - - VB2_DEBUG("Updating auxfw\n"); - - /* - * The underlying platform is expected to know how and where to find the - * firmware image for all auxfw devices. - */ - rv = vb2ex_auxfw_update(); - if (rv != VB2_SUCCESS) { - VB2_DEBUG("vb2ex_auxfw_update() returned %d\n", rv); - - /* - * The device may need a reboot. It may need to unprotect the - * region before updating, or may need to reboot after updating. - * Either way, it's not an error requiring recovery mode. - * - * If we fail for any other reason, trigger recovery mode. - */ - if (rv != VB2_REQUEST_REBOOT_EC_TO_RO) - vb2api_fail(ctx, VB2_RECOVERY_AUXFW_UPDATE, rv); - } - - return rv; -} - -/** * Decides if auxfw sync is allowed to be performed. * * If sync is allowed, invokes the external callback, @@ -90,7 +56,8 @@ VB2_TRY(auxfw_sync_check_update(ctx, &fw_update)); if (fw_update > VB2_AUXFW_NO_UPDATE) { - VB2_TRY(update_auxfw(ctx)); + VB2_DEBUG("Updating auxfw\n"); + VB2_TRY(vb2ex_auxfw_update(), ctx, VB2_RECOVERY_AUXFW_UPDATE); /* * auxfw update is applied successfully. Request EC reboot to * RO, so that the chips that had FW update get reset to a diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2common.c vboot-utils-0~R99-14469.B/firmware/2lib/2common.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2common.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2common.c 2022-02-11 14:46:09.000000000 +0000 @@ -8,8 +8,6 @@ #include "2common.h" #include "2rsa.h" -#include "2sha.h" -#include "2sysincludes.h" vb2_error_t vb2_safe_memcmp(const void *s1, const void *s2, size_t size) { @@ -190,9 +188,9 @@ const struct vb2_workbuf *wb) { struct vb2_workbuf wblocal = *wb; - struct vb2_digest_context *dc; uint8_t *digest; uint32_t digest_size; + vb2_error_t rv; if (sig->data_size > size) { VB2_DEBUG("Data buffer smaller than length of signed data.\n"); @@ -208,164 +206,26 @@ if (!digest) return VB2_ERROR_VDATA_WORKBUF_DIGEST; - /* Hashing requires temp space for the context */ - dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc)); - if (!dc) - return VB2_ERROR_VDATA_WORKBUF_HASHING; - - VB2_TRY(vb2_digest_init(dc, key->hash_alg)); - VB2_TRY(vb2_digest_extend(dc, data, sig->data_size)); - VB2_TRY(vb2_digest_finalize(dc, digest, digest_size)); - - vb2_workbuf_free(&wblocal, sizeof(*dc)); - - return vb2_verify_digest(key, sig, digest, &wblocal); -} - -vb2_error_t vb2_check_keyblock(const struct vb2_keyblock *block, uint32_t size, - const struct vb2_signature *sig) -{ - if(size < sizeof(*block)) { - VB2_DEBUG("Not enough space for keyblock header.\n"); - return VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER; - } - - if (memcmp(block->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE)) { - VB2_DEBUG("Not a valid verified boot keyblock.\n"); - return VB2_ERROR_KEYBLOCK_MAGIC; - } - - if (block->header_version_major != VB2_KEYBLOCK_VERSION_MAJOR) { - VB2_DEBUG("Incompatible keyblock header version.\n"); - return VB2_ERROR_KEYBLOCK_HEADER_VERSION; - } - - if (size < block->keyblock_size) { - VB2_DEBUG("Not enough data for keyblock.\n"); - return VB2_ERROR_KEYBLOCK_SIZE; - } - - if (vb2_verify_signature_inside(block, block->keyblock_size, sig)) { - VB2_DEBUG("Keyblock signature off end of block\n"); - return VB2_ERROR_KEYBLOCK_SIG_OUTSIDE; - } - - /* Make sure advertised signature data sizes are valid. */ - if (block->keyblock_size < sig->data_size) { - VB2_DEBUG("Signature calculated past end of block\n"); - return VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH; - } - - /* Verify we signed enough data */ - if (sig->data_size < sizeof(struct vb2_keyblock)) { - VB2_DEBUG("Didn't sign enough data\n"); - return VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE; - } - - /* Verify data key is inside the block and inside signed data */ - if (vb2_verify_packed_key_inside(block, block->keyblock_size, - &block->data_key)) { - VB2_DEBUG("Data key off end of keyblock\n"); - return VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE; - } - if (vb2_verify_packed_key_inside(block, sig->data_size, - &block->data_key)) { - VB2_DEBUG("Data key off end of signed data\n"); - return VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED; - } - - return VB2_SUCCESS; -} - -vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - struct vb2_signature *sig = &block->keyblock_signature; - vb2_error_t rv; - - /* Validity check keyblock before attempting signature check of data */ - VB2_TRY(vb2_check_keyblock(block, size, sig)); - - VB2_DEBUG("Checking keyblock signature...\n"); - rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb); - if (rv) { - VB2_DEBUG("Invalid keyblock signature.\n"); - return VB2_ERROR_KEYBLOCK_SIG_INVALID; - } - - /* Success */ - return VB2_SUCCESS; -} - -vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble, - uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - struct vb2_signature *sig = &preamble->preamble_signature; - - VB2_DEBUG("Verifying preamble.\n"); - - /* Validity checks before attempting signature of data */ - if(size < sizeof(*preamble)) { - VB2_DEBUG("Not enough data for preamble header\n"); - return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER; - } - if (preamble->header_version_major != - VB2_FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) { - VB2_DEBUG("Incompatible firmware preamble header version.\n"); - return VB2_ERROR_PREAMBLE_HEADER_VERSION; - } - - if (preamble->header_version_minor < 1) { - VB2_DEBUG("Only preamble header 2.1+ supported\n"); - return VB2_ERROR_PREAMBLE_HEADER_OLD; - } - - if (size < preamble->preamble_size) { - VB2_DEBUG("Not enough data for preamble.\n"); - return VB2_ERROR_PREAMBLE_SIZE; - } - - /* Check signature */ - if (vb2_verify_signature_inside(preamble, preamble->preamble_size, - sig)) { - VB2_DEBUG("Preamble signature off end of preamble\n"); - return VB2_ERROR_PREAMBLE_SIG_OUTSIDE; - } - - /* Make sure advertised signature data sizes are valid. */ - if (preamble->preamble_size < sig->data_size) { - VB2_DEBUG("Signature calculated past end of the block\n"); - return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH; - } - - if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) { - VB2_DEBUG("Preamble signature validation failed\n"); - return VB2_ERROR_PREAMBLE_SIG_INVALID; - } - - /* Verify we signed enough data */ - if (sig->data_size < sizeof(struct vb2_fw_preamble)) { - VB2_DEBUG("Didn't sign enough data\n"); - return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE; - } - - /* Verify body signature is inside the signed data */ - if (vb2_verify_signature_inside(preamble, sig->data_size, - &preamble->body_signature)) { - VB2_DEBUG("Firmware body signature off end of preamble\n"); - return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE; - } - - /* Verify kernel subkey is inside the signed data */ - if (vb2_verify_packed_key_inside(preamble, sig->data_size, - &preamble->kernel_subkey)) { - VB2_DEBUG("Kernel subkey off end of preamble\n"); - return VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE; + if (key->allow_hwcrypto) { + rv = vb2ex_hwcrypto_digest_init(key->hash_alg, sig->data_size); + if (rv == VB2_SUCCESS) { + VB2_DEBUG("Using HW crypto engine for hash_alg %d\n", key->hash_alg); + VB2_TRY(vb2ex_hwcrypto_digest_extend(data, sig->data_size)); + VB2_TRY(vb2ex_hwcrypto_digest_finalize(digest, digest_size)); + } else if (rv == VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED) { + VB2_DEBUG("HW crypto for hash_alg %d not supported, using SW\n", + key->hash_alg); + VB2_TRY(vb2_digest_buffer(data, sig->data_size, key->hash_alg, + digest, digest_size)); + } else { + VB2_DEBUG("HW crypto init error : %d\n", rv); + return rv; + } + } else { + VB2_DEBUG("HW crypto forbidden by TPM flag, using SW\n"); + VB2_TRY(vb2_digest_buffer(data, sig->data_size, key->hash_alg, + digest, digest_size)); } - /* Success */ - return VB2_SUCCESS; + return vb2_verify_digest(key, sig, digest, &wblocal); } diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2ec_sync.c vboot-utils-0~R99-14469.B/firmware/2lib/2ec_sync.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2ec_sync.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2ec_sync.c 2022-02-11 14:46:09.000000000 +0000 @@ -160,10 +160,10 @@ struct vb2_shared_data *sd = vb2_get_sd(ctx); int in_rw = 0; /* - * We don't use vb2ex_ec_trusted, which checks EC_IN_RW. It is - * controlled by cr50 but on some platforms, cr50 can't know when a EC - * resets. So, we trust what EC-RW says. If it lies it's in RO, we'll - * flash RW while it's in RW. + * We don't use VB2_CONTEXT_EC_TRUSTED, which checks if not EC_IN_RW. + * It is controlled by cr50 but on some platforms, cr50 can't know when + * a EC resets. So, we trust what EC-RW says. If it lies it's in RO, + * we'll flash RW while it's in RW. */ /* If we couldn't determine where the EC was, reboot to recovery. */ VB2_TRY(vb2ex_ec_running_rw(&in_rw), @@ -212,6 +212,10 @@ return VB2_REQUEST_REBOOT_EC_TO_RO; } + /* We no longer trust the EC once it is already in RW or tries to jump + to RW. */ + ctx->flags &= ~VB2_CONTEXT_EC_TRUSTED; + /* Tell EC to jump to RW. It should already be in RW for EFS2. */ if (!(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW)) { VB2_DEBUG("jumping to EC-RW\n"); diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2firmware.c vboot-utils-0~R99-14469.B/firmware/2lib/2firmware.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2firmware.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2firmware.c 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,237 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Misc functions which need access to vb2_context but are not public APIs + */ + +#include "2api.h" +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2rsa.h" +#include "2secdata.h" +#include "2sha.h" +#include "2sysincludes.h" + +vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + struct vb2_workbuf wb; + + uint8_t *key_data; + uint32_t key_size; + struct vb2_public_key root_key; + + struct vb2_keyblock *kb; + uint32_t block_size; + + vb2_error_t rv = VB2_SUCCESS; + + vb2_workbuf_from_ctx(ctx, &wb); + + /* Read the root key */ + key_size = gbb->rootkey_size; + key_data = vb2_workbuf_alloc(&wb, key_size); + if (!key_data) + return VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY; + + VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB, gbb->rootkey_offset, + key_data, key_size)); + + /* Unpack the root key */ + VB2_TRY(vb2_unpack_key_buffer(&root_key, key_data, key_size)); + + root_key.allow_hwcrypto = vb2_hwcrypto_allowed(ctx); + + /* Load the firmware keyblock header after the root key */ + kb = vb2_workbuf_alloc(&wb, sizeof(*kb)); + if (!kb) + return VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER; + + VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, + kb, sizeof(*kb))); + + block_size = kb->keyblock_size; + + /* + * Load the entire keyblock, now that we know how big it is. Note that + * we're loading the entire keyblock instead of just the piece after + * the header. That means we re-read the header. But that's a tiny + * amount of data, and it makes the code much more straightforward. + */ + kb = vb2_workbuf_realloc(&wb, sizeof(*kb), block_size); + if (!kb) + return VB2_ERROR_FW_KEYBLOCK_WORKBUF; + + VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, block_size)); + + /* Verify the keyblock */ + VB2_TRY(vb2_verify_keyblock(kb, block_size, &root_key, &wb), + ctx, VB2_RECOVERY_FW_KEYBLOCK); + + /* Key version is the upper 16 bits of the composite firmware version */ + if (kb->data_key.key_version > VB2_MAX_KEY_VERSION) + rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE; + if (!rv && kb->data_key.key_version < (sd->fw_version_secdata >> 16)) { + if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK) + VB2_DEBUG("Ignoring FW key rollback due to GBB flag\n"); + else + rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK; + } + if (rv) { + vb2api_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv); + return rv; + } + + sd->fw_version = kb->data_key.key_version << 16; + + /* Preamble follows the keyblock in the vblock. */ + sd->vblock_preamble_offset = kb->keyblock_size; + + /* + * Save the data key in the work buffer. We'll overwrite the root key + * we read above. That's ok, because now that we have the data key we + * no longer need the root key. First, let's double-check that it is + * well-formed though (although the keyblock was signed anyway). + */ + VB2_TRY(vb2_verify_packed_key_inside(kb, block_size, &kb->data_key)); + + /* Save the future offset and size while kb->data_key is still valid. + The check above made sure that key_offset and key_size are valid. */ + sd->data_key_offset = vb2_offset_of(sd, key_data); + sd->data_key_size = kb->data_key.key_offset + kb->data_key.key_size; + + /* + * Use memmove() instead of memcpy(). In theory, the destination will + * never overlap because with the source because the root key is likely + * to be at least as large as the data key, but there's no harm here in + * being paranoid. Make sure we immediately invalidate 'kb' after the + * move to guarantee we won't try to access it anymore. + */ + memmove(key_data, &kb->data_key, sd->data_key_size); + kb = NULL; + + /* + * Data key will persist in the workbuf after we return. + * + * Work buffer now contains: + * - vb2_shared_data + * - packed firmware data key + */ + vb2_set_workbuf_used(ctx, sd->data_key_offset + sd->data_key_size); + + return VB2_SUCCESS; +} + +vb2_error_t vb2_load_fw_preamble(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + struct vb2_workbuf wb; + + uint8_t *key_data = vb2_member_of(sd, sd->data_key_offset); + uint32_t key_size = sd->data_key_size; + struct vb2_public_key data_key; + + /* Preamble goes in the next unused chunk of work buffer */ + struct vb2_fw_preamble *pre; + uint32_t pre_size; + + vb2_error_t rv = VB2_SUCCESS; + + vb2_workbuf_from_ctx(ctx, &wb); + + /* Unpack the firmware data key */ + if (!sd->data_key_size) + return VB2_ERROR_FW_PREAMBLE2_DATA_KEY; + + VB2_TRY(vb2_unpack_key_buffer(&data_key, key_data, key_size)); + + data_key.allow_hwcrypto = vb2_hwcrypto_allowed(ctx); + + /* Load the firmware preamble header */ + pre = vb2_workbuf_alloc(&wb, sizeof(*pre)); + if (!pre) + return VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER; + + VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, + sd->vblock_preamble_offset, + pre, sizeof(*pre))); + + pre_size = pre->preamble_size; + + /* Load the entire firmware preamble, now that we know how big it is */ + pre = vb2_workbuf_realloc(&wb, sizeof(*pre), pre_size); + if (!pre) + return VB2_ERROR_FW_PREAMBLE2_WORKBUF; + + VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, + sd->vblock_preamble_offset, + pre, pre_size)); + + /* Work buffer now contains the data subkey data and the preamble */ + + /* Verify the preamble */ + VB2_TRY(vb2_verify_fw_preamble(pre, pre_size, &data_key, &wb), + ctx, VB2_RECOVERY_FW_PREAMBLE); + + /* + * Firmware version is the lower 16 bits of the composite firmware + * version. + */ + if (pre->firmware_version > VB2_MAX_PREAMBLE_VERSION) + rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE; + /* Combine with the key version from vb2_load_fw_keyblock() */ + sd->fw_version |= pre->firmware_version; + if (!rv && sd->fw_version < sd->fw_version_secdata) { + if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK) + VB2_DEBUG("Ignoring FW rollback due to GBB flag\n"); + else + rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK; + } + if (rv) { + vb2api_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv); + return rv; + } + + /* + * If this is a newer version than in secure storage, and we + * successfully booted the same slot last boot, roll forward the + * version in secure storage. + * + * Note that this happens before we've verified the firmware data this + * boot; we're relying on the indicator that the last boot was + * successful. That's ok, because even if the firmware data has a + * valid hash, the only way we can know if it's functional is to trust + * the status from the last boot. + */ + if (sd->fw_version > sd->fw_version_secdata && + sd->last_fw_slot == sd->fw_slot && + sd->last_fw_result == VB2_FW_RESULT_SUCCESS) { + sd->fw_version_secdata = sd->fw_version; + vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, + sd->fw_version); + } + + /* Keep track of where we put the preamble */ + sd->preamble_offset = vb2_offset_of(sd, pre); + sd->preamble_size = pre_size; + + /* + * Preamble will persist in work buffer after we return. + * + * Work buffer now contains: + * - vb2_shared_data + * - vb2_gbb_header + * - packed firmware data key + * - firmware preamble + * + * TODO: we could move the preamble down over the firmware data key + * since we don't need it anymore. + */ + vb2_set_workbuf_used(ctx, sd->preamble_offset + pre_size); + + return VB2_SUCCESS; +} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2kernel.c vboot-utils-0~R99-14469.B/firmware/2lib/2kernel.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -11,8 +11,7 @@ #include "2nvstorage.h" #include "2rsa.h" #include "2secdata.h" -#include "vb2_common.h" -#include "vboot_kernel.h" +#include "vboot_api.h" /** * Reset any NVRAM requests. @@ -148,7 +147,7 @@ flags = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS); flags &= ~VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_DISABLED; flags |= VB2_SECDATA_KERNEL_FLAG_PHONE_RECOVERY_UI_DISABLED; - flags |= VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED; + flags &= ~VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED; flags |= VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED; vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, flags); } @@ -158,12 +157,14 @@ vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS); sd->kernel_version = sd->kernel_version_secdata; + vb2_fill_dev_boot_flags(ctx); + /* Find the key to use to verify the kernel keyblock */ if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { /* Load recovery key from GBB. */ rv = vb2_gbb_read_recovery_key(ctx, &packed_key, NULL, &wb); if (rv) { - if (vb2_allow_recovery(ctx)) + if (ctx->boot_mode != VB2_BOOT_MODE_BROKEN_SCREEN) VB2_DIE("GBB read recovery key failed.\n"); else /* diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2misc.c vboot-utils-0~R99-14469.B/firmware/2lib/2misc.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2misc.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2misc.c 2022-02-11 14:46:09.000000000 +0000 @@ -15,7 +15,6 @@ #include "2sha.h" #include "2struct.h" #include "2sysincludes.h" -#include "vb2_common.h" #include "vboot_api.h" #include "vboot_struct.h" @@ -155,7 +154,6 @@ else /* Recovery was forced. Override recovery reason */ sd->recovery_reason = VB2_RECOVERY_RO_MANUAL; - sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY; } /* If recovery reason is non-zero, tell caller we need recovery mode */ @@ -165,6 +163,8 @@ sd->recovery_reason, vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE)); } + + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; } vb2_error_t vb2_fw_init_gbb(struct vb2_context *ctx) @@ -251,7 +251,7 @@ * developer mode. */ vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 0); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 0); + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 0); vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 0); vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, 0); } @@ -376,8 +376,14 @@ return VB2_SUCCESS; } -void vb2_enable_developer_mode(struct vb2_context *ctx) +vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx) { + if (ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) { + VB2_DEBUG("ERROR: Can only enable developer mode from manual " + "recovery mode\n"); + return VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED; + } + uint32_t flags; VB2_DEBUG("Enabling developer mode...\n"); @@ -386,34 +392,26 @@ flags |= VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE; vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_FLAGS, flags); - if (BOOT_EXTERNAL_ON_DEV) - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - VB2_DEBUG("Mode change will take effect on next reboot\n"); + + return VB2_SUCCESS; } -test_mockable -int vb2_allow_recovery(struct vb2_context *ctx) +vb2_error_t vb2api_disable_developer_mode(struct vb2_context *ctx) { - if (ctx->flags & VB2_CONTEXT_NO_BOOT) - return 0; - - /* VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY forces this to always return - true. */ - if (vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY) - return 1; + if (vb2api_gbb_get_flags(ctx) & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { + VB2_DEBUG("ERROR: dev mode forced by GBB flag\n"); + return VB2_ERROR_API_DISABLE_DEV_NOT_ALLOWED; + } - /* - * If EC is in RW, it implies recovery wasn't manually requested. - * On some platforms, EC_IN_RW can't be reset by the EC, thus, this may - * return false (=RW). That's ok because if recovery is manual, we will - * get the right signal and that's the case we care about. - */ - if (!vb2ex_ec_trusted()) - return 0; + VB2_DEBUG("Leaving dev mode\n"); + vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); + return VB2_SUCCESS; +} - /* Now we confidently check the recovery switch state at boot */ - return !!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_MANUAL_RECOVERY); +void vb2api_request_diagnostics(struct vb2_context *ctx) { + vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); + VB2_DEBUG("Diagnostics requested\n"); } void vb2_clear_recovery(struct vb2_context *ctx) @@ -427,13 +425,13 @@ reason, subcode, vb2_get_recovery_reason_string(reason)); - /* Clear recovery request for both manual and non-manual. */ + /* Clear recovery request for both the manual recovery and the broken + screen. */ vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_NOT_REQUESTED); vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 0); - /* But stow recovery reason as subcode for non-manual recovery. */ - if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && - !vb2_allow_recovery(ctx)) { + /* But stow recovery reason as subcode for the broken screen. */ + if (ctx->boot_mode == VB2_BOOT_MODE_BROKEN_SCREEN) { VB2_DEBUG("Stow recovery reason as subcode (%#x)\n", sd->recovery_reason); vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, sd->recovery_reason); @@ -460,6 +458,11 @@ return vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); } +void vb2api_set_locale_id(struct vb2_context *ctx, uint32_t locale_id) +{ + vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, locale_id); +} + void vb2api_export_vbsd(struct vb2_context *ctx, void *dest) { struct vb2_shared_data *sd = vb2_get_sd(ctx); @@ -528,51 +531,43 @@ { struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) - return VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY; + if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_ALTFW) + return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW; switch (vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT)) { case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL: - if (vb2_dev_boot_external_allowed(ctx)) + if (ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED) return VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; break; - case VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY: - if (vb2_dev_boot_legacy_allowed(ctx)) - return VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY; + case VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW: + if (ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED) + return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW; break; } return VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL; } -int vb2_dev_boot_allowed(struct vb2_context *ctx) +void vb2_fill_dev_boot_flags(struct vb2_context *ctx) { struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) - return !!(gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON); - - return 1; -} - -int vb2_dev_boot_legacy_allowed(struct vb2_context *ctx) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - - return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY) || - (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) || - vb2_secdata_fwmp_get_flag(ctx, - VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY); -} - -int vb2_dev_boot_external_allowed(struct vb2_context *ctx) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - - return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) || - (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) || - vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL); + if (!vb2_secdata_fwmp_get_flag(ctx, + VB2_SECDATA_FWMP_DEV_DISABLE_BOOT) || + (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)) + ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALLOWED; + + if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) || + (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) || + vb2_secdata_fwmp_get_flag(ctx, + VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL)) + ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED; + + if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW) || + (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW) || + vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW)) + ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED; } int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx) @@ -661,9 +656,9 @@ i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL); DEBUG_INFO_APPEND("\ndev_boot_usb: %d", i); - /* Add dev_boot_legacy flag */ - i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY); - DEBUG_INFO_APPEND("\ndev_boot_legacy: %d", i); + /* Add dev_boot_altfw flag */ + i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW); + DEBUG_INFO_APPEND("\ndev_boot_altfw: %d", i); /* Add dev_default_boot flag */ i = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); @@ -713,3 +708,35 @@ buf[DEBUG_INFO_MAX_LENGTH] = '\0'; return buf; } + +void vb2_set_boot_mode(struct vb2_context *ctx) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); + struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); + + /* Cast boot mode to non-constant and assign */ + enum vb2_boot_mode *boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode; + *boot_mode = VB2_BOOT_MODE_NORMAL; + + /* + * The only way to pass this check and proceed to the recovery process + * is to physically request a recovery (a.k.a. manual recovery). All + * other recovery requests including manual recovery requested by a + * (compromised) host will end up with 'broken' screen. + */ + if ((ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) && + !(ctx->flags & VB2_CONTEXT_NO_BOOT) && + (ctx->flags & VB2_CONTEXT_EC_TRUSTED)) { + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + } else if (sd->recovery_reason) { + if (gbb->flags & VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY) + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + else + *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN; + } else if (vb2api_diagnostic_ui_enabled(ctx) && + vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) { + *boot_mode = VB2_BOOT_MODE_DIAGNOSTICS; + } else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) { + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + } +} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2nvstorage.c vboot-utils-0~R99-14469.B/firmware/2lib/2nvstorage.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2nvstorage.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2nvstorage.c 2022-02-11 14:46:09.000000000 +0000 @@ -80,6 +80,11 @@ sd->status |= VB2_SD_STATUS_NV_REINIT; /* TODO: unit test for status flag being set */ + } else { +#ifndef CHROMEOS_ENVIRONMENT + /* Always clear this on first reboot that didn't need reinit. */ + vb2_nv_set(ctx, VB2_NV_FIRMWARE_SETTINGS_RESET, 0); +#endif } sd->status |= VB2_SD_STATUS_NV_INIT; @@ -145,7 +150,7 @@ case VB2_NV_DEV_BOOT_EXTERNAL: return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_EXTERNAL); - case VB2_NV_DEV_BOOT_LEGACY: + case VB2_NV_DEV_BOOT_ALTFW: return GETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY); case VB2_NV_DEV_BOOT_SIGNED_ONLY: @@ -209,6 +214,9 @@ return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_POST_EC_SYNC_DELAY); + case VB2_NV_MINIOS_PRIORITY: + return GETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_MINIOS_PRIORITY); + case VB2_NV_DEPRECATED_DEV_BOOT_FASTBOOT_FULL_CAP: case VB2_NV_DEPRECATED_FASTBOOT_UNLOCK_IN_FW: case VB2_NV_DEPRECATED_ENABLE_ALT_OS_REQUEST: @@ -331,7 +339,7 @@ SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_EXTERNAL); break; - case VB2_NV_DEV_BOOT_LEGACY: + case VB2_NV_DEV_BOOT_ALTFW: SETBIT(VB2_NV_OFFS_DEV, VB2_NV_DEV_FLAG_LEGACY); break; @@ -416,6 +424,10 @@ SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_POST_EC_SYNC_DELAY); break; + case VB2_NV_MINIOS_PRIORITY: + SETBIT(VB2_NV_OFFS_MISC, VB2_NV_MISC_MINIOS_PRIORITY); + break; + case VB2_NV_DEPRECATED_DEV_BOOT_FASTBOOT_FULL_CAP: case VB2_NV_DEPRECATED_FASTBOOT_UNLOCK_IN_FW: case VB2_NV_DEPRECATED_ENABLE_ALT_OS_REQUEST: diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2packed_key.c vboot-utils-0~R99-14469.B/firmware/2lib/2packed_key.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2packed_key.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2packed_key.c 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,80 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Key unpacking functions + */ + +#include "2common.h" +#include "2packed_key.h" +#include "2rsa.h" +#include "2sysincludes.h" + +test_mockable +vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, + const uint8_t *buf, uint32_t size) +{ + const struct vb2_packed_key *packed_key = + (const struct vb2_packed_key *)buf; + const uint32_t *buf32; + uint32_t expected_key_size; + + /* Make sure passed buffer is big enough for the packed key */ + VB2_TRY(vb2_verify_packed_key_inside(buf, size, packed_key)); + + /* Unpack key algorithm */ + key->sig_alg = vb2_crypto_to_signature(packed_key->algorithm); + if (key->sig_alg == VB2_SIG_INVALID) { + VB2_DEBUG("Unsupported signature algorithm.\n"); + return VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; + } + + key->hash_alg = vb2_crypto_to_hash(packed_key->algorithm); + if (key->hash_alg == VB2_HASH_INVALID) { + VB2_DEBUG("Unsupported hash algorithm.\n"); + return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM; + } + + expected_key_size = vb2_packed_key_size(key->sig_alg); + if (!expected_key_size || expected_key_size != packed_key->key_size) { + VB2_DEBUG("Wrong key size for algorithm\n"); + return VB2_ERROR_UNPACK_KEY_SIZE; + } + + /* Make sure source buffer is 32-bit aligned */ + buf32 = (const uint32_t *)vb2_packed_key_data(packed_key); + if (!vb2_aligned(buf32, sizeof(uint32_t))) + return VB2_ERROR_UNPACK_KEY_ALIGN; + + /* Validity check key array size */ + key->arrsize = buf32[0]; + if (key->arrsize * sizeof(uint32_t) != vb2_rsa_sig_size(key->sig_alg)) + return VB2_ERROR_UNPACK_KEY_ARRAY_SIZE; + + key->n0inv = buf32[1]; + + /* Arrays point inside the key data */ + key->n = buf32 + 2; + key->rr = buf32 + 2 + key->arrsize; + + /* disable hwcrypto for RSA by default */ + key->allow_hwcrypto = 0; + +#ifdef __COVERITY__ + __coverity_tainted_data_sanitize__(key); + __coverity_tainted_data_sanitize__(buf); +#endif + return VB2_SUCCESS; +} + +vb2_error_t vb2_unpack_key(struct vb2_public_key *key, + const struct vb2_packed_key *packed_key) +{ + if (!packed_key) + return VB2_ERROR_UNPACK_KEY_BUFFER; + + return vb2_unpack_key_buffer(key, + (const uint8_t *)packed_key, + packed_key->key_offset + + packed_key->key_size); +} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2recovery_reasons.c vboot-utils-0~R99-14469.B/firmware/2lib/2recovery_reasons.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2recovery_reasons.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2recovery_reasons.c 2022-02-11 14:46:09.000000000 +0000 @@ -152,8 +152,8 @@ return "Recovery hash space lock error in RO firmware"; /* 0x60 */ case VB2_RECOVERY_TPM_DISABLE_FAILED: return "Failed to disable TPM before running untrusted code"; - /* 0x61 */ case VB2_RECOVERY_ALTFW_HASH_FAILED: - return "Verification of alternative firmware payload failed"; + /* 0x61 */ case VB2_RECOVERY_ALTFW_HASH_MISMATCH: + return "Verification of alternate bootloader payload failed"; /* 0x62 */ case VB2_RECOVERY_SECDATA_FWMP_INIT: return "FWMP secure NVRAM (TPM) initialization error"; /* 0x63 */ case VB2_RECOVERY_CR50_BOOT_MODE: diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2rsa.c vboot-utils-0~R99-14469.B/firmware/2lib/2rsa.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2rsa.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2rsa.c 2022-02-11 14:46:09.000000000 +0000 @@ -11,6 +11,7 @@ #include "2common.h" #include "2rsa.h" +#include "2rsa_private.h" #include "2sha.h" #include "2sysincludes.h" #include "vboot_test.h" diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2secdata_fwmp.c vboot-utils-0~R99-14469.B/firmware/2lib/2secdata_fwmp.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2secdata_fwmp.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2secdata_fwmp.c 2022-02-11 14:46:09.000000000 +0000 @@ -60,6 +60,25 @@ return VB2_SUCCESS; } +uint32_t vb2api_secdata_fwmp_create(struct vb2_context *ctx) +{ + struct vb2_secdata_fwmp *sec = (void *)&ctx->secdata_fwmp; + + /* Clear the entire struct */ + memset(sec, 0, sizeof(*sec)); + + /* Set to current version */ + sec->struct_version = VB2_SECDATA_FWMP_VERSION; + + /* Set the structure size */ + sec->struct_size = sizeof(*sec); + + /* Calculate initial CRC */ + sec->crc8 = vb2_secdata_fwmp_crc(sec); + + return sizeof(*sec); +} + vb2_error_t vb2_secdata_fwmp_init(struct vb2_context *ctx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2secdata_kernel.c vboot-utils-0~R99-14469.B/firmware/2lib/2secdata_kernel.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2secdata_kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2secdata_kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -22,7 +22,13 @@ return MAJOR_VER(sec->struct_version) == 0; } -uint8_t vb2_secdata_kernel_crc(struct vb2_context *ctx) +/** + * Calculate crc8 of kernel secure storage. + * + * @param ctx Context pointer + * @return Calculated crc8 value. + */ +static uint8_t secdata_kernel_crc(struct vb2_context *ctx) { size_t offset, size; @@ -54,7 +60,7 @@ *size = VB2_SECDATA_KERNEL_SIZE_V02; /* Verify CRC */ - if (sec->crc8 != vb2_secdata_kernel_crc(ctx)) { + if (sec->crc8 != secdata_kernel_crc(ctx)) { VB2_DEBUG("secdata_kernel: bad CRC\n"); return VB2_ERROR_SECDATA_KERNEL_CRC; } @@ -101,7 +107,7 @@ *size = sec->struct_size; /* Verify CRC */ - if (sec->crc8 != vb2_secdata_kernel_crc(ctx)) { + if (sec->crc8 != secdata_kernel_crc(ctx)) { VB2_DEBUG("secdata_kernel: bad CRC\n"); return VB2_ERROR_SECDATA_KERNEL_CRC; } @@ -131,7 +137,7 @@ memset(sec, 0, sizeof(*sec)); sec->struct_version = VB2_SECDATA_KERNEL_VERSION_LATEST; sec->struct_size = sizeof(*sec); - sec->crc8 = vb2_secdata_kernel_crc(ctx); + sec->crc8 = secdata_kernel_crc(ctx); /* Mark as changed */ ctx->flags |= VB2_CONTEXT_SECDATA_KERNEL_CHANGED; @@ -256,9 +262,9 @@ } if (is_v0(ctx)) - v0->crc8 = vb2_secdata_kernel_crc(ctx); + v0->crc8 = secdata_kernel_crc(ctx); else - v1->crc8 = vb2_secdata_kernel_crc(ctx); + v1->crc8 = secdata_kernel_crc(ctx); ctx->flags |= VB2_CONTEXT_SECDATA_KERNEL_CHANGED; return; @@ -300,7 +306,7 @@ } memcpy(sec->ec_hash, sha256, sizeof(sec->ec_hash)); - sec->crc8 = vb2_secdata_kernel_crc(ctx); + sec->crc8 = secdata_kernel_crc(ctx); ctx->flags |= VB2_CONTEXT_SECDATA_KERNEL_CHANGED; diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2sha256.c vboot-utils-0~R99-14469.B/firmware/2lib/2sha256.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2sha256.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2sha256.c 2022-02-11 14:46:09.000000000 +0000 @@ -1,3 +1,8 @@ +/* Copyright 2021 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. + */ + /* SHA-256 and SHA-512 implementation based on code by Oliver Gay * under a BSD-style license. See below. */ @@ -37,6 +42,7 @@ #include "2common.h" #include "2sha.h" +#include "2sha_private.h" #include "2sysincludes.h" #define SHFR(x, n) (x >> n) @@ -50,22 +56,6 @@ #define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) -#define UNPACK32(x, str) \ - { \ - *((str) + 3) = (uint8_t) ((x) ); \ - *((str) + 2) = (uint8_t) ((x) >> 8); \ - *((str) + 1) = (uint8_t) ((x) >> 16); \ - *((str) + 0) = (uint8_t) ((x) >> 24); \ - } - -#define PACK32(str, x) \ - { \ - *(x) = ((uint32_t) *((str) + 3) ) \ - | ((uint32_t) *((str) + 2) << 8) \ - | ((uint32_t) *((str) + 1) << 16) \ - | ((uint32_t) *((str) + 0) << 24); \ - } - /* Macros used for loops unrolling */ #define SHA256_SCR(i) \ @@ -77,13 +67,13 @@ #define SHA256_EXP(a, b, c, d, e, f, g, h, j) \ { \ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \ - + sha256_k[j] + w[j]; \ + + vb2_sha256_k[j] + w[j]; \ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \ wv[d] += t1; \ wv[h] = t1 + t2; \ } -static const uint32_t sha256_h0[8] = { +const uint32_t vb2_sha256_h0[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; @@ -93,7 +83,7 @@ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 }; -static const uint32_t sha256_k[64] = { +const uint32_t vb2_sha256_k[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -116,7 +106,7 @@ void vb2_sha256_init(struct vb2_sha256_context *ctx, enum vb2_hash_algorithm algo) { - const uint32_t *h0 = algo == VB2_HASH_SHA224 ? sha224_h0 : sha256_h0; + const uint32_t *h0 = algo == VB2_HASH_SHA224 ? sha224_h0 : vb2_sha256_h0; #ifndef UNROLL_LOOPS int i; @@ -167,7 +157,7 @@ for (j = 0; j < 64; j++) { t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) - + sha256_k[j] + w[j]; + + vb2_sha256_k[j] + w[j]; t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); wv[7] = wv[6]; wv[6] = wv[5]; diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2sha256_x86.c vboot-utils-0~R99-14469.B/firmware/2lib/2sha256_x86.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2sha256_x86.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2sha256_x86.c 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,255 @@ +/* Copyright 2021 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. + * + * SHA256 implementation using x86 SHA extension. + * Mainly from https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-x86.c, + * Written and place in public domain by Jeffrey Walton + * Based on code from Intel, and by Sean Gulley for + * the miTLS project. + */ +#include "2common.h" +#include "2sha.h" +#include "2sha_private.h" +#include "2api.h" + +static struct vb2_sha256_context sha_ctx; + +typedef int vb2_m128i __attribute__ ((vector_size(16))); + +static inline vb2_m128i vb2_loadu_si128(vb2_m128i *ptr) +{ + vb2_m128i result; + asm volatile ("movups %1, %0" : "=x"(result) : "m"(*ptr)); + return result; +} + +static inline void vb2_storeu_si128(vb2_m128i *to, vb2_m128i from) +{ + asm volatile ("movups %1, %0" : "=m"(*to) : "x"(from)); +} + +static inline vb2_m128i vb2_add_epi32(vb2_m128i a, vb2_m128i b) +{ + return a + b; +} + +static inline vb2_m128i vb2_shuffle_epi8(vb2_m128i value, vb2_m128i mask) +{ + asm ("pshufb %1, %0" : "+x"(value) : "xm"(mask)); + return value; +} + +static inline vb2_m128i vb2_shuffle_epi32(vb2_m128i value, int mask) +{ + vb2_m128i result; + asm ("pshufd %2, %1, %0" : "=x"(result) : "xm"(value), "i" (mask)); + return result; +} + +static inline vb2_m128i vb2_alignr_epi8(vb2_m128i a, vb2_m128i b, int imm8) +{ + asm ("palignr %2, %1, %0" : "+x"(a) : "xm"(b), "i"(imm8)); + return a; +} + +static inline vb2_m128i vb2_sha256msg1_epu32(vb2_m128i a, vb2_m128i b) +{ + asm ("sha256msg1 %1, %0" : "+x"(a) : "xm"(b)); + return a; +} + +static inline vb2_m128i vb2_sha256msg2_epu32(vb2_m128i a, vb2_m128i b) +{ + asm ("sha256msg2 %1, %0" : "+x"(a) : "xm"(b)); + return a; +} + +static inline vb2_m128i vb2_sha256rnds2_epu32(vb2_m128i a, vb2_m128i b, + vb2_m128i k) +{ + asm ("sha256rnds2 %1, %0" : "+x"(a) : "xm"(b), "Yz"(k)); + return a; +} + +#define SHA256_X86_PUT_STATE1(j, i) \ + { \ + msgtmp[j] = vb2_loadu_si128((vb2_m128i *) \ + (message + (i << 6) + (j * 16))); \ + msgtmp[j] = vb2_shuffle_epi8(msgtmp[j], shuf_mask); \ + msg = vb2_add_epi32(msgtmp[j], \ + vb2_loadu_si128((vb2_m128i *)&vb2_sha256_k[j * 4])); \ + state1 = vb2_sha256rnds2_epu32(state1, state0, msg); \ + } + +#define SHA256_X86_PUT_STATE0() \ + { \ + msg = vb2_shuffle_epi32(msg, 0x0E); \ + state0 = vb2_sha256rnds2_epu32(state0, state1, msg); \ + } + +#define SHA256_X86_LOOP(j) \ + { \ + int k = j & 3; \ + int prev_k = (k + 3) & 3; \ + int next_k = (k + 1) & 3; \ + msg = vb2_add_epi32(msgtmp[k], \ + vb2_loadu_si128((vb2_m128i *)&vb2_sha256_k[j * 4])); \ + state1 = vb2_sha256rnds2_epu32(state1, state0, msg); \ + tmp = vb2_alignr_epi8(msgtmp[k], msgtmp[prev_k], 4); \ + msgtmp[next_k] = vb2_add_epi32(msgtmp[next_k], tmp); \ + msgtmp[next_k] = vb2_sha256msg2_epu32(msgtmp[next_k], \ + msgtmp[k]); \ + SHA256_X86_PUT_STATE0(); \ + msgtmp[prev_k] = vb2_sha256msg1_epu32(msgtmp[prev_k], \ + msgtmp[k]); \ + } + +static void vb2_sha256_transform_x86ext(const uint8_t *message, + unsigned int block_nb) +{ + vb2_m128i state0, state1, msg, abef_save, cdgh_save; + vb2_m128i msgtmp[4]; + vb2_m128i tmp; + int i; + const vb2_m128i shuf_mask = {0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f}; + + state0 = vb2_loadu_si128((vb2_m128i *)&sha_ctx.h[0]); + state1 = vb2_loadu_si128((vb2_m128i *)&sha_ctx.h[4]); + for (i = 0; i < (int) block_nb; i++) { + abef_save = state0; + cdgh_save = state1; + + SHA256_X86_PUT_STATE1(0, i); + SHA256_X86_PUT_STATE0(); + + SHA256_X86_PUT_STATE1(1, i); + SHA256_X86_PUT_STATE0(); + msgtmp[0] = vb2_sha256msg1_epu32(msgtmp[0], msgtmp[1]); + + SHA256_X86_PUT_STATE1(2, i); + SHA256_X86_PUT_STATE0(); + msgtmp[1] = vb2_sha256msg1_epu32(msgtmp[1], msgtmp[2]); + + SHA256_X86_PUT_STATE1(3, i); + tmp = vb2_alignr_epi8(msgtmp[3], msgtmp[2], 4); + msgtmp[0] = vb2_add_epi32(msgtmp[0], tmp); + msgtmp[0] = vb2_sha256msg2_epu32(msgtmp[0], msgtmp[3]); + SHA256_X86_PUT_STATE0(); + msgtmp[2] = vb2_sha256msg1_epu32(msgtmp[2], msgtmp[3]); + + SHA256_X86_LOOP(4); + SHA256_X86_LOOP(5); + SHA256_X86_LOOP(6); + SHA256_X86_LOOP(7); + SHA256_X86_LOOP(8); + SHA256_X86_LOOP(9); + SHA256_X86_LOOP(10); + SHA256_X86_LOOP(11); + SHA256_X86_LOOP(12); + SHA256_X86_LOOP(13); + SHA256_X86_LOOP(14); + + msg = vb2_add_epi32(msgtmp[3], + vb2_loadu_si128((vb2_m128i *)&vb2_sha256_k[15 * 4])); + state1 = vb2_sha256rnds2_epu32(state1, state0, msg); + SHA256_X86_PUT_STATE0(); + + state0 = vb2_add_epi32(state0, abef_save); + state1 = vb2_add_epi32(state1, cdgh_save); + + } + + vb2_storeu_si128((vb2_m128i *)&sha_ctx.h[0], state0); + vb2_storeu_si128((vb2_m128i *)&sha_ctx.h[4], state1); +} + +vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, + uint32_t data_size) +{ + if (hash_alg != VB2_HASH_SHA256) + return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; + + sha_ctx.h[0] = vb2_sha256_h0[5]; + sha_ctx.h[1] = vb2_sha256_h0[4]; + sha_ctx.h[2] = vb2_sha256_h0[1]; + sha_ctx.h[3] = vb2_sha256_h0[0]; + sha_ctx.h[4] = vb2_sha256_h0[7]; + sha_ctx.h[5] = vb2_sha256_h0[6]; + sha_ctx.h[6] = vb2_sha256_h0[3]; + sha_ctx.h[7] = vb2_sha256_h0[2]; + sha_ctx.size = 0; + sha_ctx.total_size = 0; + memset(sha_ctx.block, 0, sizeof(sha_ctx.block)); + + return VB2_SUCCESS; +} + +vb2_error_t vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size) +{ + unsigned int remaining_blocks; + unsigned int new_size, rem_size, tmp_size; + const uint8_t *shifted_data; + + tmp_size = VB2_SHA256_BLOCK_SIZE - sha_ctx.size; + rem_size = size < tmp_size ? size : tmp_size; + + memcpy(&sha_ctx.block[sha_ctx.size], buf, rem_size); + + if (sha_ctx.size + size < VB2_SHA256_BLOCK_SIZE) { + sha_ctx.size += size; + return VB2_SUCCESS; + } + + new_size = size - rem_size; + remaining_blocks = new_size / VB2_SHA256_BLOCK_SIZE; + + shifted_data = buf + rem_size; + + vb2_sha256_transform_x86ext(sha_ctx.block, 1); + vb2_sha256_transform_x86ext(shifted_data, remaining_blocks); + + rem_size = new_size % VB2_SHA256_BLOCK_SIZE; + + memcpy(sha_ctx.block, &shifted_data[remaining_blocks * VB2_SHA256_BLOCK_SIZE], + rem_size); + + sha_ctx.size = rem_size; + sha_ctx.total_size += (remaining_blocks + 1) * VB2_SHA256_BLOCK_SIZE; + return VB2_SUCCESS; +} + +vb2_error_t vb2ex_hwcrypto_digest_finalize(uint8_t *digest, + uint32_t digest_size) +{ + unsigned int block_nb; + unsigned int pm_size; + unsigned int size_b; + unsigned int block_rem_size = sha_ctx.size % VB2_SHA256_BLOCK_SIZE; + if (digest_size != VB2_SHA256_DIGEST_SIZE) { + VB2_DEBUG("ERROR: Digest size does not match expected length.\n"); + return VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE; + } + + block_nb = (1 + ((VB2_SHA256_BLOCK_SIZE - SHA256_MIN_PAD_LEN) + < block_rem_size)); + + size_b = (sha_ctx.total_size + sha_ctx.size) * 8; + pm_size = block_nb * VB2_SHA256_BLOCK_SIZE; + + memset(sha_ctx.block + sha_ctx.size, 0, pm_size - sha_ctx.size); + sha_ctx.block[sha_ctx.size] = SHA256_PAD_BEGIN; + UNPACK32(size_b, sha_ctx.block + pm_size - 4); + + vb2_sha256_transform_x86ext(sha_ctx.block, block_nb); + + UNPACK32(sha_ctx.h[3], &digest[ 0]); + UNPACK32(sha_ctx.h[2], &digest[ 4]); + UNPACK32(sha_ctx.h[7], &digest[ 8]); + UNPACK32(sha_ctx.h[6], &digest[12]); + UNPACK32(sha_ctx.h[1], &digest[16]); + UNPACK32(sha_ctx.h[0], &digest[20]); + UNPACK32(sha_ctx.h[5], &digest[24]); + UNPACK32(sha_ctx.h[4], &digest[28]); + return VB2_SUCCESS; +} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2struct.c vboot-utils-0~R99-14469.B/firmware/2lib/2struct.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2struct.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2struct.c 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,317 @@ +/* Copyright 2021 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. + * + * Functions for reading, checking and verifying firmware and + * kernel data structures. + */ + +#include "2common.h" + +vb2_error_t vb2_check_keyblock(const struct vb2_keyblock *block, uint32_t size, + const struct vb2_signature *sig) +{ + if(size < sizeof(*block)) { + VB2_DEBUG("Not enough space for keyblock header.\n"); + return VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER; + } + + if (memcmp(block->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE)) { + VB2_DEBUG("Not a valid verified boot keyblock.\n"); + return VB2_ERROR_KEYBLOCK_MAGIC; + } + + if (block->header_version_major != VB2_KEYBLOCK_VERSION_MAJOR) { + VB2_DEBUG("Incompatible keyblock header version.\n"); + return VB2_ERROR_KEYBLOCK_HEADER_VERSION; + } + + if (size < block->keyblock_size) { + VB2_DEBUG("Not enough data for keyblock.\n"); + return VB2_ERROR_KEYBLOCK_SIZE; + } + + if (vb2_verify_signature_inside(block, block->keyblock_size, sig)) { + VB2_DEBUG("Keyblock signature off end of block\n"); + return VB2_ERROR_KEYBLOCK_SIG_OUTSIDE; + } + + /* Make sure advertised signature data sizes are valid. */ + if (block->keyblock_size < sig->data_size) { + VB2_DEBUG("Signature calculated past end of block\n"); + return VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH; + } + + /* Verify we signed enough data */ + if (sig->data_size < sizeof(struct vb2_keyblock)) { + VB2_DEBUG("Didn't sign enough data\n"); + return VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE; + } + + /* Verify data key is inside the block and inside signed data */ + if (vb2_verify_packed_key_inside(block, block->keyblock_size, + &block->data_key)) { + VB2_DEBUG("Data key off end of keyblock\n"); + return VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE; + } + if (vb2_verify_packed_key_inside(block, sig->data_size, + &block->data_key)) { + VB2_DEBUG("Data key off end of signed data\n"); + return VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED; + } + + return VB2_SUCCESS; +} + +vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) +{ + struct vb2_signature *sig = &block->keyblock_signature; + vb2_error_t rv; + + /* Validity check keyblock before attempting signature check of data */ + VB2_TRY(vb2_check_keyblock(block, size, sig)); + + VB2_DEBUG("Checking keyblock signature...\n"); + rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb); + if (rv) { + VB2_DEBUG("Invalid keyblock signature.\n"); + return VB2_ERROR_KEYBLOCK_SIG_INVALID; + } + + /* Success */ + return VB2_SUCCESS; +} + +vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) +{ + struct vb2_signature *sig = &preamble->preamble_signature; + + VB2_DEBUG("Verifying preamble.\n"); + + /* Validity checks before attempting signature of data */ + if(size < sizeof(*preamble)) { + VB2_DEBUG("Not enough data for preamble header\n"); + return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER; + } + if (preamble->header_version_major != + VB2_FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) { + VB2_DEBUG("Incompatible firmware preamble header version.\n"); + return VB2_ERROR_PREAMBLE_HEADER_VERSION; + } + + if (preamble->header_version_minor < 1) { + VB2_DEBUG("Only preamble header 2.1+ supported\n"); + return VB2_ERROR_PREAMBLE_HEADER_OLD; + } + + if (size < preamble->preamble_size) { + VB2_DEBUG("Not enough data for preamble.\n"); + return VB2_ERROR_PREAMBLE_SIZE; + } + + /* Check signature */ + if (vb2_verify_signature_inside(preamble, preamble->preamble_size, + sig)) { + VB2_DEBUG("Preamble signature off end of preamble\n"); + return VB2_ERROR_PREAMBLE_SIG_OUTSIDE; + } + + /* Make sure advertised signature data sizes are valid. */ + if (preamble->preamble_size < sig->data_size) { + VB2_DEBUG("Signature calculated past end of the block\n"); + return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH; + } + + if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) { + VB2_DEBUG("Preamble signature validation failed\n"); + return VB2_ERROR_PREAMBLE_SIG_INVALID; + } + + /* Verify we signed enough data */ + if (sig->data_size < sizeof(struct vb2_fw_preamble)) { + VB2_DEBUG("Didn't sign enough data\n"); + return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE; + } + + /* Verify body signature is inside the signed data */ + if (vb2_verify_signature_inside(preamble, sig->data_size, + &preamble->body_signature)) { + VB2_DEBUG("Firmware body signature off end of preamble\n"); + return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE; + } + + /* Verify kernel subkey is inside the signed data */ + if (vb2_verify_packed_key_inside(preamble, sig->data_size, + &preamble->kernel_subkey)) { + VB2_DEBUG("Kernel subkey off end of preamble\n"); + return VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE; + } + + /* Success */ + return VB2_SUCCESS; +} + +uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble) +{ + if (preamble->header_version_minor < 2) + return 0; + + return preamble->flags; +} + +test_mockable +vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block, + uint32_t size, + const struct vb2_workbuf *wb) +{ + const struct vb2_signature *sig = &block->keyblock_hash; + struct vb2_workbuf wblocal = *wb; + struct vb2_digest_context *dc; + uint8_t *digest; + uint32_t digest_size; + + /* Validity check keyblock before attempting hash check of data */ + VB2_TRY(vb2_check_keyblock(block, size, sig)); + + VB2_DEBUG("Checking keyblock hash...\n"); + + /* Digest goes at start of work buffer */ + digest_size = vb2_digest_size(VB2_HASH_SHA512); + digest = vb2_workbuf_alloc(&wblocal, digest_size); + if (!digest) + return VB2_ERROR_VDATA_WORKBUF_DIGEST; + + /* Hashing requires temp space for the context */ + dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc)); + if (!dc) + return VB2_ERROR_VDATA_WORKBUF_HASHING; + + VB2_TRY(vb2_digest_init(dc, VB2_HASH_SHA512)); + + VB2_TRY(vb2_digest_extend(dc, (const uint8_t *)block, sig->data_size)); + + VB2_TRY(vb2_digest_finalize(dc, digest, digest_size)); + + if (vb2_safe_memcmp(vb2_signature_data(sig), digest, + digest_size) != 0) { + VB2_DEBUG("Invalid keyblock hash.\n"); + return VB2_ERROR_KEYBLOCK_HASH_INVALID_IN_DEV_MODE; + } + + /* Success */ + return VB2_SUCCESS; +} + +test_mockable +vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) +{ + struct vb2_signature *sig = &preamble->preamble_signature; + uint32_t min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_0_SIZE; + + VB2_DEBUG("Verifying kernel preamble.\n"); + + /* Make sure it's even safe to look at the struct */ + if(size < min_size) { + VB2_DEBUG("Not enough data for preamble header.\n"); + return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER; + } + if (preamble->header_version_major != + VB2_KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) { + VB2_DEBUG("Incompatible kernel preamble header version.\n"); + return VB2_ERROR_PREAMBLE_HEADER_VERSION; + } + + if (preamble->header_version_minor >= 2) + min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_2_SIZE; + else if (preamble->header_version_minor == 1) + min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_1_SIZE; + if(preamble->preamble_size < min_size) { + VB2_DEBUG("Preamble size too small for header.\n"); + return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER; + } + if (size < preamble->preamble_size) { + VB2_DEBUG("Not enough data for preamble.\n"); + return VB2_ERROR_PREAMBLE_SIZE; + } + + /* Check signature */ + if (vb2_verify_signature_inside(preamble, preamble->preamble_size, + sig)) { + VB2_DEBUG("Preamble signature off end of preamble\n"); + return VB2_ERROR_PREAMBLE_SIG_OUTSIDE; + } + + /* Make sure advertised signature data sizes are valid. */ + if (preamble->preamble_size < sig->data_size) { + VB2_DEBUG("Signature calculated past end of the block\n"); + return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH; + } + + if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) { + VB2_DEBUG("Preamble signature validation failed\n"); + return VB2_ERROR_PREAMBLE_SIG_INVALID; + } + + /* Verify we signed enough data */ + if (sig->data_size < sizeof(struct vb2_fw_preamble)) { + VB2_DEBUG("Didn't sign enough data\n"); + return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE; + } + + /* Verify body signature is inside the signed data */ + if (vb2_verify_signature_inside(preamble, sig->data_size, + &preamble->body_signature)) { + VB2_DEBUG("Body signature off end of preamble\n"); + return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE; + } + + /* + * If bootloader is present, verify it's covered by the body + * signature. + */ + if (preamble->bootloader_size) { + const void *body_ptr = + (const void *)(uintptr_t)preamble->body_load_address; + const void *bootloader_ptr = + (const void *)(uintptr_t)preamble->bootloader_address; + if (vb2_verify_member_inside(body_ptr, + preamble->body_signature.data_size, + bootloader_ptr, + preamble->bootloader_size, + 0, 0)) { + VB2_DEBUG("Bootloader off end of signed data\n"); + return VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE; + } + } + + /* + * If vmlinuz header is present, verify it's covered by the body + * signature. + */ + if (preamble->header_version_minor >= 1 && + preamble->vmlinuz_header_size) { + const void *body_ptr = + (const void *)(uintptr_t)preamble->body_load_address; + const void *vmlinuz_header_ptr = (const void *) + (uintptr_t)preamble->vmlinuz_header_address; + if (vb2_verify_member_inside(body_ptr, + preamble->body_signature.data_size, + vmlinuz_header_ptr, + preamble->vmlinuz_header_size, + 0, 0)) { + VB2_DEBUG("Vmlinuz header off end of signed data\n"); + return VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE; + } + } + + /* Success */ + return VB2_SUCCESS; +} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2stub.c vboot-utils-0~R99-14469.B/firmware/2lib/2stub.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2stub.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2stub.c 2022-02-11 14:46:09.000000000 +0000 @@ -8,10 +8,15 @@ #include #include #include +#include #include "2api.h" +#include "2common.h" #include "2sysincludes.h" +/*****************************************************************************/ +/* General utility stubs */ + __attribute__((weak)) void vb2ex_printf(const char *func, const char *fmt, ...) { @@ -26,10 +31,18 @@ } __attribute__((weak)) -vb2_error_t vb2ex_tpm_clear_owner(struct vb2_context *ctx) +void vb2ex_abort(void) { - fprintf(stderr, "%s: function not implemented\n", __func__); - return VB2_ERROR_EX_UNIMPLEMENTED; + /* Stub simply exits. */ + abort(); +} + +__attribute__((weak)) +uint32_t vb2ex_mtime(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * VB2_MSEC_PER_SEC + tv.tv_usec / VB2_USEC_PER_MSEC; } __attribute__((weak)) @@ -37,17 +50,95 @@ enum vb2_resource_index index, uint32_t offset, void *buf, uint32_t size) { - fprintf(stderr, "%s: function not implemented\n", __func__); + VB2_DEBUG("function not implemented\n"); + return VB2_ERROR_EX_UNIMPLEMENTED; +} + +/*****************************************************************************/ +/* TPM-related stubs */ + +__attribute__((weak)) +vb2_error_t vb2ex_tpm_clear_owner(struct vb2_context *ctx) +{ + VB2_DEBUG("function not implemented\n"); return VB2_ERROR_EX_UNIMPLEMENTED; } __attribute__((weak)) vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val) { - fprintf(stderr, "%s: function not implemented\n", __func__); + VB2_DEBUG("function not implemented\n"); return VB2_ERROR_EX_UNIMPLEMENTED; } +/*****************************************************************************/ +/* auxfw and EC-related stubs */ + +__attribute__((weak)) +vb2_error_t vb2ex_ec_running_rw(int *in_rw) +{ + *in_rw = 0; + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_jump_to_rw(void) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_disable_jump(void) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_hash_image(enum vb2_firmware_selection select, + const uint8_t **hash, int *hash_size) +{ + static const uint8_t fake_hash[32] = {1, 2, 3, 4}; + + *hash = fake_hash; + *hash_size = sizeof(fake_hash); + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_get_expected_image_hash(enum vb2_firmware_selection select, + const uint8_t **hash, int *hash_size) +{ + static const uint8_t fake_hash[32] = {1, 2, 3, 4}; + + *hash = fake_hash; + *hash_size = sizeof(fake_hash); + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_update_image(enum vb2_firmware_selection select) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_protect(enum vb2_firmware_selection select) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *ctx) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_ec_battery_cutoff(void) +{ + return VB2_SUCCESS; +} + __attribute__((weak)) vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity) { @@ -67,12 +158,8 @@ return VB2_SUCCESS; } -__attribute__((weak)) -void vb2ex_abort(void) -{ - /* Stub simply exits. */ - abort(); -} +/*****************************************************************************/ +/* UI-related stubs */ __attribute__((weak)) const char *vb2ex_get_debug_info(struct vb2_context *ctx) @@ -87,15 +174,17 @@ } __attribute__((weak)) -uint32_t vb2ex_prepare_log_screen(const char *str) +vb2_error_t vb2ex_diag_get_storage_health(const char **out) { - return 1; + *out = "mock"; + return VB2_SUCCESS; } __attribute__((weak)) -const char *vb2ex_get_diagnostic_storage(void) +vb2_error_t vb2ex_diag_get_storage_test_log(const char **out) { - return "mock"; + *out = "mock"; + return VB2_SUCCESS; } __attribute__((weak)) @@ -111,3 +200,64 @@ *out = "mock"; return VB2_SUCCESS; } + +__attribute__((weak)) +void vb2ex_msleep(uint32_t msec) +{ +} + +__attribute__((weak)) +void vb2ex_beep(uint32_t msec, uint32_t frequency) +{ +} + +__attribute__((weak)) +uint32_t vb2ex_get_locale_count(void) +{ + return 0; +} + +__attribute__((weak)) +uint32_t vb2ex_get_altfw_count(void) +{ + return 0; +} + +__attribute__((weak)) +int vb2ex_physical_presence_pressed(void) +{ + return 0; +} + +__attribute__((weak)) +vb2_error_t vb2ex_commit_data(struct vb2_context *ctx) +{ + ctx->flags &= ~VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED; + ctx->flags &= ~VB2_CONTEXT_SECDATA_KERNEL_CHANGED; + ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED; + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *ctx) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *ctx) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_developer_ui(struct vb2_context *ctx) +{ + return VB2_SUCCESS; +} + +__attribute__((weak)) +vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *ctx) +{ + return VB2_SUCCESS; +} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2stub_hwcrypto.c vboot-utils-0~R99-14469.B/firmware/2lib/2stub_hwcrypto.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2stub_hwcrypto.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2stub_hwcrypto.c 2022-02-11 14:46:09.000000000 +0000 @@ -7,6 +7,7 @@ #include "2api.h" +#ifndef X86_SHA_EXT __attribute__((weak)) vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, uint32_t data_size) @@ -26,6 +27,7 @@ { return VB2_ERROR_SHA_FINALIZE_ALGORITHM; /* Should not be called. */ } +#endif __attribute__((weak)) vb2_error_t vb2ex_hwcrypto_rsa_verify_digest(const struct vb2_public_key *key, diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2ui.c vboot-utils-0~R99-14469.B/firmware/2lib/2ui.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2ui.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2ui.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,493 +0,0 @@ -/* Copyright 2020 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. - * - * User interfaces for developer and recovery mode menus. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2return_codes.h" -#include "2ui.h" -#include "2ui_private.h" -#include "vboot_api.h" /* For VB_SHUTDOWN_REQUEST_POWER_BUTTON */ -#include "vboot_kernel.h" - -/*****************************************************************************/ -/* Utility functions */ - -/** - * Check GBB flags against VbExIsShutdownRequested() shutdown request, - * and check for VB_BUTTON_POWER_SHORT_PRESS key, to determine if a - * shutdown is required. - * - * @param ui UI context pointer - * @return VB2_REQUEST_SHUTDOWN if shutdown needed, or VB2_REQUEST_UI_CONTINUE - */ -vb2_error_t check_shutdown_request(struct vb2_ui_context *ui) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ui->ctx); - uint32_t shutdown_request = VbExIsShutdownRequested(); - - /* - * Ignore power button push until after we have seen it released. - * This avoids shutting down immediately if the power button is still - * being held on startup. After we've recognized a valid power button - * push then don't report the event until after the button is released. - */ - if (shutdown_request & VB_SHUTDOWN_REQUEST_POWER_BUTTON) { - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - if (ui->power_button == VB2_POWER_BUTTON_RELEASED) - ui->power_button = VB2_POWER_BUTTON_PRESSED; - } else { - if (ui->power_button == VB2_POWER_BUTTON_PRESSED) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - ui->power_button = VB2_POWER_BUTTON_RELEASED; - } - - if (ui->key == VB_BUTTON_POWER_SHORT_PRESS) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - /* If desired, ignore shutdown request due to lid closure. */ - if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; - - /* - * In detachables, disable shutdown due to power button. - * It is used for menu selection instead. - */ - if (DETACHABLE) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - if (shutdown_request) - return VB2_REQUEST_SHUTDOWN; - - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Error action functions */ - -vb2_error_t error_exit_action(struct vb2_ui_context *ui) -{ - /* - * If an error message is currently shown on the screen, any - * key press clears that error. Unset the key so that it is - * not processed by other action functions. - */ - if (ui->key && ui->error_code) { - ui->error_code = VB2_UI_ERROR_NONE; - ui->key = 0; - } - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Menu navigation functions */ - -const struct vb2_menu *get_menu(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu; - static const struct vb2_menu empty_menu = { - .num_items = 0, - .items = NULL, - }; - if (ui->state->screen->get_menu) { - menu = ui->state->screen->get_menu(ui); - return menu ? menu : &empty_menu; - } else { - return &ui->state->screen->menu; - } -} - -vb2_error_t menu_navigation_action(struct vb2_ui_context *ui) -{ - uint32_t key = ui->key; - - /* Map detachable button presses for simplicity. */ - if (DETACHABLE) { - if (key == VB_BUTTON_VOL_UP_SHORT_PRESS) - key = VB_KEY_UP; - else if (key == VB_BUTTON_VOL_DOWN_SHORT_PRESS) - key = VB_KEY_DOWN; - else if (key == VB_BUTTON_POWER_SHORT_PRESS) - key = VB_KEY_ENTER; - } - - switch (key) { - case VB_KEY_UP: - return vb2_ui_menu_prev(ui); - case VB_KEY_DOWN: - return vb2_ui_menu_next(ui); - case VB_KEY_ENTER: - return vb2_ui_menu_select(ui); - case VB_KEY_ESC: - return vb2_ui_screen_back(ui); - default: - if (key != 0) - VB2_DEBUG("Pressed key %#x, trusted? %d\n", - ui->key, ui->key_trusted); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t vb2_ui_menu_prev(struct vb2_ui_context *ui) -{ - int item; - - if (!DETACHABLE && ui->key == VB_BUTTON_VOL_UP_SHORT_PRESS) - return VB2_REQUEST_UI_CONTINUE; - - item = ui->state->selected_item - 1; - while (item >= 0 && VB2_GET_BIT(ui->state->hidden_item_mask, item)) - item--; - /* Only update if item is valid */ - if (item >= 0) - ui->state->selected_item = item; - - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t vb2_ui_menu_next(struct vb2_ui_context *ui) -{ - int item; - const struct vb2_menu *menu; - - if (!DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_SHORT_PRESS) - return VB2_REQUEST_UI_CONTINUE; - - menu = get_menu(ui); - item = ui->state->selected_item + 1; - while (item < menu->num_items && - VB2_GET_BIT(ui->state->hidden_item_mask, item)) - item++; - /* Only update if item is valid */ - if (item < menu->num_items) - ui->state->selected_item = item; - - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t vb2_ui_menu_select(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu; - const struct vb2_menu_item *menu_item; - - if (!DETACHABLE && ui->key == VB_BUTTON_POWER_SHORT_PRESS) - return VB2_REQUEST_UI_CONTINUE; - - menu = get_menu(ui); - if (menu->num_items == 0) - return VB2_REQUEST_UI_CONTINUE; - - menu_item = &menu->items[ui->state->selected_item]; - - /* Cannot select a disabled menu item */ - if (VB2_GET_BIT(ui->state->disabled_item_mask, - ui->state->selected_item)) { - VB2_DEBUG("Menu item <%s> disabled; ignoring\n", - menu_item->text); - return VB2_REQUEST_UI_CONTINUE; - } - - if (menu_item->action) { - VB2_DEBUG("Menu item <%s> run action\n", menu_item->text); - return menu_item->action(ui); - } else if (menu_item->target) { - VB2_DEBUG("Menu item <%s> to target screen %#x\n", - menu_item->text, menu_item->target); - return vb2_ui_screen_change(ui, menu_item->target); - } - - VB2_DEBUG("Menu item <%s> no action or target screen\n", - menu_item->text); - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Screen navigation functions */ - -vb2_error_t vb2_ui_screen_back(struct vb2_ui_context *ui) -{ - struct vb2_screen_state *tmp; - - if (ui->state && ui->state->prev) { - tmp = ui->state->prev; - free(ui->state); - ui->state = tmp; - if (ui->state->screen->reinit) - return ui->state->screen->reinit(ui); - } else { - VB2_DEBUG("ERROR: No previous screen; ignoring\n"); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t default_screen_init(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu = get_menu(ui); - ui->state->selected_item = 0; - if (menu->num_items > 1 && menu->items[0].is_language_select) - ui->state->selected_item = 1; - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t vb2_ui_screen_change(struct vb2_ui_context *ui, enum vb2_screen id) -{ - const struct vb2_screen_info *new_screen_info; - struct vb2_screen_state *cur_state; - int state_exists = 0; - - new_screen_info = vb2_get_screen_info(id); - if (new_screen_info == NULL) { - VB2_DEBUG("ERROR: Screen entry %#x not found; ignoring\n", id); - return VB2_REQUEST_UI_CONTINUE; - } - - /* Check to see if the screen state already exists in our stack. */ - cur_state = ui->state; - while (cur_state != NULL) { - if (cur_state->screen->id == id) { - state_exists = 1; - break; - } - cur_state = cur_state->prev; - } - - if (state_exists) { - /* Pop until the requested screen is at the top of stack. */ - while (ui->state->screen->id != id) { - cur_state = ui->state; - ui->state = cur_state->prev; - free(cur_state); - } - if (ui->state->screen->reinit) - return ui->state->screen->reinit(ui); - } else { - /* Allocate the requested screen on top of the stack. */ - cur_state = malloc(sizeof(*ui->state)); - memset(cur_state, 0, sizeof(*ui->state)); - if (cur_state == NULL) { - VB2_DEBUG("WARNING: malloc failed; ignoring\n"); - return VB2_REQUEST_UI_CONTINUE; - } - cur_state->prev = ui->state; - cur_state->screen = new_screen_info; - ui->state = cur_state; - if (ui->state->screen->init) - return ui->state->screen->init(ui); - else - return default_screen_init(ui); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Core UI loop */ - -vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, - vb2_error_t (*global_action)(struct vb2_ui_context *ui)) -{ - struct vb2_ui_context ui; - struct vb2_screen_state prev_state; - int prev_disable_timer; - enum vb2_ui_error prev_error_code; - const struct vb2_menu *menu; - const struct vb2_screen_info *root_info; - uint32_t key_flags; - uint32_t start_time_ms, elapsed_ms; - vb2_error_t rv; - - memset(&ui, 0, sizeof(ui)); - ui.ctx = ctx; - root_info = vb2_get_screen_info(root_screen_id); - if (root_info == NULL) - VB2_DIE("Root screen not found.\n"); - ui.locale_id = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - rv = vb2_ui_screen_change(&ui, root_screen_id); - if (rv != VB2_REQUEST_UI_CONTINUE) - return rv; - memset(&prev_state, 0, sizeof(prev_state)); - prev_disable_timer = 0; - prev_error_code = VB2_UI_ERROR_NONE; - - while (1) { - start_time_ms = vb2ex_mtime(); - - /* Draw if there are state changes. */ - if (memcmp(&prev_state, ui.state, sizeof(*ui.state)) || - /* Redraw when timer is disabled. */ - prev_disable_timer != ui.disable_timer || - /* Redraw/beep on a transition. */ - prev_error_code != ui.error_code || - /* Beep. */ - ui.error_beep != 0 || - /* Redraw on a screen request to refresh. */ - ui.force_display) { - - menu = get_menu(&ui); - VB2_DEBUG("<%s> menu item <%s>\n", - ui.state->screen->name, - menu->num_items ? - menu->items[ui.state->selected_item].text : - "null"); - vb2ex_display_ui(ui.state->screen->id, ui.locale_id, - ui.state->selected_item, - ui.state->disabled_item_mask, - ui.state->hidden_item_mask, - ui.disable_timer, - ui.state->current_page, - ui.error_code); - if (ui.error_beep || - (ui.error_code && - prev_error_code != ui.error_code)) { - vb2ex_beep(250, 400); - ui.error_beep = 0; - } - - /* Reset refresh flag. */ - ui.force_display = 0; - - /* Update prev variables. */ - memcpy(&prev_state, ui.state, sizeof(*ui.state)); - prev_disable_timer = ui.disable_timer; - prev_error_code = ui.error_code; - } - - /* Grab new keyboard input. */ - ui.key = VbExKeyboardReadWithFlags(&key_flags); - ui.key_trusted = !!(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD); - - /* Check for shutdown request. */ - rv = check_shutdown_request(&ui); - if (rv != VB2_REQUEST_UI_CONTINUE) { - VB2_DEBUG("Shutdown requested!\n"); - return rv; - } - - /* Check if we need to exit an error box. */ - rv = error_exit_action(&ui); - if (rv != VB2_REQUEST_UI_CONTINUE) - return rv; - - /* Run screen action. */ - if (ui.state->screen->action) { - rv = ui.state->screen->action(&ui); - if (rv != VB2_REQUEST_UI_CONTINUE) - return rv; - } - - /* Run menu navigation action. */ - rv = menu_navigation_action(&ui); - if (rv != VB2_REQUEST_UI_CONTINUE) - return rv; - - /* Run global action function if available. */ - if (global_action) { - rv = global_action(&ui); - if (rv != VB2_REQUEST_UI_CONTINUE) - return rv; - } - - /* Delay. */ - elapsed_ms = vb2ex_mtime() - start_time_ms; - if (elapsed_ms < KEY_DELAY_MS) - vb2ex_msleep(KEY_DELAY_MS - elapsed_ms); - } - - return VB2_SUCCESS; -} - -/*****************************************************************************/ -/* Developer mode */ - -vb2_error_t vb2_developer_menu(struct vb2_context *ctx) -{ - return ui_loop(ctx, VB2_SCREEN_DEVELOPER_MODE, developer_action); -} - -vb2_error_t developer_action(struct vb2_ui_context *ui) -{ - /* Developer mode keyboard shortcuts */ - if (ui->key == VB_KEY_CTRL('S')) - return vb2_ui_screen_change(ui, VB2_SCREEN_DEVELOPER_TO_NORM); - if (ui->key == VB_KEY_CTRL('U') || - (DETACHABLE && ui->key == VB_BUTTON_VOL_UP_LONG_PRESS)) - return vb2_ui_developer_mode_boot_external_action(ui); - if (ui->key == VB_KEY_CTRL('D') || - (DETACHABLE && ui->key == VB_BUTTON_VOL_DOWN_LONG_PRESS)) - return vb2_ui_developer_mode_boot_internal_action(ui); - if (ui->key == VB_KEY_CTRL('L')) - return vb2_ui_developer_mode_boot_alternate_action(ui); - if (ui->key == '\t') - return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO); - - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Broken recovery */ - -vb2_error_t vb2_broken_recovery_menu(struct vb2_context *ctx) -{ - return ui_loop(ctx, VB2_SCREEN_RECOVERY_BROKEN, broken_recovery_action); -} - -vb2_error_t broken_recovery_action(struct vb2_ui_context *ui) -{ - /* Broken recovery keyboard shortcuts */ - if (ui->key == '\t') - return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO); - - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Manual recovery */ - -vb2_error_t vb2_manual_recovery_menu(struct vb2_context *ctx) -{ - return ui_loop(ctx, VB2_SCREEN_RECOVERY_SELECT, manual_recovery_action); -} - -vb2_error_t manual_recovery_action(struct vb2_ui_context *ui) -{ - /* See if we have a recovery kernel available yet. */ - vb2_error_t rv = VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE); - if (rv == VB2_SUCCESS) - return rv; - - /* If disk validity state changed, switch to appropriate screen. */ - if (ui->recovery_rv != rv) { - VB2_DEBUG("Recovery VbTryLoadKernel %#x --> %#x\n", - ui->recovery_rv, rv); - ui->recovery_rv = rv; - return vb2_ui_screen_change(ui, - rv == VB2_ERROR_LK_NO_DISK_FOUND ? - VB2_SCREEN_RECOVERY_SELECT : - VB2_SCREEN_RECOVERY_INVALID); - } - - /* Manual recovery keyboard shortcuts */ - if (ui->key == VB_KEY_CTRL('D') || - (DETACHABLE && ui->key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS)) - return vb2_ui_screen_change(ui, VB2_SCREEN_RECOVERY_TO_DEV); - - if (ui->key == '\t') - return vb2_ui_screen_change(ui, VB2_SCREEN_DEBUG_INFO); - - return VB2_REQUEST_UI_CONTINUE; -} - -/*****************************************************************************/ -/* Diagnostics */ - -vb2_error_t vb2_diagnostic_menu(struct vb2_context *ctx) -{ - return ui_loop(ctx, VB2_SCREEN_DIAGNOSTICS, NULL); -} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/2ui_screens.c vboot-utils-0~R99-14469.B/firmware/2lib/2ui_screens.c --- vboot-utils-0~R88-13597.B/firmware/2lib/2ui_screens.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/2ui_screens.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1270 +0,0 @@ -/* Copyright 2020 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. - * - * Firmware screen definitions. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2ui.h" -#include "2ui_private.h" -#include "vboot_api.h" -#include "vboot_kernel.h" - -#define MENU_ITEMS(a) ((struct vb2_menu){ \ - .num_items = ARRAY_SIZE(a), \ - .items = a, \ -}) - -#define LANGUAGE_SELECT_ITEM ((struct vb2_menu_item){ \ - .text = "Language selection", \ - .target = VB2_SCREEN_LANGUAGE_SELECT, \ - .is_language_select = 1, \ -}) - -#define NEXT_ITEM(target_screen) ((struct vb2_menu_item){ \ - .text = "Next", \ - .target = (target_screen), \ -}) - -#define BACK_ITEM ((struct vb2_menu_item){ \ - .text = "Back", \ - .action = vb2_ui_screen_back, \ -}) - -#define ADVANCED_OPTIONS_ITEM ((struct vb2_menu_item){ \ - .text = "Advanced options", \ - .target = VB2_SCREEN_ADVANCED_OPTIONS, \ -}) - -/* Action that will power off the device. */ -static vb2_error_t power_off_action(struct vb2_ui_context *ui) -{ - return VB2_REQUEST_SHUTDOWN; -} - -#define POWER_OFF_ITEM ((struct vb2_menu_item){ \ - .text = "Power off", \ - .action = power_off_action, \ -}) - -/******************************************************************************/ -/* - * Functions used for log screens - * - * Expects that the page_count is valid and page_up_item and page_down_item are - * assigned to correct menu item indices in all three functions, the - * current_page is valid in prev and next actions, and the back_item is assigned - * to a correct menu item index. - */ - -static vb2_error_t log_page_init(struct vb2_ui_context *ui) -{ - const struct vb2_screen_info *screen = ui->state->screen; - - ui->state->current_page = 0; - - if (ui->state->page_count == 1) { - VB2_SET_BIT(ui->state->disabled_item_mask, - screen->page_up_item); - VB2_SET_BIT(ui->state->disabled_item_mask, - screen->page_down_item); - ui->state->selected_item = screen->back_item; - } else { - VB2_SET_BIT(ui->state->disabled_item_mask, - screen->page_up_item); - ui->state->selected_item = screen->page_down_item; - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t log_page_prev_action(struct vb2_ui_context *ui) -{ - const struct vb2_screen_info *screen = ui->state->screen; - - /* Validity check. */ - if (ui->state->current_page == 0) - return VB2_REQUEST_UI_CONTINUE; - - ui->state->current_page--; - - /* Clear bits of page down. */ - if (ui->state->current_page != ui->state->page_count - 1) - VB2_CLR_BIT(ui->state->disabled_item_mask, - screen->page_down_item); - - /* Disable page up at the first page. */ - if (ui->state->current_page == 0) - VB2_SET_BIT(ui->state->disabled_item_mask, - screen->page_up_item); - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t log_page_next_action(struct vb2_ui_context *ui) -{ - const struct vb2_screen_info *screen = ui->state->screen; - - /* Validity check. */ - if (ui->state->current_page == ui->state->page_count - 1) - return VB2_REQUEST_UI_CONTINUE; - - ui->state->current_page++; - - /* Clear bits of page up. */ - if (ui->state->current_page != 0) - VB2_CLR_BIT(ui->state->disabled_item_mask, - screen->page_up_item); - - /* Disable page down at the last page. */ - if (ui->state->current_page == ui->state->page_count - 1) - VB2_SET_BIT(ui->state->disabled_item_mask, - screen->page_down_item); - - return VB2_REQUEST_UI_CONTINUE; -} - -#define PAGE_UP_ITEM ((struct vb2_menu_item){ \ - .text = "Page up", \ - .action = log_page_prev_action, \ -}) - -#define PAGE_DOWN_ITEM ((struct vb2_menu_item){ \ - .text = "Page down", \ - .action = log_page_next_action, \ -}) - -/******************************************************************************/ -/* VB2_SCREEN_BLANK */ - -static const struct vb2_screen_info blank_screen = { - .id = VB2_SCREEN_BLANK, - .name = "Blank", -}; - -/******************************************************************************/ -/* VB2_SCREEN_LANGUAGE_SELECT */ - -static vb2_error_t language_select_action(struct vb2_ui_context *ui) -{ - vb2_error_t rv; - ui->locale_id = ui->state->selected_item; - VB2_DEBUG("Locale changed to %u\n", ui->locale_id); - - /* Write locale id back to nvdata. */ - vb2_nv_set(ui->ctx, VB2_NV_LOCALIZATION_INDEX, ui->locale_id); - - /* Commit nvdata changes immediately, in case of three-finger salute - reboot. Ignore commit errors in recovery mode. */ - rv = vb2ex_commit_data(ui->ctx); - if (rv && !(ui->ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) - return rv; - - return vb2_ui_screen_back(ui); -} - -const struct vb2_menu *get_language_menu(struct vb2_ui_context *ui) -{ - int i; - uint32_t num_locales; - struct vb2_menu_item *items; - - if (ui->language_menu.num_items > 0) - return &ui->language_menu; - - num_locales = vb2ex_get_locale_count(); - if (num_locales == 0) { - VB2_DEBUG("WARNING: No locales available; assuming 1 locale\n"); - num_locales = 1; - } - - items = malloc(num_locales * sizeof(struct vb2_menu_item)); - if (!items) { - VB2_DEBUG("ERROR: malloc failed for language items\n"); - return NULL; - } - - for (i = 0; i < num_locales; i++) { - items[i].text = "Some language"; - items[i].action = language_select_action; - } - - ui->language_menu.num_items = num_locales; - ui->language_menu.items = items; - return &ui->language_menu; -} - -static vb2_error_t language_select_init(struct vb2_ui_context *ui) -{ - const struct vb2_menu *menu = get_menu(ui); - if (menu->num_items == 0) { - VB2_DEBUG("ERROR: No menu items found; " - "rejecting entering language selection screen\n"); - return vb2_ui_screen_back(ui); - } - if (ui->locale_id < menu->num_items) { - ui->state->selected_item = ui->locale_id; - } else { - VB2_DEBUG("WARNING: Current locale not found in menu items; " - "initializing selected_item to 0\n"); - ui->state->selected_item = 0; - } - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_screen_info language_select_screen = { - .id = VB2_SCREEN_LANGUAGE_SELECT, - .name = "Language selection screen", - .init = language_select_init, - .get_menu = get_language_menu, -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_BROKEN */ - -static const struct vb2_menu_item recovery_broken_items[] = { - LANGUAGE_SELECT_ITEM, - ADVANCED_OPTIONS_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_broken_screen = { - .id = VB2_SCREEN_RECOVERY_BROKEN, - .name = "Recover broken device", - .menu = MENU_ITEMS(recovery_broken_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_ADVANCED_OPTIONS */ - -#define ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE 1 -#define ADVANCED_OPTIONS_ITEM_DEBUG_INFO 2 - -vb2_error_t advanced_options_init(struct vb2_ui_context *ui) -{ - ui->state->selected_item = ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE; - if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED || - !vb2_allow_recovery(ui->ctx)) { - VB2_SET_BIT(ui->state->hidden_item_mask, - ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE); - ui->state->selected_item = ADVANCED_OPTIONS_ITEM_DEBUG_INFO; - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_menu_item advanced_options_items[] = { - LANGUAGE_SELECT_ITEM, - [ADVANCED_OPTIONS_ITEM_DEVELOPER_MODE] = { - .text = "Enable developer mode", - .target = VB2_SCREEN_RECOVERY_TO_DEV, - }, - [ADVANCED_OPTIONS_ITEM_DEBUG_INFO] = { - .text = "Debug info", - .target = VB2_SCREEN_DEBUG_INFO, - }, - { - .text = "Firmware log", - .target = VB2_SCREEN_FIRMWARE_LOG, - }, - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info advanced_options_screen = { - .id = VB2_SCREEN_ADVANCED_OPTIONS, - .name = "Advanced options", - .init = advanced_options_init, - .menu = MENU_ITEMS(advanced_options_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DEBUG_INFO */ - -#define DEBUG_INFO_ITEM_PAGE_UP 1 -#define DEBUG_INFO_ITEM_PAGE_DOWN 2 -#define DEBUG_INFO_ITEM_BACK 3 - -static vb2_error_t debug_info_init(struct vb2_ui_context *ui) -{ - const char *log_string = vb2ex_get_debug_info(ui->ctx); - if (!log_string) { - VB2_DEBUG("ERROR: Failed to retrieve debug info\n"); - ui->error_code = VB2_UI_ERROR_DEBUG_LOG; - return vb2_ui_screen_back(ui); - } - ui->state->page_count = vb2ex_prepare_log_screen(log_string); - if (ui->state->page_count == 0) { - VB2_DEBUG("ERROR: Failed to prepare debug info screen\n"); - ui->error_code = VB2_UI_ERROR_DEBUG_LOG; - return vb2_ui_screen_back(ui); - } - - return log_page_init(ui); -} - -static vb2_error_t debug_info_reinit(struct vb2_ui_context *ui) -{ - const char *log_string = vb2ex_get_debug_info(ui->ctx); - if (!log_string) { - VB2_DEBUG("ERROR: Failed to retrieve debug info\n"); - ui->error_code = VB2_UI_ERROR_DEBUG_LOG; - return vb2_ui_screen_back(ui); - } - ui->state->page_count = vb2ex_prepare_log_screen(log_string); - if (ui->state->page_count == 0) { - VB2_DEBUG("ERROR: Failed to prepare debug info screen\n"); - ui->error_code = VB2_UI_ERROR_DEBUG_LOG; - return vb2_ui_screen_back(ui); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_menu_item debug_info_items[] = { - LANGUAGE_SELECT_ITEM, - [DEBUG_INFO_ITEM_PAGE_UP] = PAGE_UP_ITEM, - [DEBUG_INFO_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM, - [DEBUG_INFO_ITEM_BACK] = BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info debug_info_screen = { - .id = VB2_SCREEN_DEBUG_INFO, - .name = "Debug info", - .init = debug_info_init, - .reinit = debug_info_reinit, - .menu = MENU_ITEMS(debug_info_items), - .page_up_item = DEBUG_INFO_ITEM_PAGE_UP, - .page_down_item = DEBUG_INFO_ITEM_PAGE_DOWN, - .back_item = DEBUG_INFO_ITEM_BACK, -}; - -/******************************************************************************/ -/* VB2_SCREEN_FIRMWARE_LOG */ - -#define FIRMWARE_LOG_ITEM_PAGE_UP 1 -#define FIRMWARE_LOG_ITEM_PAGE_DOWN 2 -#define FIRMWARE_LOG_ITEM_BACK 3 - -static vb2_error_t firmware_log_init(struct vb2_ui_context *ui) -{ - const char *log_string = vb2ex_get_firmware_log(1); - if (!log_string) { - VB2_DEBUG("ERROR: Failed to retrieve firmware log\n"); - ui->error_code = VB2_UI_ERROR_FIRMWARE_LOG; - return vb2_ui_screen_back(ui); - } - ui->state->page_count = vb2ex_prepare_log_screen(log_string); - if (ui->state->page_count == 0) { - VB2_DEBUG("ERROR: Failed to prepare firmware log screen\n"); - ui->error_code = VB2_UI_ERROR_FIRMWARE_LOG; - return vb2_ui_screen_back(ui); - } - - return log_page_init(ui); -} - -static vb2_error_t firmware_log_reinit(struct vb2_ui_context *ui) -{ - const char *log_string = vb2ex_get_firmware_log(0); - if (!log_string) { - VB2_DEBUG("ERROR: Failed to retrieve firmware log\n"); - ui->error_code = VB2_UI_ERROR_FIRMWARE_LOG; - return vb2_ui_screen_back(ui); - } - ui->state->page_count = vb2ex_prepare_log_screen(log_string); - if (ui->state->page_count == 0) { - VB2_DEBUG("ERROR: Failed to prepare firmware log screen\n"); - ui->error_code = VB2_UI_ERROR_FIRMWARE_LOG; - return vb2_ui_screen_back(ui); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_menu_item firmware_log_items[] = { - LANGUAGE_SELECT_ITEM, - [FIRMWARE_LOG_ITEM_PAGE_UP] = PAGE_UP_ITEM, - [FIRMWARE_LOG_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM, - [FIRMWARE_LOG_ITEM_BACK] = BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info firmware_log_screen = { - .id = VB2_SCREEN_FIRMWARE_LOG, - .name = "Firmware log", - .init = firmware_log_init, - .reinit = firmware_log_reinit, - .menu = MENU_ITEMS(firmware_log_items), - .page_up_item = FIRMWARE_LOG_ITEM_PAGE_UP, - .page_down_item = FIRMWARE_LOG_ITEM_PAGE_DOWN, - .back_item = FIRMWARE_LOG_ITEM_BACK, -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_SELECT */ - -#define RECOVERY_SELECT_ITEM_PHONE 1 -#define RECOVERY_SELECT_ITEM_EXTERNAL_DISK 2 -#define RECOVERY_SELECT_ITEM_DIAGNOSTICS 3 - -/* Set VB2_NV_DIAG_REQUEST and reboot. */ -static vb2_error_t launch_diagnostics_action(struct vb2_ui_context *ui) -{ - vb2_nv_set(ui->ctx, VB2_NV_DIAG_REQUEST, 1); - VB2_DEBUG("Diagnostics requested, rebooting\n"); - return VB2_REQUEST_REBOOT; -} - -vb2_error_t recovery_select_init(struct vb2_ui_context *ui) -{ - ui->state->selected_item = RECOVERY_SELECT_ITEM_PHONE; - if (!vb2api_phone_recovery_ui_enabled(ui->ctx)) { - VB2_DEBUG("WARNING: Phone recovery not available\n"); - VB2_SET_BIT(ui->state->hidden_item_mask, - RECOVERY_SELECT_ITEM_PHONE); - ui->state->selected_item = RECOVERY_SELECT_ITEM_EXTERNAL_DISK; - } - - if (!DIAGNOSTIC_UI || !vb2api_diagnostic_ui_enabled(ui->ctx)) - VB2_SET_BIT(ui->state->hidden_item_mask, - RECOVERY_SELECT_ITEM_DIAGNOSTICS); - - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_menu_item recovery_select_items[] = { - LANGUAGE_SELECT_ITEM, - [RECOVERY_SELECT_ITEM_PHONE] = { - .text = "Recovery using phone", - .target = VB2_SCREEN_RECOVERY_PHONE_STEP1, - }, - [RECOVERY_SELECT_ITEM_EXTERNAL_DISK] = { - .text = "Recovery using external disk", - .target = VB2_SCREEN_RECOVERY_DISK_STEP1, - }, - [RECOVERY_SELECT_ITEM_DIAGNOSTICS] = { - .text = "Launch diagnostics", - .action = launch_diagnostics_action, - }, - ADVANCED_OPTIONS_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_select_screen = { - .id = VB2_SCREEN_RECOVERY_SELECT, - .name = "Recovery method selection", - .init = recovery_select_init, - .menu = MENU_ITEMS(recovery_select_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_INVALID */ - -static const struct vb2_menu_item recovery_invalid_items[] = { - LANGUAGE_SELECT_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_invalid_screen = { - .id = VB2_SCREEN_RECOVERY_INVALID, - .name = "Invalid recovery inserted", - .menu = MENU_ITEMS(recovery_invalid_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_TO_DEV */ - -#define RECOVERY_TO_DEV_ITEM_CONFIRM 1 -#define RECOVERY_TO_DEV_ITEM_CANCEL 2 - -vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui) -{ - if (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { - /* We're in dev mode, so let user know they can't transition */ - ui->error_code = VB2_UI_ERROR_DEV_MODE_ALREADY_ENABLED; - return vb2_ui_screen_back(ui); - } - - if (!PHYSICAL_PRESENCE_KEYBOARD && vb2ex_physical_presence_pressed()) { - VB2_DEBUG("Presence button stuck?\n"); - return vb2_ui_screen_back(ui); - } - - ui->state->selected_item = RECOVERY_TO_DEV_ITEM_CONFIRM; - - /* Disable "Confirm" button for other physical presence types. */ - if (!PHYSICAL_PRESENCE_KEYBOARD) { - VB2_SET_BIT(ui->state->hidden_item_mask, - RECOVERY_TO_DEV_ITEM_CONFIRM); - ui->state->selected_item = RECOVERY_TO_DEV_ITEM_CANCEL; - } - - ui->physical_presence_button_pressed = 0; - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t recovery_to_dev_finalize(struct vb2_ui_context *ui) -{ - VB2_DEBUG("Physical presence confirmed!\n"); - - /* Validity check, should never happen. */ - if (ui->state->screen->id != VB2_SCREEN_RECOVERY_TO_DEV || - (vb2_get_sd(ui->ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) || - !vb2_allow_recovery(ui->ctx)) { - VB2_DEBUG("ERROR: Dev transition validity check failed\n"); - return VB2_REQUEST_UI_CONTINUE; - } - - VB2_DEBUG("Enabling dev mode and rebooting...\n"); - vb2_enable_developer_mode(ui->ctx); - return VB2_REQUEST_REBOOT_EC_TO_RO; -} - -vb2_error_t recovery_to_dev_confirm_action(struct vb2_ui_context *ui) -{ - if (!ui->key_trusted) { - VB2_DEBUG("Reject untrusted %s confirmation\n", - ui->key == VB_KEY_ENTER ? "ENTER" : "POWER"); - /* - * If physical presence is confirmed using the keyboard, - * beep and notify the user when the ENTER key comes - * from an untrusted keyboard. - */ - if (PHYSICAL_PRESENCE_KEYBOARD && ui->key == VB_KEY_ENTER) - ui->error_code = VB2_UI_ERROR_UNTRUSTED_CONFIRMATION; - return VB2_REQUEST_UI_CONTINUE; - } - return recovery_to_dev_finalize(ui); -} - -vb2_error_t recovery_to_dev_action(struct vb2_ui_context *ui) -{ - int pressed; - - if (ui->key == ' ') { - VB2_DEBUG("SPACE means cancel dev mode transition\n"); - return vb2_ui_screen_back(ui); - } - - /* Keyboard physical presence case covered by "Confirm" action. */ - if (PHYSICAL_PRESENCE_KEYBOARD) - return VB2_REQUEST_UI_CONTINUE; - - pressed = vb2ex_physical_presence_pressed(); - if (pressed) { - VB2_DEBUG("Physical presence button pressed, " - "awaiting release\n"); - ui->physical_presence_button_pressed = 1; - return VB2_REQUEST_UI_CONTINUE; - } - if (!ui->physical_presence_button_pressed) - return VB2_REQUEST_UI_CONTINUE; - VB2_DEBUG("Physical presence button released\n"); - - return recovery_to_dev_finalize(ui); -} - -static const struct vb2_menu_item recovery_to_dev_items[] = { - LANGUAGE_SELECT_ITEM, - [RECOVERY_TO_DEV_ITEM_CONFIRM] = { - .text = "Confirm", - .action = recovery_to_dev_confirm_action, - }, - [RECOVERY_TO_DEV_ITEM_CANCEL] = { - .text = "Cancel", - .action = vb2_ui_screen_back, - }, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_to_dev_screen = { - .id = VB2_SCREEN_RECOVERY_TO_DEV, - .name = "Transition to developer mode", - .init = recovery_to_dev_init, - .action = recovery_to_dev_action, - .menu = MENU_ITEMS(recovery_to_dev_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_PHONE_STEP1 */ - -static const struct vb2_menu_item recovery_phone_step1_items[] = { - LANGUAGE_SELECT_ITEM, - NEXT_ITEM(VB2_SCREEN_RECOVERY_PHONE_STEP2), - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_phone_step1_screen = { - .id = VB2_SCREEN_RECOVERY_PHONE_STEP1, - .name = "Phone recovery step 1", - .menu = MENU_ITEMS(recovery_phone_step1_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_PHONE_STEP2 */ - -static const struct vb2_menu_item recovery_phone_step2_items[] = { - LANGUAGE_SELECT_ITEM, - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_phone_step2_screen = { - .id = VB2_SCREEN_RECOVERY_PHONE_STEP2, - .name = "Phone recovery step 2", - .menu = MENU_ITEMS(recovery_phone_step2_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_DISK_STEP1 */ - -static const struct vb2_menu_item recovery_disk_step1_items[] = { - LANGUAGE_SELECT_ITEM, - NEXT_ITEM(VB2_SCREEN_RECOVERY_DISK_STEP2), - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_disk_step1_screen = { - .id = VB2_SCREEN_RECOVERY_DISK_STEP1, - .name = "Disk recovery step 1", - .menu = MENU_ITEMS(recovery_disk_step1_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_DISK_STEP2 */ - -static const struct vb2_menu_item recovery_disk_step2_items[] = { - LANGUAGE_SELECT_ITEM, - NEXT_ITEM(VB2_SCREEN_RECOVERY_DISK_STEP3), - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_disk_step2_screen = { - .id = VB2_SCREEN_RECOVERY_DISK_STEP2, - .name = "Disk recovery step 2", - .menu = MENU_ITEMS(recovery_disk_step2_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_RECOVERY_DISK_STEP3 */ - -static const struct vb2_menu_item recovery_disk_step3_items[] = { - LANGUAGE_SELECT_ITEM, - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info recovery_disk_step3_screen = { - .id = VB2_SCREEN_RECOVERY_DISK_STEP3, - .name = "Disk recovery step 3", - .menu = MENU_ITEMS(recovery_disk_step3_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DEVELOPER_MODE */ - -#define DEVELOPER_MODE_ITEM_RETURN_TO_SECURE 1 -#define DEVELOPER_MODE_ITEM_BOOT_INTERNAL 2 -#define DEVELOPER_MODE_ITEM_BOOT_EXTERNAL 3 -#define DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER 4 - -vb2_error_t developer_mode_init(struct vb2_ui_context *ui) -{ - enum vb2_dev_default_boot_target default_boot = - vb2api_get_dev_default_boot_target(ui->ctx); - - /* TODO(b/159579189): Split this case into a separate root screen */ - if (!vb2_dev_boot_allowed(ui->ctx)) - vb2_ui_screen_change(ui, VB2_SCREEN_DEVELOPER_TO_NORM); - - /* Don't show "Return to secure mode" button if GBB forces dev mode. */ - if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) - VB2_SET_BIT(ui->state->hidden_item_mask, - DEVELOPER_MODE_ITEM_RETURN_TO_SECURE); - - /* Don't show "Boot from external disk" button if not allowed. */ - if (!vb2_dev_boot_external_allowed(ui->ctx)) - VB2_SET_BIT(ui->state->hidden_item_mask, - DEVELOPER_MODE_ITEM_BOOT_EXTERNAL); - - /* Don't show "Select alternate bootloader" button if not allowed. */ - if (!vb2_dev_boot_legacy_allowed(ui->ctx)) - VB2_SET_BIT(ui->state->hidden_item_mask, - DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER); - - /* Choose the default selection. */ - switch (default_boot) { - case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL: - ui->state->selected_item = DEVELOPER_MODE_ITEM_BOOT_EXTERNAL; - break; - case VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY: - ui->state->selected_item = - DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER; - break; - default: - ui->state->selected_item = DEVELOPER_MODE_ITEM_BOOT_INTERNAL; - break; - } - - ui->start_time_ms = vb2ex_mtime(); - - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t vb2_ui_developer_mode_boot_internal_action( - struct vb2_ui_context *ui) -{ - if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) || - !vb2_dev_boot_allowed(ui->ctx)) { - VB2_DEBUG("ERROR: Dev mode internal boot not allowed\n"); - return VB2_REQUEST_UI_CONTINUE; - } - - VB2_TRY(VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_FIXED)); - return VB2_SUCCESS; -} - -vb2_error_t vb2_ui_developer_mode_boot_external_action( - struct vb2_ui_context *ui) -{ - vb2_error_t rv; - - /* Validity check, should never happen. */ - if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) || - !vb2_dev_boot_allowed(ui->ctx) || - !vb2_dev_boot_external_allowed(ui->ctx)) { - VB2_DEBUG("ERROR: Dev mode external boot not allowed\n"); - ui->error_beep = 1; - ui->error_code = VB2_UI_ERROR_EXTERNAL_BOOT_NOT_ENABLED; - return VB2_REQUEST_UI_CONTINUE; - } - - rv = VbTryLoadKernel(ui->ctx, VB_DISK_FLAG_REMOVABLE); - if (rv == VB2_SUCCESS) { - return VB2_SUCCESS; - } else if (rv == VB2_ERROR_LK_NO_DISK_FOUND) { - if (ui->state->screen->id != - VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL) { - VB2_DEBUG("No external disk found\n"); - ui->error_beep = 1; - } - return vb2_ui_screen_change( - ui, VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL); - } else { - if (ui->state->screen->id != - VB2_SCREEN_DEVELOPER_INVALID_DISK) { - VB2_DEBUG("Invalid external disk: %#x\n", rv); - ui->error_beep = 1; - } - return vb2_ui_screen_change( - ui, VB2_SCREEN_DEVELOPER_INVALID_DISK); - } -} - -vb2_error_t developer_mode_action(struct vb2_ui_context *ui) -{ - const int use_short = vb2api_use_short_dev_screen_delay(ui->ctx); - uint64_t elapsed_ms; - - /* TODO(b/159579189): Split this case into a separate root screen */ - if (!vb2_dev_boot_allowed(ui->ctx)) - vb2_ui_screen_change(ui, VB2_SCREEN_DEVELOPER_TO_NORM); - - /* Once any user interaction occurs, stop the timer. */ - if (ui->key) - ui->disable_timer = 1; - if (ui->disable_timer) - return VB2_REQUEST_UI_CONTINUE; - - elapsed_ms = vb2ex_mtime() - ui->start_time_ms; - - /* If we're using short delay, wait 2 seconds and don't beep. */ - if (use_short && elapsed_ms > DEV_DELAY_SHORT_MS) { - VB2_DEBUG("Booting default target after 2s\n"); - ui->disable_timer = 1; - return vb2_ui_menu_select(ui); - } - - /* Otherwise, beep at 20 and 20.5 seconds. */ - if ((ui->beep_count == 0 && elapsed_ms > DEV_DELAY_BEEP1_MS) || - (ui->beep_count == 1 && elapsed_ms > DEV_DELAY_BEEP2_MS)) { - vb2ex_beep(250, 400); - ui->beep_count++; - } - - /* Stop after 30 seconds. */ - if (elapsed_ms > DEV_DELAY_NORMAL_MS) { - VB2_DEBUG("Booting default target after 30s\n"); - ui->disable_timer = 1; - return vb2_ui_menu_select(ui); - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_menu_item developer_mode_items[] = { - LANGUAGE_SELECT_ITEM, - [DEVELOPER_MODE_ITEM_RETURN_TO_SECURE] = { - .text = "Return to secure mode", - .target = VB2_SCREEN_DEVELOPER_TO_NORM, - }, - [DEVELOPER_MODE_ITEM_BOOT_INTERNAL] = { - .text = "Boot from internal disk", - .action = vb2_ui_developer_mode_boot_internal_action, - }, - [DEVELOPER_MODE_ITEM_BOOT_EXTERNAL] = { - .text = "Boot from external disk", - .action = vb2_ui_developer_mode_boot_external_action, - }, - [DEVELOPER_MODE_ITEM_SELECT_BOOTLOADER] = { - .text = "Select alternate bootloader", - .target = VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER, - }, - ADVANCED_OPTIONS_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info developer_mode_screen = { - .id = VB2_SCREEN_DEVELOPER_MODE, - .name = "Developer mode", - .init = developer_mode_init, - .action = developer_mode_action, - .menu = MENU_ITEMS(developer_mode_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DEVELOPER_TO_NORM */ - -#define DEVELOPER_TO_NORM_ITEM_CONFIRM 1 - -static vb2_error_t developer_to_norm_init(struct vb2_ui_context *ui) -{ - /* Don't allow to-norm if GBB forces dev mode */ - if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - VB2_DEBUG("ERROR: to-norm not allowed\n"); - ui->error_code = VB2_UI_ERROR_TO_NORM_NOT_ALLOWED; - return vb2_ui_screen_back(ui); - } - ui->state->selected_item = DEVELOPER_TO_NORM_ITEM_CONFIRM; - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t developer_to_norm_action(struct vb2_ui_context *ui) -{ - if (vb2_get_gbb(ui->ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - VB2_DEBUG("ERROR: dev mode forced by GBB flag\n"); - return VB2_REQUEST_UI_CONTINUE; - } - - VB2_DEBUG("Leaving dev mode\n"); - vb2_nv_set(ui->ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - return VB2_REQUEST_REBOOT; -} - -static const struct vb2_menu_item developer_to_norm_items[] = { - LANGUAGE_SELECT_ITEM, - { - .text = "Confirm", - .action = developer_to_norm_action, - }, - { - .text = "Cancel", - .action = vb2_ui_screen_back, - }, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info developer_to_norm_screen = { - .id = VB2_SCREEN_DEVELOPER_TO_NORM, - .name = "Transition to normal mode", - .init = developer_to_norm_init, - .menu = MENU_ITEMS(developer_to_norm_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL */ - -static const struct vb2_menu_item developer_boot_external_items[] = { - LANGUAGE_SELECT_ITEM, - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info developer_boot_external_screen = { - .id = VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL, - .name = "Developer boot from external disk", - .action = vb2_ui_developer_mode_boot_external_action, - .menu = MENU_ITEMS(developer_boot_external_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DEVELOPER_INVALID_DISK */ - -static const struct vb2_menu_item developer_invalid_disk_items[] = { - LANGUAGE_SELECT_ITEM, - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info developer_invalid_disk_screen = { - .id = VB2_SCREEN_DEVELOPER_INVALID_DISK, - .name = "Invalid external disk in dev mode", - .action = vb2_ui_developer_mode_boot_external_action, - .menu = MENU_ITEMS(developer_invalid_disk_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER */ - -static const struct vb2_menu_item developer_select_bootloader_items_before[] = { - LANGUAGE_SELECT_ITEM, -}; - -static const struct vb2_menu_item developer_select_bootloader_items_after[] = { - BACK_ITEM, - POWER_OFF_ITEM, -}; - -static vb2_error_t developer_select_bootloader_init(struct vb2_ui_context *ui) -{ - if (get_menu(ui)->num_items == 0) { - ui->error_code = VB2_UI_ERROR_NO_BOOTLOADER; - return vb2_ui_screen_back(ui); - } - /* Select the first bootloader. */ - ui->state->selected_item = - ARRAY_SIZE(developer_select_bootloader_items_before); - return VB2_REQUEST_UI_CONTINUE; -} - -vb2_error_t vb2_ui_developer_mode_boot_alternate_action( - struct vb2_ui_context *ui) -{ - uint32_t altfw_num; - const size_t menu_before_len = - ARRAY_SIZE(developer_select_bootloader_items_before); - - if (!(ui->ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) || - !vb2_dev_boot_allowed(ui->ctx) || - !vb2_dev_boot_legacy_allowed(ui->ctx)) { - VB2_DEBUG("ERROR: Dev mode alternate bootloader not allowed\n"); - ui->error_code = VB2_UI_ERROR_ALTERNATE_BOOT_DISABLED; - return VB2_REQUEST_UI_CONTINUE; - } - - if (vb2ex_get_bootloader_count() == 0) { - VB2_DEBUG("ERROR: No alternate bootloader was found\n"); - ui->error_code = VB2_UI_ERROR_NO_BOOTLOADER; - return VB2_REQUEST_UI_CONTINUE; - } - - if (ui->key == VB_KEY_CTRL('L')) { - altfw_num = 0; - VB2_DEBUG("Try booting from default bootloader\n"); - } else { - altfw_num = ui->state->selected_item - menu_before_len + 1; - VB2_DEBUG("Try booting from bootloader #%u\n", altfw_num); - } - - /* VbExLegacy will not return if successful */ - VbExLegacy(altfw_num); - - VB2_DEBUG("ERROR: Alternate bootloader failed\n"); - ui->error_code = VB2_UI_ERROR_ALTERNATE_BOOT_FAILED; - return VB2_REQUEST_UI_CONTINUE; -} - -static const struct vb2_menu *get_bootloader_menu(struct vb2_ui_context *ui) -{ - int i; - uint32_t num_bootloaders, num_items; - struct vb2_menu_item *items; - const size_t menu_before_len = - ARRAY_SIZE(developer_select_bootloader_items_before); - const size_t menu_after_len = - ARRAY_SIZE(developer_select_bootloader_items_after); - - if (ui->bootloader_menu.num_items > 0) - return &ui->bootloader_menu; - - num_bootloaders = vb2ex_get_bootloader_count(); - if (num_bootloaders == 0) { - VB2_DEBUG("ERROR: No bootloader was found\n"); - return NULL; - } - VB2_DEBUG("num_bootloaders: %u\n", num_bootloaders); - num_items = num_bootloaders + menu_before_len + menu_after_len; - items = malloc(num_items * sizeof(struct vb2_menu_item)); - if (!items) { - VB2_DEBUG("ERROR: malloc failed for bootloader items\n"); - return NULL; - } - - /* Copy prefix items to the begin. */ - memcpy(&items[0], - developer_select_bootloader_items_before, - menu_before_len * sizeof(struct vb2_menu_item)); - - /* Copy bootloaders. */ - for (i = 0; i < num_bootloaders; i++) { - items[i + menu_before_len].text = "Some bootloader"; - items[i + menu_before_len].action = - vb2_ui_developer_mode_boot_alternate_action; - } - - /* Copy postfix items to the end. */ - memcpy(&items[num_items - menu_after_len], - developer_select_bootloader_items_after, - menu_after_len * sizeof(struct vb2_menu_item)); - - ui->bootloader_menu.num_items = num_items; - ui->bootloader_menu.items = items; - - return &ui->bootloader_menu; -} - -static const struct vb2_screen_info developer_select_bootloader_screen = { - .id = VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER, - .name = "Select alternate bootloader", - .init = developer_select_bootloader_init, - .get_menu = get_bootloader_menu, -}; - -/******************************************************************************/ -/* VB2_SCREEN_DIAGNOSTICS */ - -static const struct vb2_menu_item diagnostics_items[] = { - LANGUAGE_SELECT_ITEM, - { - .text = "Storage", - .target = VB2_SCREEN_DIAGNOSTICS_STORAGE, - }, - { - .text = "Quick memory check", - .target = VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK, - }, - { - .text = "Full memory check", - .target = VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL, - }, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info diagnostics_screen = { - .id = VB2_SCREEN_DIAGNOSTICS, - .name = "Diagnostic tools", - .menu = MENU_ITEMS(diagnostics_items), -}; - -/******************************************************************************/ -/* VB2_SCREEN_DIAGNOSTICS_STORAGE */ - -#define DIAGNOSTICS_STORAGE_ITEM_PAGE_UP 0 -#define DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN 1 -#define DIAGNOSTICS_STORAGE_ITEM_BACK 2 - -static vb2_error_t diagnostics_storage_init(struct vb2_ui_context *ui) -{ - const char *log_string = vb2ex_get_diagnostic_storage(); - if (!log_string) { - VB2_DEBUG("ERROR: Failed to retrieve storage log message\n"); - ui->error_code = VB2_UI_ERROR_DIAGNOSTICS; - return vb2_ui_screen_back(ui); - } - - ui->state->page_count = vb2ex_prepare_log_screen(log_string); - if (ui->state->page_count == 0) { - VB2_DEBUG("ERROR: Failed to prepare storage log screen\n"); - ui->error_code = VB2_UI_ERROR_DIAGNOSTICS; - return vb2_ui_screen_back(ui); - } - return log_page_init(ui); -} - -static const struct vb2_menu_item diagnostics_storage_items[] = { - [DIAGNOSTICS_STORAGE_ITEM_PAGE_UP] = PAGE_UP_ITEM, - [DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM, - [DIAGNOSTICS_STORAGE_ITEM_BACK] = BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info diagnostics_storage_screen = { - .id = VB2_SCREEN_DIAGNOSTICS_STORAGE, - .name = "Storage", - .init = diagnostics_storage_init, - .menu = MENU_ITEMS(diagnostics_storage_items), - .page_up_item = DIAGNOSTICS_STORAGE_ITEM_PAGE_UP, - .page_down_item = DIAGNOSTICS_STORAGE_ITEM_PAGE_DOWN, - .back_item = DIAGNOSTICS_STORAGE_ITEM_BACK, -}; - -/******************************************************************************/ -/* VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK - VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL */ - -#define DIAGNOSTICS_MEMORY_ITEM_PAGE_UP 0 -#define DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN 1 -#define DIAGNOSTICS_MEMORY_ITEM_CANCEL 2 -#define DIAGNOSTICS_MEMORY_ITEM_BACK 3 - -typedef vb2_error_t (*memory_test_op_t)(int reset, const char **out); -static vb2_error_t diagnostics_memory_update_screen(struct vb2_ui_context *ui, - memory_test_op_t op, - int reset) -{ - const char *log_string = NULL; - - /* Early return if the memory test is done. */ - if (ui->state->test_finished) - return VB2_REQUEST_UI_CONTINUE; - - vb2_error_t rv = op(reset, &log_string); - - /* The test is still running but the output buffer was unchanged. */ - if (rv == VB2_ERROR_EX_DIAG_TEST_RUNNING) - return VB2_REQUEST_UI_CONTINUE; - - if ((rv && rv != VB2_ERROR_EX_DIAG_TEST_UPDATED) || !log_string) { - VB2_DEBUG("ERROR: Failed to retrieve memory test status\n"); - ui->error_code = VB2_UI_ERROR_DIAGNOSTICS; - return vb2_ui_screen_back(ui); - } - - ui->state->page_count = vb2ex_prepare_log_screen(log_string); - if (ui->state->page_count == 0) { - VB2_DEBUG("ERROR: Failed to prepare memory log screen, error: " - "%#x\n", rv); - ui->error_code = VB2_UI_ERROR_DIAGNOSTICS; - return vb2_ui_screen_back(ui); - } - if (ui->state->current_page >= ui->state->page_count) - ui->state->current_page = ui->state->page_count - 1; - - ui->force_display = 1; - - /* Show cancel button when the test is running, otherwise show the back - * button. VB2_SUCCESS indicates the test is finished. */ - VB2_CLR_BIT(ui->state->hidden_item_mask, - DIAGNOSTICS_MEMORY_ITEM_CANCEL); - VB2_CLR_BIT(ui->state->hidden_item_mask, DIAGNOSTICS_MEMORY_ITEM_BACK); - if (rv == VB2_ERROR_EX_DIAG_TEST_UPDATED) { - VB2_SET_BIT(ui->state->hidden_item_mask, - DIAGNOSTICS_MEMORY_ITEM_BACK); - if (ui->state->selected_item == DIAGNOSTICS_MEMORY_ITEM_BACK) - ui->state->selected_item = - DIAGNOSTICS_MEMORY_ITEM_CANCEL; - } else { - VB2_SET_BIT(ui->state->hidden_item_mask, - DIAGNOSTICS_MEMORY_ITEM_CANCEL); - if (ui->state->selected_item == DIAGNOSTICS_MEMORY_ITEM_CANCEL) - ui->state->selected_item = DIAGNOSTICS_MEMORY_ITEM_BACK; - ui->state->test_finished = 1; - } - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t diagnostics_memory_init_quick(struct vb2_ui_context *ui) -{ - return diagnostics_memory_update_screen( - ui, &vb2ex_diag_memory_quick_test, 1); -} - -static vb2_error_t diagnostics_memory_init_full(struct vb2_ui_context *ui) -{ - return diagnostics_memory_update_screen( - ui, &vb2ex_diag_memory_full_test, 1); -} - -static vb2_error_t diagnostics_memory_update_quick(struct vb2_ui_context *ui) -{ - return diagnostics_memory_update_screen( - ui, &vb2ex_diag_memory_quick_test, 0); -} - -static vb2_error_t diagnostics_memory_update_full(struct vb2_ui_context *ui) -{ - return diagnostics_memory_update_screen( - ui, &vb2ex_diag_memory_full_test, 0); -} - -static const struct vb2_menu_item diagnostics_memory_items[] = { - [DIAGNOSTICS_MEMORY_ITEM_PAGE_UP] = PAGE_UP_ITEM, - [DIAGNOSTICS_MEMORY_ITEM_PAGE_DOWN] = PAGE_DOWN_ITEM, - [DIAGNOSTICS_MEMORY_ITEM_CANCEL] = { - .text = "Cancel and go back", - .action = vb2_ui_screen_back, - }, - [DIAGNOSTICS_MEMORY_ITEM_BACK] = BACK_ITEM, - POWER_OFF_ITEM, -}; - -static const struct vb2_screen_info diagnostics_memory_quick_screen = { - .id = VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK, - .name = "Quick memory check", - .init = diagnostics_memory_init_quick, - .action = diagnostics_memory_update_quick, - .menu = MENU_ITEMS(diagnostics_memory_items), -}; - -static const struct vb2_screen_info diagnostics_memory_full_screen = { - .id = VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL, - .name = "Full memory check", - .init = diagnostics_memory_init_full, - .action = diagnostics_memory_update_full, - .menu = MENU_ITEMS(diagnostics_memory_items), -}; - -/******************************************************************************/ -/* - * TODO(chromium:1035800): Refactor UI code across vboot and depthcharge. - * Currently vboot and depthcharge maintain their own copies of menus/screens. - * vboot detects keyboard input and controls the navigation among different menu - * items and screens, while depthcharge performs the actual rendering of each - * screen, based on the menu information passed from vboot. - */ -static const struct vb2_screen_info *screens[] = { - &blank_screen, - &language_select_screen, - &recovery_broken_screen, - &advanced_options_screen, - &debug_info_screen, - &firmware_log_screen, - &recovery_select_screen, - &recovery_invalid_screen, - &recovery_to_dev_screen, - &recovery_phone_step1_screen, - &recovery_phone_step2_screen, - &recovery_disk_step1_screen, - &recovery_disk_step2_screen, - &recovery_disk_step3_screen, - &developer_mode_screen, - &developer_to_norm_screen, - &developer_boot_external_screen, - &developer_invalid_disk_screen, - &developer_select_bootloader_screen, - &diagnostics_screen, - &diagnostics_storage_screen, - &diagnostics_memory_quick_screen, - &diagnostics_memory_full_screen, -}; - -const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen id) -{ - int i; - for (i = 0; i < ARRAY_SIZE(screens); i++) { - if (screens[i]->id == id) - return screens[i]; - } - return NULL; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2api.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2api.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2api.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2api.h 2022-02-11 14:46:09.000000000 +0000 @@ -64,6 +64,17 @@ */ #define VB2_TRY(expr, ...) _VB2_TRY_IMPL(expr, ##__VA_ARGS__, NULL, 0) +/** + * Check if the return value is an error. + * + * @param rv The return value. + * @return True if the value is an error. + */ +static inline int vb2_is_error(vb2_error_t rv) +{ + return rv >= VB2_ERROR_BASE && rv <= VB2_ERROR_MAX; +} + /* Flags for vb2_context. * * Unless otherwise noted, flags are set by verified boot and may be read (but @@ -182,8 +193,12 @@ */ VB2_CONTEXT_NVDATA_V2 = (1 << 18), - /* Allow vendor data to be set via the vendor data ui. */ - VB2_CONTEXT_VENDOR_DATA_SETTABLE = (1 << 19), + /* + * Allow vendor data to be set via the vendor data ui. + * + * Deprecated with CL:2512740. + */ + VB2_CONTEXT_DEPRECATED_VENDOR_DATA_SETTABLE = (1 << 19), /* * Caller may set this before running vb2api_fw_phase1. In this case, @@ -218,6 +233,82 @@ * NO_BOOT means the OS is not allowed to boot. Only relevant for EFS2. */ VB2_CONTEXT_NO_BOOT = (1 << 23), + + /* + * TRUSTED means EC is running an RO copy and PD isn't enabled. At + * least that was last known to the GSC. If EC RO is correctly behaving, + * it doesn't jump to RW when this flag is set. + */ + VB2_CONTEXT_EC_TRUSTED = (1 << 24), + + /* + * Boot into developer mode is allowed by FWMP or GBB flags. + */ + VB2_CONTEXT_DEV_BOOT_ALLOWED = (1 << 25), + + /* + * Boot into developer mode from external disk is allowed by nvdata, + * FWMP or GBB flags. + */ + VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED = (1 << 26), + + /* + * Boot into developer mode from alternate bootloader is allowed by + * nvdata, FWMP or GBB flags. + */ + VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED = (1 << 27), +}; + +/* Boot mode decided in vb2api_fw_phase1. + * + * Boot mode is a constant set by verified boot and may be read (but should not + * be set or cleared) by the caller. + * The boot modes are mutually exclusive. If a boot fulfill more than one + * constraints of the listing boot modes, it will be set to the most important + * one. The priority is the same as the listing order. + */ +enum vb2_boot_mode { + /* Undefined, The boot mode is not set. */ + VB2_BOOT_MODE_UNDEFINED = 0, + + /* + * Manual recovery boot, regardless of dev mode state. + * + * VB2_CONTEXT_RECOVERY_MODE is set and the recovery is physically + * requested (a.k.a. Manual recovery). All other recovery requests + * including manual recovery requested by a (compromised) host will end + * up with a broken screen. + */ + VB2_BOOT_MODE_MANUAL_RECOVERY = 1, + + /* + * Broken screen. + * + * If a recovery boot is not a manual recovery (a.k.a. not requested + * physically), the recovery is not allowed and will end up with + * broken screen. + */ + VB2_BOOT_MODE_BROKEN_SCREEN = 2, + + /* + * Diagnostic boot. + * + * If diagnostic boot is enabled (a.k.a. vb2api_diagnostic_ui_enabled) + * and the nvdata contains VB2_NV_DIAG_REQUEST from previous boot, it + * will boot to diagnostic mode. + */ + VB2_BOOT_MODE_DIAGNOSTICS = 3, + + /* + * Developer boot: self-signed kernel okay. + * + * The developer mode switch is set (a.k.a. VB2_CONTEXT_DEVELOPER_MODE) + * and we are in the developer boot mode. + */ + VB2_BOOT_MODE_DEVELOPER = 4, + + /* Normal boot: kernel must be verified. */ + VB2_BOOT_MODE_NORMAL = 5, }; /* Helper for aligning fields in vb2_context. */ @@ -261,8 +352,8 @@ /* * Secure data for firmware verification stage. Caller must fill this * from some secure non-volatile location before calling - * vb2api_fw_phase1. If the VB2_CONTEXT_SECDATA_CHANGED flag is set - * when a function returns, caller must save the data back to the + * vb2api_fw_phase1. If the VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED flag + * is set when a function returns, caller must save the data back to the * secure non-volatile location and then clear the flag. */ uint8_t secdata_firmware[VB2_SECDATA_FIRMWARE_SIZE]; @@ -294,6 +385,16 @@ */ uint8_t secdata_fwmp[VB2_SECDATA_FWMP_MAX_SIZE]; VB2_PAD_STRUCT(VB2_SECDATA_FWMP_MAX_SIZE, 8); + + /********************************************************************** + * Fields below added in struct version 3.1. + */ + + /* + * Mutually exclusive boot mode. + * This constant is initialized after calling vb2api_fw_phase1(). + */ + const enum vb2_boot_mode boot_mode; }; /* Resource index for vb2ex_read_resource() */ @@ -563,6 +664,15 @@ uint32_t vb2api_secdata_kernel_create_v0(struct vb2_context *ctx); /** + * Create an empty Firmware Management Parameters (FWMP) in secure storage + * context. + * + * @param ctx Context pointer + * @return size of created FWMP secure storage data in bytes + */ +uint32_t vb2api_secdata_fwmp_create(struct vb2_context *ctx); + +/** * Check the validity of firmware management parameters (FWMP) space. * * Checks size, version, and CRC. If the struct size is larger than the size @@ -840,6 +950,14 @@ uint32_t vb2api_get_locale_id(struct vb2_context *ctx); /** + * Set the locale id in nvdata. + * + * @param ctx Vboot context + * @param locale_id The locale id to be set + */ +void vb2api_set_locale_id(struct vb2_context *ctx, uint32_t locale_id); + +/** * Whether phone recovery functionality is enabled or not. * * @param ctx Vboot context @@ -871,12 +989,13 @@ /* Default to boot from external disk. */ VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL = 1, - /* Default to boot legacy OS. */ - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY = 2, + /* Default to boot altfw. */ + VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW = 2, }; /** - * Get the default boot target in developer mode. + * Get the default boot target in developer mode. This function must be called + * after vb2api_kernel_phase1. * * @param ctx Vboot context * @return The developer mode default boot target. @@ -892,6 +1011,37 @@ */ int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx); +/** + * Request to enable developer mode. + * + * Enables the developer flag in vb2_context firmware secdata. Note that + * modified secdata must be saved for change to apply on reboot. + * + * NOTE: Doesn't update the LAST_BOOT_DEVELOPER secdata flag. That should be + * done on the next boot. + * + * @param ctx Vboot context + * @return VB2_SUCCESS if success; error if enabling developer mode is not + * allowed. + */ +vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx); + +/** + * Request to disable developer mode by setting VB2_NV_DIAG_REQUEST. + * + * @param ctx Vboot context + * @return VB2_SUCCESS if success; other errors if the check of + * VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON failed. + */ +vb2_error_t vb2api_disable_developer_mode(struct vb2_context *ctx); + +/** + * Request diagnostics by setting VB2_NV_DIAG_REQUEST. + * + * @param ctx Vboot context + */ +void vb2api_request_diagnostics(struct vb2_context *ctx); + /*****************************************************************************/ /* APIs provided by the caller to verified boot */ @@ -1001,7 +1151,7 @@ * caller may not get a chance to commit this data. * * @param ctx Vboot context - * @returns VB2_SUCCESS, or non-zero error code. + * @return VB2_SUCCESS, or non-zero error code. */ vb2_error_t vb2ex_commit_data(struct vb2_context *ctx); @@ -1011,7 +1161,7 @@ /** * Initialize the TPM. * - * @returns VB2_SUCCESS, or non-zero error code. + * @return VB2_SUCCESS, or non-zero error code. */ vb2_error_t vb2ex_tpm_init(void); @@ -1022,7 +1172,7 @@ * TPM_TakeOwnership, since the TPM device can be opened only by one process at * a time. * - * @returns VB2_SUCCESS, or non-zero error code. + * @return VB2_SUCCESS, or non-zero error code. */ vb2_error_t vb2ex_tpm_close(void); vb2_error_t vb2ex_tpm_open(void); @@ -1057,7 +1207,7 @@ * the TPM RNG directly. Otherwise, an attacker with communication interception * abilities could launch replay attacks by reusing previous nonces. * - * @returns VB2_SUCCESS, or non-zero error code. + * @return VB2_SUCCESS, or non-zero error code. */ vb2_error_t vb2ex_tpm_get_random(uint8_t *buf, uint32_t length); @@ -1089,7 +1239,7 @@ * * @param mode_val Desired TPM mode to set. May be one of ENABLED * or DISABLED from vb2_tpm_mode enum. - * @returns VB2_SUCCESS, or non-zero error code. + * @return VB2_SUCCESS, or non-zero error code. */ vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val); @@ -1202,14 +1352,6 @@ vb2_error_t vb2api_ec_sync(struct vb2_context *ctx); /** - * This is called only if the system implements a keyboard-based (virtual) - * developer switch. It must return true only if the system has an embedded - * controller which is provably running in its RO firmware at the time the - * function is called. - */ -int vb2ex_ec_trusted(void); - -/** * Check if the EC is currently running rewritable code. * * If the EC is in RO code, sets *in_rw=0. @@ -1293,136 +1435,89 @@ /*****************************************************************************/ /* Functions for UI display. */ -/* Helpers for bitmask operations */ -#define VB2_SET_BIT(mask, index) ((mask) |= ((uint32_t)1 << (index))) -#define VB2_CLR_BIT(mask, index) ((mask) &= ~((uint32_t)1 << (index))) -#define VB2_GET_BIT(mask, index) ((mask) & ((uint32_t)1 << (index))) +/** + * UI for a non-manual recovery ("BROKEN"). + * + * Enter the broken screen UI, which shows that an unrecoverable error was + * encountered last boot. Wait for the user to physically reset or shut down. + * + * @param ctx Vboot context + * @return VB2_SUCCESS, or non-zero error code. + */ +vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *ctx); -/* Screens. */ -enum vb2_screen { - /* Blank screen */ - VB2_SCREEN_BLANK = 0x0, - /* Wait screen for EC sync and AUXFW sync */ - VB2_SCREEN_FIRMWARE_SYNC = 0x100, - /* Broken screen */ - VB2_SCREEN_RECOVERY_BROKEN = 0x110, - /* Advanced options */ - VB2_SCREEN_ADVANCED_OPTIONS = 0x120, - /* Language selection screen */ - VB2_SCREEN_LANGUAGE_SELECT = 0x130, - /* Debug info */ - VB2_SCREEN_DEBUG_INFO = 0x140, - /* Firmware log */ - VB2_SCREEN_FIRMWARE_LOG = 0x150, - /* First recovery screen to select recovering from disk or phone */ - VB2_SCREEN_RECOVERY_SELECT = 0x200, - /* Invalid recovery media inserted */ - VB2_SCREEN_RECOVERY_INVALID = 0x201, - /* Confirm transition to developer mode */ - VB2_SCREEN_RECOVERY_TO_DEV = 0x202, - /* Recovery using phone */ - VB2_SCREEN_RECOVERY_PHONE_STEP1 = 0x210, - VB2_SCREEN_RECOVERY_PHONE_STEP2 = 0x211, - /* Recovery using disk */ - VB2_SCREEN_RECOVERY_DISK_STEP1 = 0x220, - VB2_SCREEN_RECOVERY_DISK_STEP2 = 0x221, - VB2_SCREEN_RECOVERY_DISK_STEP3 = 0x222, - /* Developer mode screen */ - VB2_SCREEN_DEVELOPER_MODE = 0x300, - /* Confirm transition to normal mode */ - VB2_SCREEN_DEVELOPER_TO_NORM = 0x310, - /* Developer boot from external disk */ - VB2_SCREEN_DEVELOPER_BOOT_EXTERNAL = 0x320, - /* Invalid external disk inserted */ - VB2_SCREEN_DEVELOPER_INVALID_DISK = 0x330, - /* Select alternate bootloader ("legacy boot") */ - VB2_SCREEN_DEVELOPER_SELECT_BOOTLOADER = 0x340, - /* Diagnostic tools */ - VB2_SCREEN_DIAGNOSTICS = 0x400, - /* Storage diagnostic screen */ - VB2_SCREEN_DIAGNOSTICS_STORAGE = 0x410, - /* Memory diagnostic screens */ - VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK = 0x420, - VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL = 0x421, -}; +/** + * UI for a manual recovery-mode boot. + * + * Enter the recovery menu, which prompts the user to insert recovery media, + * navigate the step-by-step recovery, or enter developer mode if allowed. + * + * @param ctx Vboot context + * @return VB2_SUCCESS, or non-zero error code. + */ +vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *ctx); -enum vb2_ui_error { - /* No error */ - VB2_UI_ERROR_NONE = 0, - /* Dev mode already enabled */ - VB2_UI_ERROR_DEV_MODE_ALREADY_ENABLED, - /* To-norm not allowed */ - VB2_UI_ERROR_TO_NORM_NOT_ALLOWED, - /* Debug info screen initialization failed */ - VB2_UI_ERROR_DEBUG_LOG, - /* External boot not enabled */ - VB2_UI_ERROR_EXTERNAL_BOOT_NOT_ENABLED, - /* Firmware log screen initialization failed */ - VB2_UI_ERROR_FIRMWARE_LOG, - /* Untrusted confirmation */ - VB2_UI_ERROR_UNTRUSTED_CONFIRMATION, - /* Alternate bootloader is disabled */ - VB2_UI_ERROR_ALTERNATE_BOOT_DISABLED, - /* No bootloader was found */ - VB2_UI_ERROR_NO_BOOTLOADER, - /* Alternate bootloader failed */ - VB2_UI_ERROR_ALTERNATE_BOOT_FAILED, - /* Diagnostics internal failure */ - VB2_UI_ERROR_DIAGNOSTICS, -}; +/** + * UI for a developer-mode boot. + * + * Enter the developer menu, which provides options to switch out of developer + * mode, boot from external media, use legacy bootloader, or boot Chrome OS from + * disk. + * + * If a timeout occurs, take the default boot action. + * + * @param ctx Vboot context + * @return VB2_SUCCESS, or non-zero error code. + */ +vb2_error_t vb2ex_developer_ui(struct vb2_context *ctx); /** - * Display UI screen. + * UI for a diagnostic tools boot. * - * @param screen Screen to display. - * @param locale_id Id of current locale. - * @param selected_item Index of the selected menu item. If the screen - * doesn't have a menu, this value will be ignored. - * @param disabled_item_mask Mask for disabled menu items. Bit (1 << idx) - * indicates whether item 'idx' is disabled. - * A disabled menu item is visible and selectable, - * with a different button style. - * @param hidden_item_mask Mask for hidden menu items. Bit (1 << idx) - * indicates whether item 'idx' is hidden. - * A hidden menu item is neither visible nor - * selectable. - * @param timer_disabled Whether timer is disabled or not. Some screen - * descriptions will depend on this value. - * @param current_page Current page number for a log screen. If the - * screen doesn't show logs, this value will be - * ignored. - * @param error_code Error code if an error occurred. - * @return VB2_SUCCESS, or error code on error. - */ -vb2_error_t vb2ex_display_ui(enum vb2_screen screen, - uint32_t locale_id, - uint32_t selected_item, - uint32_t disabled_item_mask, - uint32_t hidden_item_mask, - int timer_disabled, - uint32_t current_page, - enum vb2_ui_error error_code); + * Enter the diagnostic tools menu, which provides debug information and + * diagnostic tests of various hardware components. + * + * @param ctx Vboot context + * @return VB2_SUCCESS, or non-zero error code. + */ +vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *ctx); + +/* Helpers for bitmask operations */ +#define VB2_SET_BIT(mask, index) ((mask) |= ((uint32_t)1 << (index))) +#define VB2_CLR_BIT(mask, index) ((mask) &= ~((uint32_t)1 << (index))) +#define VB2_GET_BIT(mask, index) ((mask) & ((uint32_t)1 << (index))) /** * Check that physical presence button is currently pressed by the user. * - * @returns 1 for pressed, 0 for not. + * @return 1 for pressed, 0 for not. */ int vb2ex_physical_presence_pressed(void); /** * Get the number of supported locales. * - * @returns Number of locales. 0 if none or on error. + * @return Number of locales. 0 if none or on error. */ uint32_t vb2ex_get_locale_count(void); /** * Return the number of available alternate bootloaders. * - * @returns Number of alternate bootloaders. 0 if none or on error. + * @return Number of alternate bootloaders. 0 if none or on error. */ -uint32_t vb2ex_get_bootloader_count(void); +uint32_t vb2ex_get_altfw_count(void); + +/** + * Run alternate bootloader. + * + * @param altfw_id ID of alternate bootloader to run, where + * altfw_id <= vb2ex_get_altfw_count(). 0 for default, + * which corresponds to an alternate bootloader in + * the range 1 <= altfw_id <= vb2ex_getfw_count(). + * @return VB2_SUCCESS, or error code on error. + */ +vb2_error_t vb2ex_run_altfw(uint32_t altfw_id); /** * Delay for at least the specified number of milliseconds. @@ -1484,29 +1579,30 @@ const char *vb2ex_get_firmware_log(int reset); /** - * Specify the string to be used for an upcoming log screen display. + * Get the health info of the storage. * - * Before a vb2ex_display_ui() call is made for a screen which displays logs, - * the log string should be provided via this function. The total number of - * pages in the log string is returned. If the log string ever changes, this - * function should be called again before the next vb2ex_display_ui() call. - * - * @param str The log string to display. - * @return The number of pages after pagination. 0 if none or error. + * @param out For returning a read-only pointer of full log string which is + * guaranteed to be null-terminated. The function will manage + * memory internally, so the returned pointer will only be valid + * until next call. + * @return VB2_SUCCESS, or error code on error. */ -uint32_t vb2ex_prepare_log_screen(const char *str); +vb2_error_t vb2ex_diag_get_storage_health(const char **out); /** - * Get the full storage diagnostic log. + * Get the storage self-test log. * - * Return a pointer of full log string which is guaranteed to be - * null-terminated. The function implementation should manage string memory - * internally. Subsequent calls may update the string and/or may return a new - * pointer. - * - * @return The pointer to the full debug info string. NULL on error. + * @param out For returning a read-only pointer of full log string which is + * guaranteed to be null-terminated. The function will manage + * memory internally, so the returned pointer will only be valid + * until next call. + * @return The status of storage test. VB2_SUCCESS means the test is finished, + * regardless of passing or failing. VB2_ERROR_EX_DIAG_TEST_RUNNING means + * the test is still running. VB2_ERROR_EX_UNIMPLEMENTED means the storage + * self-test is not supported on this device. Other non-zero codes for internal + * errors. */ -const char *vb2ex_get_diagnostic_storage(void); +vb2_error_t vb2ex_diag_get_storage_test_log(const char **out); /** * Get the memory diagnostic status. When it is called, it will take over the diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2common.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2common.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2common.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2common.h 2022-02-11 14:46:09.000000000 +0000 @@ -10,6 +10,8 @@ #include "2api.h" #include "2gbb.h" +#include "2misc.h" +#include "2packed_key.h" #include "2return_codes.h" #include "2sha.h" #include "2struct.h" @@ -65,7 +67,8 @@ #define VB2_REC_OR_DIE(ctx, format, args...) do { \ VB2_DEBUG(format, ## args); \ - if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { \ + if ((vb2_get_sd(ctx)->status & VB2_SD_STATUS_RECOVERY_DECIDED) && \ + !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) { \ vb2ex_abort(); \ for (;;); \ } \ @@ -84,6 +87,16 @@ #endif #endif +#if (defined(__GNUC__) && __GNUC__ >= 7) +#define VBOOT_FALLTHROUGH __attribute__((__fallthrough__)) +#elif defined(__clang__) +#if __has_attribute(__fallthrough__) +#define VBOOT_FALLTHROUGH __attribute__((__fallthrough__)) +#endif +#else +#define VBOOT_FALLTHROUGH ((void)0) +#endif + /** * Round up a number to a multiple of VB2_WORKBUF_ALIGN * @@ -287,7 +300,7 @@ static inline const uint8_t *vb2_packed_key_data( const struct vb2_packed_key *key) { - return (const uint8_t *)key + key->key_offset; + return (const uint8_t *)((uintptr_t)key + key->key_offset); } /** @@ -320,7 +333,7 @@ static inline const uint8_t *vb2_signature_data( const struct vb2_signature *sig) { - return (const uint8_t *)sig + sig->sig_offset; + return (const uint8_t *)((uintptr_t)sig + sig->sig_offset); } /** @@ -417,4 +430,44 @@ const struct vb2_public_key *key, const struct vb2_workbuf *wb); +/** + * Get the flags for the kernel preamble. + * + * @param preamble Preamble to check + * @return Flags for the preamble. Old preamble versions (<2.2) return 0. + */ +uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble); + +/** + * Verify a keyblock using its hash. + * + * Header fields are also checked for validity. Does not verify key index or key + * block flags. Use this for self-signed keyblocks in developer mode. + * + * @param block Keyblock to verify + * @param size Size of keyblock buffer + * @param key Key to use to verify block + * @param wb Work buffer + * @return VB2_SUCCESS, or non-zero error code if error. + */ +vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block, + uint32_t size, + const struct vb2_workbuf *wb); + +/** + * Check the validity of a kernel preamble using a public key. + * + * The signature in the preamble is destroyed during the check. + * + * @param preamble Preamble to verify + * @param size Size of preamble buffer + * @param key Key to use to verify preamble + * @param wb Work buffer + * @return VB2_SUCCESS, or non-zero error code if error. + */ +vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb); + #endif /* VBOOT_REFERENCE_2COMMON_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2gbb_flags.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2gbb_flags.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2gbb_flags.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2gbb_flags.h 2022-02-11 14:46:09.000000000 +0000 @@ -53,8 +53,8 @@ /* Allow Enter key to trigger dev->tonorm screen transition */ VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM = 1 << 6, - /* Allow booting Legacy OSes in dev mode even if dev_boot_legacy=0. */ - VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY = 1 << 7, + /* Allow booting Legacy OSes in dev mode even if dev_boot_altfw=0. */ + VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW = 1 << 7, /* * Currently running FAFT tests. May be used as a hint to disable @@ -69,7 +69,7 @@ VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC = 1 << 9, /* Default to booting legacy OS when dev screen times out */ - VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY = 1 << 10, + VB2_GBB_FLAG_DEFAULT_DEV_BOOT_ALTFW = 1 << 10, /* Disable auxiliary firmware (auxfw) software sync */ VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC = 1 << 11, diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2misc.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2misc.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2misc.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2misc.h 2022-02-11 14:46:09.000000000 +0000 @@ -162,32 +162,6 @@ vb2_error_t vb2_load_kernel_preamble(struct vb2_context *ctx); /** - * Utility function to enable developer mode. - * - * Enables the developer flag in vb2_context firmware secdata. Note that - * modified secdata must be saved for change to apply on reboot. - * - * NOTE: Doesn't update the LAST_BOOT_DEVELOPER secdata flag. That should be - * done on the next boot. - * - * @param ctx Vboot context - */ -void vb2_enable_developer_mode(struct vb2_context *ctx); - -/** - * Check whether recovery is allowed or not. - * - * The only way to pass this check and proceed to the recovery process is to - * physically request a recovery (a.k.a. manual recovery). All other recovery - * requests including manual recovery requested by a (compromised) host will - * end up with 'broken' screen. - * - * @param ctx Vboot context - * @return 1 if recovery is allowed; 0 if no or uncertain. - */ -int vb2_allow_recovery(struct vb2_context *ctx); - -/** * Clear recovery request appropriately. * * To avoid the recovery request "sticking" and the user being in a permanent @@ -210,38 +184,26 @@ void vb2_clear_recovery(struct vb2_context *ctx); /** - * Determine if developer mode is allowed. - * - * Developer boot is not allowed if and only if FWMP_DEV_DISABLE_BOOT is set and - * GBB_FORCE_DEV_SWITCH_ON is not set. + * Fill VB2_CONTEXT_DEV_BOOT_ALLOWED, VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED and + * VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED flags in ctx->flags. * - * @param ctx Vboot context - * @return 1 if allowed, or 0 otherwise. + * @param ctx Vboot context. */ -int vb2_dev_boot_allowed(struct vb2_context *ctx); +void vb2_fill_dev_boot_flags(struct vb2_context *ctx); /** - * Determine if booting from legacy BIOS is allowed. - * - * Legacy BIOS is allowed if any of these flags are set: - * VB2_NV_DEV_BOOT_LEGACY, VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY, and - * VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY. + * Determine and set a mutually exclusive boot mode in the vboot context. * - * @param ctx Vboot context - * @return 1 if allowed, or 0 otherwise. - */ -int vb2_dev_boot_legacy_allowed(struct vb2_context *ctx); - -/** - * Determine if booting from external disk is allowed. + * Determine the most relevant boot mode for current boot, store into + * ctx->boot_mode, which is a ctx field introduced in struct version 3.1. * - * Booting from external disk is allowed if any of these flags are set: - * VB2_NV_DEV_BOOT_EXTERNAL, VB2_GBB_FLAG_FORCE_DEV_BOOT_USB, and - * VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL. + * This function should be only called by vb2api_fw_phase1. + * The vb2api_fw_phase1 should call this function at its end phase once and all + * the following steps should directly access ctx->boot_mode to retrieve the + * most relevant boot mode. * - * @param ctx Vboot context - * @return 1 if allowed, or 0 otherwise. + * @param ctx Vboot context. */ -int vb2_dev_boot_external_allowed(struct vb2_context *ctx); +void vb2_set_boot_mode(struct vb2_context *ctx); #endif /* VBOOT_REFERENCE_2MISC_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2nvstorage_fields.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2nvstorage_fields.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2nvstorage_fields.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2nvstorage_fields.h 2022-02-11 14:46:09.000000000 +0000 @@ -79,7 +79,7 @@ #define VB2_NV_BOOT_DISABLE_DEV 0x40 #define VB2_NV_BOOT_DEBUG_RESET 0x80 -/* Fields in VB2_NV_OFFS_BOOT2 (unused = 0x00) */ +/* Fields in VB2_NV_OFFS_BOOT2 */ #define VB2_NV_BOOT2_RESULT_MASK 0x03 #define VB2_NV_BOOT2_TRIED 0x04 #define VB2_NV_BOOT2_TRY_NEXT 0x08 @@ -102,11 +102,12 @@ #define VB2_NV_TPM_CLEAR_OWNER_DONE 0x02 #define VB2_NV_TPM_REBOOTED 0x04 -/* Fields in VB2_NV_OFFS_MISC (unused = 0x80) */ +/* Fields in VB2_NV_OFFS_MISC (unused = 0xa0) */ #define VB2_NV_MISC_DEPRECATED_UNLOCK_FASTBOOT 0x01 #define VB2_NV_MISC_BOOT_ON_AC_DETECT 0x02 #define VB2_NV_MISC_TRY_RO_SYNC 0x04 #define VB2_NV_MISC_BATTERY_CUTOFF 0x08 +#define VB2_NV_MISC_MINIOS_PRIORITY 0x10 #define VB2_NV_MISC_POST_EC_SYNC_DELAY 0x40 #endif /* VBOOT_REFERENCE_2NVSTORAGE_FIELDS_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2nvstorage.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2nvstorage.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2nvstorage.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2nvstorage.h 2022-02-11 14:46:09.000000000 +0000 @@ -49,7 +49,7 @@ /* Allow booting from external disk in developer mode. 0=no, 1=yes. */ VB2_NV_DEV_BOOT_EXTERNAL, /* Allow booting of legacy OSes in developer mode. 0=no, 1=yes. */ - VB2_NV_DEV_BOOT_LEGACY, + VB2_NV_DEV_BOOT_ALTFW, /* Only boot Google-signed images in developer mode. 0=no, 1=yes. */ VB2_NV_DEV_BOOT_SIGNED_ONLY, /* @@ -125,6 +125,8 @@ VB2_NV_POST_EC_SYNC_DELAY, /* Request booting of diagnostic rom. 0=no, 1=yes. */ VB2_NV_DIAG_REQUEST, + /* Priority of miniOS partition to load: 0=MINIOS-A, 1=MINIOS-B. */ + VB2_NV_MINIOS_PRIORITY, }; /* Firmware result codes for VB2_NV_FW_RESULT and VB2_NV_FW_PREV_RESULT */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2packed_key.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2packed_key.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2packed_key.h 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2packed_key.h 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,39 @@ +/* Copyright 2021 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. + * + * Functions related to unpacking keys and key buffers. + */ + +#ifndef VBOOT_REFERENCE_2PACKED_KEY_H_ +#define VBOOT_REFERENCE_2PACKED_KEY_H_ + +/** + * Unpack a vboot1-format key buffer for use in verification + * + * The elements of the unpacked key will point into the source buffer, so don't + * free the source buffer until you're done with the key. + * + * @param key Destintion for unpacked key + * @param buf Source buffer containing packed key + * @param size Size of buffer in bytes + * @return VB2_SUCCESS, or non-zero error code if error. + */ +vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, + const uint8_t *buf, uint32_t size); + +/** + * Unpack a vboot1-format key for use in verification + * + * The elements of the unpacked key will point into the source packed key, so + * don't free the source until you're done with the public key. + * + * @param key Destintion for unpacked key + * @param packed_key Source packed key + * @param size Size of buffer in bytes + * @return VB2_SUCCESS, or non-zero error code if error. + */ +vb2_error_t vb2_unpack_key(struct vb2_public_key *key, + const struct vb2_packed_key *packed_key); + +#endif /* VBOOT_REFERENCE_2PACKED_KEY_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2recovery_reasons.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2recovery_reasons.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2recovery_reasons.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2recovery_reasons.h 2022-02-11 14:46:09.000000000 +0000 @@ -14,7 +14,7 @@ * Return a description of the recovery reason code. * * @param recovery reason code - * @returns A string literal with English description of the recovery reason + * @return A string literal with English description of the recovery reason */ const char *vb2_get_recovery_reason_string(uint8_t code); @@ -265,8 +265,8 @@ /* Failed to disable the TPM [prior to running untrusted code] */ VB2_RECOVERY_TPM_DISABLE_FAILED = 0x60, - /* Alt FW Failed hash verification */ - VB2_RECOVERY_ALTFW_HASH_FAILED = 0x61, + /* Verification of altfw payload failed (deprecated) */ + VB2_RECOVERY_ALTFW_HASH_MISMATCH = 0x61, /* FWMP secure data initialization error */ VB2_RECOVERY_SECDATA_FWMP_INIT = 0x62, diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2return_codes.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2return_codes.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2return_codes.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2return_codes.h 2022-02-11 14:46:09.000000000 +0000 @@ -29,7 +29,7 @@ */ VB2_REQUEST = 0x1000, - /* Calling firmware requested shutdown via VbExIsShutdownRequested() */ + /* Calling firmware requested shutdown */ VB2_REQUEST_SHUTDOWN = 0x1001, /* Calling firmware needs to perform a reboot */ @@ -44,6 +44,9 @@ /* Continue in the UI loop. This is used in UI internal functions. */ VB2_REQUEST_UI_CONTINUE = 0x1005, + /* Break from the UI loop. This is used in UI internal functions. */ + VB2_REQUEST_UI_EXIT = 0x1006, + /* End of VB2_REQUEST_* */ VB2_REQUEST_END = 0x5000, @@ -395,6 +398,9 @@ /* No signature matching key ID */ VB2_ERROR_KEYBLOCK_SIG_ID, + /* Invalid keyblock hash in dev mode (self-signed kernel) */ + VB2_ERROR_KEYBLOCK_HASH_INVALID_IN_DEV_MODE, + /********************************************************************** * Preamble verification errors (all in vb2_verify_preamble()) */ @@ -448,164 +454,174 @@ VB2_ERROR_MISC = VB2_ERROR_BASE + 0x080000, /* Work buffer too small (see vb2api_init and vb2api_reinit) */ - VB2_ERROR_WORKBUF_SMALL, + VB2_ERROR_WORKBUF_SMALL = 0x10080001, /* Work buffer unaligned (see vb2api_init and vb2api_reinit) */ - VB2_ERROR_WORKBUF_ALIGN, + VB2_ERROR_WORKBUF_ALIGN = 0x10080002, /* Work buffer too small in GBB-related function */ - VB2_ERROR_GBB_WORKBUF, + VB2_ERROR_GBB_WORKBUF = 0x10080003, /* Bad magic number in vb2_read_gbb_header() */ - VB2_ERROR_GBB_MAGIC, + VB2_ERROR_GBB_MAGIC = 0x10080004, /* Incompatible version in vb2_read_gbb_header() */ - VB2_ERROR_GBB_VERSION, + VB2_ERROR_GBB_VERSION = 0x10080005, /* Old version in vb2_read_gbb_header() */ - VB2_ERROR_GBB_TOO_OLD, + VB2_ERROR_GBB_TOO_OLD = 0x10080006, /* Header size too small in vb2_read_gbb_header() */ - VB2_ERROR_GBB_HEADER_SIZE, + VB2_ERROR_GBB_HEADER_SIZE = 0x10080007, /* Work buffer too small for root key in vb2_load_fw_keyblock() */ - VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY, + VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY = 0x10080008, /* Work buffer too small for header in vb2_load_fw_keyblock() */ - VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER, + VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER = 0x10080009, /* Work buffer too small for keyblock in vb2_load_fw_keyblock() */ - VB2_ERROR_FW_KEYBLOCK_WORKBUF, + VB2_ERROR_FW_KEYBLOCK_WORKBUF = 0x1008000a, /* Keyblock version out of range in vb2_load_fw_keyblock() */ - VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE, + VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE = 0x1008000b, /* Keyblock version rollback in vb2_load_fw_keyblock() */ - VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK, + VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK = 0x1008000c, /* Missing firmware data key in vb2_load_fw_preamble() */ - VB2_ERROR_FW_PREAMBLE2_DATA_KEY, + VB2_ERROR_FW_PREAMBLE2_DATA_KEY = 0x1008000d, /* Work buffer too small for header in vb2_load_fw_preamble() */ - VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER, + VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER = 0x1008000e, /* Work buffer too small for preamble in vb2_load_fw_preamble() */ - VB2_ERROR_FW_PREAMBLE2_WORKBUF, + VB2_ERROR_FW_PREAMBLE2_WORKBUF = 0x1008000f, /* Firmware version out of range in vb2_load_fw_preamble() */ - VB2_ERROR_FW_PREAMBLE_VERSION_RANGE, + VB2_ERROR_FW_PREAMBLE_VERSION_RANGE = 0x10080010, /* Firmware version rollback in vb2_load_fw_preamble() */ - VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK, + VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK = 0x10080011, /* Not enough space in work buffer for resource object */ - VB2_ERROR_READ_RESOURCE_OBJECT_BUF, + VB2_ERROR_READ_RESOURCE_OBJECT_BUF = 0x10080012, /* Work buffer too small for header in vb2_load_kernel_keyblock() */ - VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER, + VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF_HEADER = 0x10080013, /* Work buffer too small for keyblock in vb2_load_kernel_keyblock() */ - VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF, + VB2_ERROR_KERNEL_KEYBLOCK_WORKBUF = 0x10080014, /* Keyblock version out of range in vb2_load_kernel_keyblock() */ - VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE, + VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE = 0x10080015, /* Keyblock version rollback in vb2_load_kernel_keyblock() */ - VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK, + VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK = 0x10080016, /* * Keyblock flags don't match current mode in * vb2_load_kernel_keyblock(). */ - VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG, - VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG, + VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG = 0x10080017, + VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG = 0x10080018, /* Missing firmware data key in vb2_load_kernel_preamble() */ - VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY, + VB2_ERROR_KERNEL_PREAMBLE2_DATA_KEY = 0x10080019, /* Work buffer too small for header in vb2_load_kernel_preamble() */ - VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER, + VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF_HEADER = 0x1008001a, /* Work buffer too small for preamble in vb2_load_kernel_preamble() */ - VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF, + VB2_ERROR_KERNEL_PREAMBLE2_WORKBUF = 0x1008001b, /* Kernel version out of range in vb2_load_kernel_preamble() */ - VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE, + VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE = 0x1008001c, /* Kernel version rollback in vb2_load_kernel_preamble() */ - VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK, + VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK = 0x1008001d, /* Kernel preamble not loaded before calling vb2api_get_kernel_size() */ - VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE, + VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE = 0x1008001e, - /* Unable to unpack kernel subkey in vb2_verify_vblock() */ - VB2_ERROR_VBLOCK_KERNEL_SUBKEY, + /* Unable to unpack kernel subkey in vb2_verify_vblock(); + * deprecated and replaced with VB2_ERROR_UNPACK_KEY_* */ + VB2_ERROR_DEPRECATED_VBLOCK_KERNEL_SUBKEY = 0x1008001f, /* * Got a self-signed kernel in vb2_verify_vblock(), but need an - * officially signed one. + * officially signed one; deprecated and replaced with + * VB2_ERROR_KERNEL_KEYBLOCK_*. */ - VB2_ERROR_VBLOCK_SELF_SIGNED, + VB2_ERROR_DEPRECATED_VBLOCK_SELF_SIGNED = 0x10080020, - /* Invalid keyblock hash in vb2_verify_vblock() */ - VB2_ERROR_VBLOCK_KEYBLOCK_HASH, + /* Invalid keyblock hash in vb2_verify_vblock(); + * deprecated and replaced with VB2_ERROR_KERNEL_KEYBLOCK_* */ + VB2_ERROR_DEPRECATED_VBLOCK_KEYBLOCK_HASH = 0x10080021, - /* Invalid keyblock in vb2_verify_vblock() */ - VB2_ERROR_VBLOCK_KEYBLOCK, + /* Invalid keyblock in vb2_verify_vblock(); + * deprecated and replaced with VB2_ERROR_KERNEL_KEYBLOCK_* */ + VB2_ERROR_DEPRECATED_VBLOCK_KEYBLOCK = 0x10080022, - /* Wrong developer key hash in vb2_verify_vblock() */ - VB2_ERROR_VBLOCK_DEV_KEY_HASH, + /* Wrong dev key hash in vb2_verify_kernel_vblock_dev_key_hash() */ + VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH = 0x10080023, /* Work buffer too small in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_WORKBUF, + VB2_ERROR_LOAD_PARTITION_WORKBUF = 0x10080024, /* Unable to read vblock in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_READ_VBLOCK, + VB2_ERROR_LOAD_PARTITION_READ_VBLOCK = 0x10080025, /* Unable to verify vblock in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK, + VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK = 0x10080026, /* Kernel body offset too large in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_BODY_OFFSET, + VB2_ERROR_LOAD_PARTITION_BODY_OFFSET = 0x10080027, /* Kernel body too big in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_BODY_SIZE, + VB2_ERROR_LOAD_PARTITION_BODY_SIZE = 0x10080028, /* Unable to read kernel body in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_READ_BODY, + VB2_ERROR_LOAD_PARTITION_READ_BODY = 0x10080029, /* Unable to unpack data key in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_DATA_KEY, + VB2_ERROR_LOAD_PARTITION_DATA_KEY = 0x1008002a, /* Unable to verify body in vb2_load_partition() */ - VB2_ERROR_LOAD_PARTITION_VERIFY_BODY, + VB2_ERROR_LOAD_PARTITION_VERIFY_BODY = 0x1008002b, /* Unable to get EC image hash in ec_sync_phase1() */ - VB2_ERROR_EC_HASH_IMAGE, + VB2_ERROR_EC_HASH_IMAGE = 0x1008002c, /* Unable to get expected EC image hash in ec_sync_phase1() */ - VB2_ERROR_EC_HASH_EXPECTED, + VB2_ERROR_EC_HASH_EXPECTED = 0x1008002d, /* Expected and image hashes are different size in ec_sync_phase1() */ - VB2_ERROR_EC_HASH_SIZE, + VB2_ERROR_EC_HASH_SIZE = 0x1008002e, /* Incompatible version for vb2_shared_data structure being loaded */ - VB2_ERROR_SHARED_DATA_VERSION, + VB2_ERROR_SHARED_DATA_VERSION = 0x1008002f, /* Bad magic number in vb2_shared_data structure */ - VB2_ERROR_SHARED_DATA_MAGIC, + VB2_ERROR_SHARED_DATA_MAGIC = 0x10080030, /* Some part of GBB data is invalid */ - VB2_ERROR_GBB_INVALID, + VB2_ERROR_GBB_INVALID = 0x10080031, /* Invalid parameter */ - VB2_ERROR_INVALID_PARAMETER, + VB2_ERROR_INVALID_PARAMETER = 0x10080032, /* Problem with workbuf validity (see vb2api_init and vb2api_reinit) */ - VB2_ERROR_WORKBUF_INVALID, + VB2_ERROR_WORKBUF_INVALID = 0x10080033, - /* Escape from NO_BOOT mode is detected. */ - VB2_ERROR_ESCAPE_NO_BOOT, + /* Escape from NO_BOOT mode is detected */ + VB2_ERROR_ESCAPE_NO_BOOT = 0x10080034, + + /* + * Keyblock flags don't match current mode in + * vb2_load_kernel_keyblock(). + */ + VB2_ERROR_KERNEL_KEYBLOCK_MINIOS_FLAG = 0x10080035, /********************************************************************** * API-level errors @@ -691,6 +707,12 @@ /* Digest buffer passed into vb2api_check_hash incorrect. */ VB2_ERROR_API_CHECK_DIGEST_SIZE, + /* Disabling developer mode is not allowed by GBB flags */ + VB2_ERROR_API_DISABLE_DEV_NOT_ALLOWED, + + /* Enabling developer mode is not allowed in non-recovery mode */ + VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED, + /********************************************************************** * Errors which may be generated by implementations of vb2ex functions. * Implementation may also return its own specific errors, which should @@ -728,8 +750,9 @@ /* AUXFW peripheral busy. Cannot upgrade firmware at present. */ VB2_ERROR_EX_AUXFW_PERIPHERAL_BUSY, - /* Error setting vendor data (see: VbExSetVendorData). */ - VB2_ERROR_EX_SET_VENDOR_DATA, + /* Error setting vendor data (see: VbExSetVendorData). + * Deprecated: functionality removed with legacy UI (b/167643628) */ + VB2_ERROR_DEPRECATED_EX_SET_VENDOR_DATA, /* The memory test is running but the output buffer was unchanged. */ VB2_ERROR_EX_DIAG_TEST_RUNNING, diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2rsa_private.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2rsa_private.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2rsa_private.h 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2rsa_private.h 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,21 @@ +/* Copyright 2021 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. + * + * Internal functions from 2rsa.c that have error conditions we can't trigger + * from the public APIs. These include checks for bad algorithms where the + * next call level up already checks for bad algorithms, etc. + * + * These functions aren't in 2rsa.h because they're not part of the public + * APIs. + */ + +#ifndef VBOOT_REFERENCE_2RSA_PRIVATE_H_ +#define VBOOT_REFERENCE_2RSA_PRIVATE_H_ + +struct vb2_public_key; +int vb2_mont_ge(const struct vb2_public_key *key, uint32_t *a); +vb2_error_t vb2_check_padding(const uint8_t *sig, + const struct vb2_public_key *key); + +#endif /* VBOOT_REFERENCE_2RSA_PRIVATE_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2secdata.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2secdata.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2secdata.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2secdata.h 2022-02-11 14:46:09.000000000 +0000 @@ -109,14 +109,18 @@ VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED = (1 << 2), /* - * Allow HW acceleration for RSA. + * Allow HW acceleration for crypto * - * RW firmware currently set this flag to enable RSA acceleration. - * Verstage will use HW implementation for RSA only when - * this flag is set. + * RW firmware currently set this flag to enable HW acceleration + * for crypto. Verstage will use HW implementation for RSA/SHA + * only when this flag is set. * - * Note: this will only allow/disallow HWCRYPTO for RSA. - * Using HW for hash digest is controlled by flag in the FW preamble. + * Note: We used a flag in the FW preamble for this before. + * FW preamble was checked by verstage so the effect was immediate. + * However with TPM flag we have to modify this in RW stage which is + * after verstage, so even if we clear this flag the first boot + * WILL use hwcrypto, RW stage will run and clear this flag and then + * hwcrypto will be disabled from next boot. */ VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED = (1 << 3), }; @@ -177,7 +181,7 @@ VB2_SECDATA_FWMP_DEV_DISABLE_BOOT = (1 << 0), VB2_SECDATA_FWMP_DEV_DISABLE_RECOVERY = (1 << 1), VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL = (1 << 2), - VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY = (1 << 3), + VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW = (1 << 3), VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY = (1 << 4), VB2_SECDATA_FWMP_DEV_USE_KEY_HASH = (1 << 5), /* CCD = case-closed debugging on cr50; flag implemented on cr50 */ @@ -217,9 +221,10 @@ uint8_t *vb2_secdata_fwmp_get_dev_key_hash(struct vb2_context *ctx); /* - * Helper function to check if hwcrypto for RSA is allowed + * Helper function to check if hwcrypto is allowed. */ -static inline int vb2_hwcrypto_rsa_allowed(struct vb2_context *ctx) { +static inline int vb2_hwcrypto_allowed(struct vb2_context *ctx) +{ /* disable hwcrypto in recovery mode */ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2sha_private.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2sha_private.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2sha_private.h 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2sha_private.h 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,38 @@ +/* Copyright 2021 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. + * + * Constants & macro for sha algorithms. + */ + +#ifndef VBOOT_REFERENCE_2SHA_PRIVATE_H_ +#define VBOOT_REFERENCE_2SHA_PRIVATE_H_ + +/* Sha256 padding is consisted of 0x80 + zeros + length of message (8 byte). + * So minimum length for padding is 9. + */ +#define SHA256_MIN_PAD_LEN 9 + +/* Beginning of sha256 padding is always 0x80 when messages are in bytes + */ +#define SHA256_PAD_BEGIN 0x80 + +extern const uint32_t vb2_sha256_h0[8]; +extern const uint32_t vb2_sha256_k[64]; + +#define UNPACK32(x, str) \ + { \ + *((str) + 3) = (uint8_t) ((x) ); \ + *((str) + 2) = (uint8_t) ((x) >> 8); \ + *((str) + 1) = (uint8_t) ((x) >> 16); \ + *((str) + 0) = (uint8_t) ((x) >> 24); \ + } + +#define PACK32(str, x) \ + { \ + *(x) = ((uint32_t) *((str) + 3) ) \ + | ((uint32_t) *((str) + 2) << 8) \ + | ((uint32_t) *((str) + 1) << 16) \ + | ((uint32_t) *((str) + 0) << 24); \ + } +#endif /* VBOOT_REFERENCE_2SHA_PRIVATE_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2struct.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2struct.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2struct.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2struct.h 2022-02-11 14:46:09.000000000 +0000 @@ -23,8 +23,14 @@ /* Flags for vb2_shared_data.flags */ enum vb2_shared_data_flags { - /* User has explicitly and physically requested recovery */ - VB2_SD_FLAG_MANUAL_RECOVERY = (1 << 0), + /* + * VB2_SD_FLAG_MANUAL_RECOVERY (1 << 0) is deprecated. This flag is not + * necessary since the introduction of persistent context (CL:1716351). + * With introducing vb2_boot_mode and differentiating between manual + * recovery and broken screen (CL:3274699), it is suggested to leverage + * the vb2_boot_mode instead to determine if the user has physically + * requested recovery. + */ /* Developer mode is enabled */ VB2_SD_FLAG_DEV_MODE_ENABLED = (1 << 1), @@ -85,6 +91,8 @@ /* EC Sync completed successfully */ VB2_SD_STATUS_EC_SYNC_COMPLETE = (1 << 6), + /* Have checked whether we are booting into recovery mode or not. */ + VB2_SD_STATUS_RECOVERY_DECIDED = (1 << 7), }; /* "V2SD" = vb2_shared_data.magic */ @@ -92,7 +100,7 @@ /* Current version of vb2_shared_data struct */ #define VB2_SHARED_DATA_VERSION_MAJOR 3 -#define VB2_SHARED_DATA_VERSION_MINOR 0 +#define VB2_SHARED_DATA_VERSION_MINOR 1 /* MAX_SIZE should not be changed without bumping up DATA_VERSION_MAJOR. */ #define VB2_CONTEXT_MAX_SIZE 384 @@ -304,43 +312,6 @@ /****************************************************************************/ -/* - * Root key hash for Ryu devices only. Contains the hash of the root key. - * This will be embedded somewhere inside the RO part of the firmware, so that - * it can verify the GBB contains only the official root key. - */ -#define RYU_ROOT_KEY_HASH_MAGIC "RtKyHash" -#define RYU_ROOT_KEY_HASH_MAGIC_INVCASE "rTkYhASH" -#define RYU_ROOT_KEY_HASH_MAGIC_SIZE 8 - -#define RYU_ROOT_KEY_HASH_VERSION_MAJOR 1 -#define RYU_ROOT_KEY_HASH_VERSION_MINOR 0 - -struct vb2_ryu_root_key_hash { - /* Magic number (RYU_ROOT_KEY_HASH_MAGIC) */ - uint8_t magic[RYU_ROOT_KEY_HASH_MAGIC_SIZE]; - - /* Version of this struct */ - uint16_t header_version_major; - uint16_t header_version_minor; - - /* - * Length of this struct, in bytes, including any variable length data - * which follows (there is none, yet). - */ - uint32_t struct_size; - - /* - * SHA-256 hash digest of the entire root key section from the GBB. If - * all 0 bytes, all root keys will be treated as if matching. - */ - uint8_t root_key_hash_digest[32]; -}; - -#define EXPECTED_VB2_RYU_ROOT_KEY_HASH_SIZE 48 - -/****************************************************************************/ - /* Packed public key data */ struct vb2_packed_key { /* Offset of key data from start of this struct */ @@ -401,6 +372,8 @@ #define VB2_KEYBLOCK_FLAG_DEVELOPER_1 0x2 /* Developer switch on */ #define VB2_KEYBLOCK_FLAG_RECOVERY_0 0x4 /* Not recovery mode */ #define VB2_KEYBLOCK_FLAG_RECOVERY_1 0x8 /* Recovery mode */ +#define VB2_KEYBLOCK_FLAG_MINIOS_0 0x10 /* Not miniOS boot */ +#define VB2_KEYBLOCK_FLAG_MINIOS_1 0x20 /* miniOS boot */ /* * Keyblock, containing the public key used to sign some other chunk of data. @@ -471,7 +444,9 @@ /* Flags for vb2_fw_preamble.flags */ /* Use RO-normal firmware (deprecated; do not use) */ #define VB2_FIRMWARE_PREAMBLE_USE_RO_NORMAL 0x00000001 -/* Do not allow use of any hardware crypto accelerators. */ +/* Do not allow use of any hardware crypto accelerators. + * (deprecated; use VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED instead) + */ #define VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO 0x00000002 /* Premable block for rewritable firmware, vboot1 version 2.1. diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2sysincludes.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2sysincludes.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2sysincludes.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2sysincludes.h 2022-02-11 14:46:09.000000000 +0000 @@ -21,9 +21,4 @@ #include #include -#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN) -#include -#include -#endif - #endif /* VBOOT_REFERENCE_2SYSINCLUDES_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2ui.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2ui.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2ui.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2ui.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,259 +0,0 @@ -/* Copyright 2020 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. - * - * User interfaces for developer and recovery mode menus. - */ - -#ifndef VBOOT_REFERENCE_2UI_H_ -#define VBOOT_REFERENCE_2UI_H_ - -#include <2api.h> -#include <2sysincludes.h> - -/*****************************************************************************/ -/* Data structures */ - -struct vb2_ui_context; /* Forward declaration */ - -struct vb2_menu_item { - /* Text description */ - const char *text; - /* Target screen */ - enum vb2_screen target; - /* Action function takes precedence over target screen if non-NULL. */ - vb2_error_t (*action)(struct vb2_ui_context *ui); - /* Whether the item is language selection */ - int is_language_select; -}; - -struct vb2_menu { - /* Number of menu items */ - uint16_t num_items; - /* List of menu items */ - const struct vb2_menu_item *items; -}; - -struct vb2_screen_info { - /* Screen id */ - enum vb2_screen id; - /* Screen name for printing to console only */ - const char *name; - /* - * Init function runs once when changing to the screen which is not in - * the history stack. - */ - vb2_error_t (*init)(struct vb2_ui_context *ui); - /* - * Re-init function runs once when changing to the screen which is - * already in the history stack, for example, when going back to the - * screen. Exactly one of init() and reinit() will be called. - */ - vb2_error_t (*reinit)(struct vb2_ui_context *ui); - /* Action function runs repeatedly while on the screen. */ - vb2_error_t (*action)(struct vb2_ui_context *ui); - /* Menu items. */ - struct vb2_menu menu; - /* - * Custom function for getting menu items. If non-null, field 'menu' - * will be ignored. - */ - const struct vb2_menu *(*get_menu)(struct vb2_ui_context *ui); - /* - * Indices of menu items; - * used by log_page_* functions in 2ui_screens.c. - */ - uint32_t page_up_item; - uint32_t page_down_item; - uint32_t back_item; -}; - -struct vb2_screen_state { - const struct vb2_screen_info *screen; - uint32_t selected_item; - uint32_t disabled_item_mask; - uint32_t hidden_item_mask; - - /* For log screen. */ - uint32_t page_count; - uint32_t current_page; - - /* For memory check screen. */ - int test_finished; /* Do not update screen if the content is done */ - - struct vb2_screen_state *prev; -}; - -enum vb2_power_button { - VB2_POWER_BUTTON_HELD_SINCE_BOOT = 0, - VB2_POWER_BUTTON_RELEASED, - VB2_POWER_BUTTON_PRESSED, /* Must have been previously released */ -}; - -struct vb2_ui_context { - struct vb2_context *ctx; - struct vb2_screen_state *state; - uint32_t locale_id; - uint32_t key; - int key_trusted; - - /* For check_shutdown_request. */ - enum vb2_power_button power_button; - - /* For developer mode. */ - int disable_timer; - uint32_t start_time_ms; - int beep_count; - - /* For manual recovery. */ - vb2_error_t recovery_rv; - - /* For to_dev transition flow. */ - int physical_presence_button_pressed; - - /* For language selection screen. */ - struct vb2_menu language_menu; - - /* For bootloader selection screen. */ - struct vb2_menu bootloader_menu; - - /* For error beep sound. */ - int error_beep; - - /* For displaying error messages. */ - enum vb2_ui_error error_code; - - /* Force calling vb2ex_display_ui for refreshing the screen. This flag - will be reset after done. */ - int force_display; -}; - -vb2_error_t vb2_ui_developer_mode_boot_internal_action( - struct vb2_ui_context *ui); -vb2_error_t vb2_ui_developer_mode_boot_external_action( - struct vb2_ui_context *ui); -vb2_error_t vb2_ui_developer_mode_boot_alternate_action( - struct vb2_ui_context *ui); - -/** - * Get info struct of a screen. - * - * @param screen Screen from enum vb2_screen - * - * @return screen info struct on success, NULL on error. - */ -const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen id); - -/*****************************************************************************/ -/* Menu navigation functions */ - -/** - * Move selection to the previous menu item. - * - * Update selected_item, taking into account hidden indices (from - * hidden_item_mask). The selection does not wrap, meaning that we block - * on 0 when we hit the start of the menu. - * - * @param ui UI context pointer - * @return VB2_REQUEST_UI_CONTINUE, or error code on error. - */ -vb2_error_t vb2_ui_menu_prev(struct vb2_ui_context *ui); - -/** - * Move selection to the next menu item. - * - * Update selected_item, taking into account hidden indices (from - * hidden_item_mask). The selection does not wrap, meaning that we block - * on the max index when we hit the end of the menu. - * - * @param ui UI context pointer - * @return VB2_REQUEST_UI_CONTINUE, or error code on error. - */ -vb2_error_t vb2_ui_menu_next(struct vb2_ui_context *ui); - -/** - * Select the current menu item. - * - * If the current menu item has an action associated with it, run the action. - * Otherwise, navigate to the target screen. If neither of these are set, then - * selecting the menu item is a no-op. - * - * @param ui UI context pointer - * @return VB2_REQUEST_UI_CONTINUE, or error code on error. - */ -vb2_error_t vb2_ui_menu_select(struct vb2_ui_context *ui); - -/*****************************************************************************/ -/* Screen navigation functions */ - -/** - * Return back to the previous screen. - * - * If the current screen is already the root scren, the request is ignored. - * - * @param ui UI context pointer - * @return VB2_REQUEST_UI_CONTINUE, or error code on error. - */ -vb2_error_t vb2_ui_screen_back(struct vb2_ui_context *ui); - -/** - * Change to the given screen. - * - * If the screen is not found, the request is ignored. - * - * @param ui UI context pointer - * @return VB2_REQUEST_UI_CONTINUE, or error code on error. - */ -vb2_error_t vb2_ui_screen_change(struct vb2_ui_context *ui, enum vb2_screen id); - -/*****************************************************************************/ -/* UI loops */ - -/** - * UI for a developer-mode boot. - * - * Enter the developer menu, which provides options to switch out of developer - * mode, boot from external media, use legacy bootloader, or boot Chrome OS from - * disk. - * - * If a timeout occurs, take the default boot action. - * - * @param ctx Vboot context - * @returns VB2_SUCCESS, or non-zero error code. - */ -vb2_error_t vb2_developer_menu(struct vb2_context *ctx); - -/** - * UI for a non-manual recovery ("BROKEN"). - * - * Enter the recovery menu, which shows that an unrecoverable error was - * encountered last boot. Wait for the user to physically reset or shut down. - * - * @param ctx Vboot context - * @returns VB2_SUCCESS, or non-zero error code. - */ -vb2_error_t vb2_broken_recovery_menu(struct vb2_context *ctx); - -/** - * UI for a manual recovery-mode boot. - * - * Enter the recovery menu, which prompts the user to insert recovery media, - * navigate the step-by-step recovery, or enter developer mode if allowed. - * - * @param ctx Vboot context - * @returns VB2_SUCCESS, or non-zero error code. - */ -vb2_error_t vb2_manual_recovery_menu(struct vb2_context *ctx); - -/** - * UI for a diagnostic tools boot. - * - * Enter the diagnostic tools menu, which provides debug information and - * diagnostic tests of various hardware components. - * - * @param ctx Vboot context - * @returns VB2_SUCCESS, or non-zero error code. - */ -vb2_error_t vb2_diagnostic_menu(struct vb2_context *ctx); - -#endif /* VBOOT_REFERENCE_2UI_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/2lib/include/2ui_private.h vboot-utils-0~R99-14469.B/firmware/2lib/include/2ui_private.h --- vboot-utils-0~R88-13597.B/firmware/2lib/include/2ui_private.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/2lib/include/2ui_private.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -/* Copyright 2020 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 declarations for 2ui.c. Defined here for testing purposes. - */ - -#include "2api.h" -#include "2common.h" - -#ifndef VBOOT_REFERENCE_2UI_PRIVATE_H_ -#define VBOOT_REFERENCE_2UI_PRIVATE_H_ - -/* Time-related constants */ -#define KEY_DELAY_MS 20 /* Delay between key scans in UI loops */ -#define DEV_DELAY_SHORT_MS (2 * VB2_MSEC_PER_SEC) /* 2 seconds */ -#define DEV_DELAY_NORMAL_MS (30 * VB2_MSEC_PER_SEC) /* 30 seconds */ -#define DEV_DELAY_BEEP1_MS (20 * VB2_MSEC_PER_SEC) /* 20 seconds */ -#define DEV_DELAY_BEEP2_MS (20 * VB2_MSEC_PER_SEC + 500) /* 20.5 seconds */ - -/* From 2ui.c */ -vb2_error_t check_shutdown_request(struct vb2_ui_context *ui); -const struct vb2_menu *get_menu(struct vb2_ui_context *ui); -vb2_error_t error_exit_action(struct vb2_ui_context *ui); -vb2_error_t menu_navigation_action(struct vb2_ui_context *ui); -vb2_error_t ui_loop(struct vb2_context *ctx, enum vb2_screen root_screen_id, - vb2_error_t (*global_action)(struct vb2_ui_context *ui)); -vb2_error_t developer_action(struct vb2_ui_context *ui); -vb2_error_t broken_recovery_action(struct vb2_ui_context *ui); -vb2_error_t manual_recovery_action(struct vb2_ui_context *ui); - -/* From 2ui_screens.c */ -const struct vb2_menu *get_language_menu(struct vb2_ui_context *ui); -vb2_error_t advanced_options_init(struct vb2_ui_context *ui); -vb2_error_t recovery_select_init(struct vb2_ui_context *ui); -vb2_error_t recovery_to_dev_init(struct vb2_ui_context *ui); -vb2_error_t recovery_to_dev_confirm_action(struct vb2_ui_context *ui); -vb2_error_t recovery_to_dev_action(struct vb2_ui_context *ui); -vb2_error_t developer_mode_init(struct vb2_ui_context *ui); -vb2_error_t developer_mode_action(struct vb2_ui_context *ui); -vb2_error_t developer_to_norm_action(struct vb2_ui_context *ui); - -#endif /* VBOOT_REFERENCE_2UI_PRIVATE_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/include/gpt.h vboot-utils-0~R99-14469.B/firmware/include/gpt.h --- vboot-utils-0~R88-13597.B/firmware/include/gpt.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/include/gpt.h 2022-02-11 14:46:09.000000000 +0000 @@ -53,6 +53,10 @@ {{{0xebd0a0a2,0xb9e5,0x4433,0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}}}} #define GPT_ENT_TYPE_LINUX_FS \ {{{0x0fc63daf,0x8483,0x4772,0x8e,0x79,{0x3d,0x69,0xd8,0x47,0x7d,0xe4}}}} +#define GPT_ENT_TYPE_CHROMEOS_MINIOS \ + {{{0x09845860,0x705f,0x4bb5,0xb1,0x6c,{0x8a,0x8a,0x09,0x9c,0xaf,0x52}}}} +#define GPT_ENT_TYPE_CHROMEOS_HIBERNATE \ + {{{0x3f0f8318,0xf146,0x4e6b,0x82,0x22,{0xc2,0x8c,0x8f,0x02,0xe0,0xd5}}}} #define UUID_NODE_LEN 6 #define GUID_SIZE 16 diff -Nru vboot-utils-0~R88-13597.B/firmware/include/tpm2_tss_constants.h vboot-utils-0~R99-14469.B/firmware/include/tpm2_tss_constants.h --- vboot-utils-0~R88-13597.B/firmware/include/tpm2_tss_constants.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/include/tpm2_tss_constants.h 2022-02-11 14:46:09.000000000 +0000 @@ -34,9 +34,13 @@ #define TPM2_NV_ReadPublic ((TPM_CC)0x00000169) #define TPM2_GetCapability ((TPM_CC)0x0000017A) #define TPM2_GetRandom ((TPM_CC)0x0000017B) +#define TPM2_PCR_Extend ((TPM_CC)0x00000182) -#define HR_SHIFT 24 +#define TPM_HT_PCR 0x00 #define TPM_HT_NV_INDEX 0x01 + +#define HR_SHIFT 24 +#define HR_PCR (TPM_HT_PCR << HR_SHIFT) #define HR_NV_INDEX (TPM_HT_NV_INDEX << HR_SHIFT) #define TPM_RH_OWNER 0x40000001 #define TPM_RH_PLATFORM 0x4000000C @@ -110,9 +114,15 @@ #define TPMI_RH_NV_INDEX_TCG_WG_START ((TPMI_RH_NV_INDEX)0x01C40000) #define TPMI_RH_NV_INDEX_RESERVED_START ((TPMI_RH_NV_INDEX)0x01C90000) +#define HASH_COUNT 1 /* Only SHA-256 is supported */ + +/* Table 206 - Defines for SHA256 Hash Values */ +#define SHA256_DIGEST_SIZE 32 + typedef uint8_t TPMI_YES_NO; typedef uint32_t TPM_CC; typedef uint32_t TPM_HANDLE; +typedef TPM_HANDLE TPMI_DH_PCR; typedef TPM_HANDLE TPMI_RH_NV_INDEX; typedef TPM_HANDLE TPMI_RH_ENABLES; typedef uint32_t TPM_CAP; @@ -146,6 +156,20 @@ } TPML_TAGGED_TPM_PROPERTY; typedef union { + uint8_t sha256[SHA256_DIGEST_SIZE]; +} TPMU_HA; + +typedef struct { + TPMI_ALG_HASH hashAlg; + TPMU_HA digest; +} TPMT_HA; + +typedef struct { + uint32_t count; + TPMT_HA digests[HASH_COUNT]; +} TPML_DIGEST_VALUES; + +typedef union { TPML_TAGGED_TPM_PROPERTY tpm_properties; } TPMU_CAPABILITIES; @@ -223,6 +247,11 @@ TPM_SU shutdown_type; }; +struct tpm2_pcr_extend_cmd { + TPMI_DH_PCR pcrHandle; + TPML_DIGEST_VALUES digests; +}; + /* Common command/response header. */ struct tpm_header { uint16_t tpm_tag; diff -Nru vboot-utils-0~R88-13597.B/firmware/include/vboot_api.h vboot-utils-0~R99-14469.B/firmware/include/vboot_api.h --- vboot-utils-0~R88-13597.B/firmware/include/vboot_api.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/include/vboot_api.h 2022-02-11 14:46:09.000000000 +0000 @@ -44,7 +44,6 @@ */ typedef void *VbExDiskHandle_t; -/* Data used only by VbSelectAndLoadKernel() */ typedef struct VbSelectAndLoadKernelParams { /* Inputs to VbSelectAndLoadKernel() */ /* Destination buffer for kernel (normally at 0x100000 on x86) */ @@ -68,12 +67,6 @@ uint8_t partition_guid[16]; /* Flags set by signer */ uint32_t flags; - /* - * TODO: in H2C, all that pretty much just gets passed to the - * bootloader as KernelBootloaderOptions, though the disk handle is - * passed as an index instead of a handle. Is that used anymore now - * that we're passing partition_guid? - */ } VbSelectAndLoadKernelParams; /** @@ -84,17 +77,60 @@ vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, VbSelectAndLoadKernelParams *kparams); +/** + * Attempt loading a kernel from the specified type(s) of disks. + * + * If successful, sets kparams.disk_handle to the disk for the kernel and + * returns VB2_SUCCESS. + * + * @param ctx Vboot context + * @param disk_flags Flags to pass to VbExDiskGetInfo() + * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error. + */ +vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags); + +/* miniOS flags */ + +/* Boot from non-active miniOS partition only */ +#define VB_MINIOS_FLAG_NON_ACTIVE (1 << 0) + +/** + * Attempt loading a miniOS kernel from internal disk. + * + * Scans sectors at the start and end of the disk, and looks for miniOS kernels + * starting at the beginning of the sector. Attempts loading any miniOS + * kernels found. + * + * If successful, sets lkp.disk_handle to the disk for the kernel and returns + * VB2_SUCCESS. + * + * @param ctx Vboot context + * @param minios_flags Flags for miniOS + * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error. + */ +vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx, + uint32_t minios_flags); + /*****************************************************************************/ /* Disk access (previously in boot_device.h) */ /* Flags for VbDisk APIs */ + +/* + * Disk selection in the lower 16 bits (where the disk lives), and disk + * attributes in the higher 16 bits (extra information about the disk + * needed to access it correctly). + */ +#define VB_DISK_FLAG_SELECT_MASK 0xffff +#define VB_DISK_FLAG_ATTRIBUTE_MASK (0xffff << 16) + /* Disk is removable. Example removable disks: SD cards, USB keys. */ -#define VB_DISK_FLAG_REMOVABLE 0x00000001 +#define VB_DISK_FLAG_REMOVABLE (1 << 0) /* * Disk is fixed. If this flag is present, disk is internal to the system and * not removable. Example fixed disks: internal SATA SSD, eMMC. */ -#define VB_DISK_FLAG_FIXED 0x00000002 +#define VB_DISK_FLAG_FIXED (1 << 1) /* * Note that VB_DISK_FLAG_REMOVABLE and VB_DISK_FLAG_FIXED are * mutually-exclusive for a single disk. VbExDiskGetInfo() may specify both @@ -130,7 +166,7 @@ * streaming aspects of the disk. If a disk is random-access (i.e. * not raw NAND) then these fields are equal. */ -#define VB_DISK_FLAG_EXTERNAL_GPT 0x00000004 +#define VB_DISK_FLAG_EXTERNAL_GPT (1 << 16) /* Information on a single disk */ typedef struct VbDiskInfo { @@ -252,291 +288,6 @@ */ void VbExStreamClose(VbExStream_t stream); - -/*****************************************************************************/ -/* Display */ - -/* Predefined (default) screens for VbExDisplayScreen(). */ -enum VbScreenType_t { - /* Blank (clear) screen */ - VB_SCREEN_BLANK = 0, - /* Developer - warning */ - VB_SCREEN_DEVELOPER_WARNING = 0x101, - /* REMOVED: Developer - easter egg (0x102) */ - /* REMOVED: Recovery - remove inserted devices (0x201) */ - /* Recovery - insert recovery image */ - VB_SCREEN_RECOVERY_INSERT = 0x202, - /* Recovery - inserted image invalid */ - VB_SCREEN_RECOVERY_NO_GOOD = 0x203, - /* Recovery - confirm dev mode */ - VB_SCREEN_RECOVERY_TO_DEV = 0x204, - /* Developer - confirm normal mode */ - VB_SCREEN_DEVELOPER_TO_NORM = 0x205, - /* Please wait - programming EC */ - VB_SCREEN_WAIT = 0x206, - /* Confirm after DEVELOPER_TO_NORM */ - VB_SCREEN_TO_NORM_CONFIRMED = 0x207, - /* Broken screen shown after verification failure */ - VB_SCREEN_OS_BROKEN = 0x208, - /* REMOVED: Display base screen (no icons, no text) (0x209) */ - /* Detachable Menu - Developer Warning */ - VB_SCREEN_DEVELOPER_WARNING_MENU = 0x20a, - /* Detachable Menu - Developer Boot */ - VB_SCREEN_DEVELOPER_MENU = 0x20b, - /* REMOVED: Detachable Menu - Recovery (0x20c) */ - /* Detachable Menu - Confirm Dev Mode */ - VB_SCREEN_RECOVERY_TO_DEV_MENU = 0x20d, - /* Detachable Menu - Confirm Normal Mode */ - VB_SCREEN_DEVELOPER_TO_NORM_MENU = 0x20e, - /* Detachable Menu - Languages */ - VB_SCREEN_LANGUAGES_MENU = 0x20f, - /* Detachable Menu - Options */ - VB_SCREEN_OPTIONS_MENU = 0x210, - /* REMOVED: Alt OS picker screen (0x211) */ - /* Alt firmware picker screen (for keyboard UI) */ - VB_SCREEN_ALT_FW_PICK = 0x212, - /* Alt firmware menu screen (for detachable UI ) */ - VB_SCREEN_ALT_FW_MENU = 0x213, - /* 0x300-0x350 reserved for device-specific screens */ - /* Vendor data not set warning screen */ - VB_COMPLETE_VENDOR_DATA = 0x300, - /* Set vendor data menu screen */ - VB_SCREEN_SET_VENDOR_DATA = 0x301, - /* Confirm vendor data menu screen */ - VB_SCREEN_CONFIRM_VENDOR_DATA = 0x302, - /* Confirm reboot for running diagnostics rom */ - VB_SCREEN_CONFIRM_DIAG = 0x303, -}; - -/* Flags to control behavior of device-specific screens. */ -enum VbVendorDataFlags_t { - /* When set display a cursor after the prompt */ - VB_VENDOR_DATA_SHOW_CURSOR = 1 << 0, - /* When set only redraw the cursor */ - VB_VENDOR_DATA_ONLY_DRAW_CURSOR = 1 << 1, -}; - -/** - * Extra data needed when displaying vendor data screens - */ -typedef struct VbVendorData -{ - /* Current state of the the vendor data input */ - const char *input_text; - /* Flags (See VbVendorDataFlags_t) */ - uint32_t flags; - /* Current confirmation selection for new vendor data */ - uint32_t selected_index; -} VbVendorData; - -/** - * Extra data that may be used when displaying a screen - */ -typedef struct VbScreenData -{ - union { - VbVendorData vendor_data; - }; -} VbScreenData; - -/** - * Display a predefined screen; see VB_SCREEN_* for valid screens. - * - * This is a backup method of screen display, intended for use if the GBB does - * not contain a full set of bitmaps. It is acceptable for the backup screen - * to be simple ASCII text such as "NO GOOD" or "INSERT"; these screens should - * only be seen during development. - */ -vb2_error_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale, - const VbScreenData *data); - -/** - * Display a predefined menu screen; see VB_SCREEN_* for valid screens. - * - * @param screen_type ID of screen to draw - * @param locale language to display - * @param selected_index Index of menu item that is currently selected. - * @param disabled_idx_mask Bitmap for enabling/disabling certain menu items. - * each bit corresponds to the menu item's index. - * @param redraw_base Setting 1 will force a full redraw of the screen - * - * @return VB2_SUCCESS or error code on error. - */ -vb2_error_t VbExDisplayMenu(uint32_t screen_type, uint32_t locale, - uint32_t selected_index, uint32_t disabled_idx_mask, - uint32_t redraw_base); - -/** - * Display a string containing debug information on the screen, rendered in a - * platform-dependent font. Should be able to handle newlines '\n' in the - * string. Firmware must support displaying at least 20 lines of text, where - * each line may be at least 80 characters long. If the firmware has its own - * debug state, it may display it to the screen below this information if the - * full_info parameter is set. - * - * @param info_str The debug string to display - * @param full_info 1 if firmware should append its own info, 0 if not - * - * @return VB2_SUCCESS or error code on error. - */ -vb2_error_t VbExDisplayDebugInfo(const char *info_str, int full_info); - -/** - * Write vendor data to read-only VPD - * - * @param vendor_data_value The value of vendor data to write to VPD. The - * string length will be exactly VENDOR_DATA_LENGTH - * characters and null-terminated. - * - * @return VB2_SUCCESS or error code on error. - */ -vb2_error_t VbExSetVendorData(const char *vendor_data_value); - -/*****************************************************************************/ -/* Keyboard and switches */ - -/* Key code for CTRL + letter */ -#define VB_KEY_CTRL(letter) (letter & 0x1f) - -/* Key code for fn keys */ -#define VB_KEY_F(num) (num + 0x108) - -/* Key codes for required non-printable-ASCII characters. */ -enum VbKeyCode_t { - VB_KEY_ENTER = '\r', - VB_KEY_ESC = 0x1b, - VB_KEY_BACKSPACE = 0x8, - VB_KEY_UP = 0x100, - VB_KEY_DOWN = 0x101, - VB_KEY_LEFT = 0x102, - VB_KEY_RIGHT = 0x103, - VB_KEY_CTRL_ENTER = 0x104, -}; - -/* - * WARNING!!! Before updating the codes in enum VbButtonCode_t, ensure that the - * code does not overlap the values in VbKeyCode_t unless the button action is - * the same as key action. - */ -enum VbButtonCode_t { - /* Volume up/down short press match the values in 8042 driver. */ - VB_BUTTON_VOL_UP_SHORT_PRESS = 0x62, - VB_BUTTON_VOL_DOWN_SHORT_PRESS = 0x63, - /* Dummy values used below. */ - VB_BUTTON_POWER_SHORT_PRESS = 0x90, - VB_BUTTON_VOL_UP_LONG_PRESS = 0x91, - VB_BUTTON_VOL_DOWN_LONG_PRESS = 0x92, - VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS = 0x93, -}; - -/* Flags for additional information. - * TODO(semenzato): consider adding flags for modifiers instead of - * making up some of the key codes above. - */ -enum VbKeyFlags_t { - VB_KEY_FLAG_TRUSTED_KEYBOARD = 1 << 0, -}; - -/** - * Read the next keypress from the keyboard buffer. - * - * Returns the keypress, or zero if no keypress is pending or error. - * - * The following keys must be returned as ASCII character codes: - * 0x08 Backspace - * 0x09 Tab - * 0x0D Enter (carriage return) - * 0x01 - 0x1A Ctrl+A - Ctrl+Z (yes, those alias with backspace/tab/enter) - * 0x1B Esc (VB_KEY_ESC) - * 0x20 Space - * 0x30 - 0x39 '0' - '9' - * 0x60 - 0x7A 'a' - 'z' - * - * Some extended keys must also be supported; see the VB_KEY_* defines above. - * - * Keys ('/') or key-chords (Fn+Q) not defined above may be handled in any of - * the following ways: - * 1. Filter (don't report anything if one of these keys is pressed). - * 2. Report as ASCII (if a well-defined ASCII value exists for the key). - * 3. Report as any other value in the range 0x200 - 0x2FF. - * It is not permitted to report a key as a multi-byte code (for example, - * sending an arrow key as the sequence of keys '\x1b', '[', '1', 'A'). */ -uint32_t VbExKeyboardRead(void); - -/** - * Same as VbExKeyboardRead(), but return extra information. - */ -uint32_t VbExKeyboardReadWithFlags(uint32_t *flags_ptr); - -/*****************************************************************************/ -/* Misc */ - -/** - * Check if the firmware needs to shut down the system. - * - * Returns a non-zero VB_SHUTDOWN_REQUEST mask indicating the reason(s) for - * shutdown if a shutdown is being requested (see VB_SHUTDOWN_REQUEST_*), or 0 - * if a shutdown is not being requested. - * - * NOTE: When we're displaying a screen, pressing the power button should shut - * down the computer. We need a way to break out of our control loop so this - * can occur cleanly. - */ -uint32_t VbExIsShutdownRequested(void); - -/* - * Shutdown requested for a reason which is not defined among other - * VB_SHUTDOWN_REQUEST_* values. This must be defined as 1 for backward - * compatibility with old versions of the API. - */ -#define VB_SHUTDOWN_REQUEST_OTHER 0x00000001 -/* Shutdown requested due to a lid switch being closed. */ -#define VB_SHUTDOWN_REQUEST_LID_CLOSED 0x00000002 -/* Shutdown requested due to a power button being pressed. */ -#define VB_SHUTDOWN_REQUEST_POWER_BUTTON 0x00000004 - -enum VbAltFwIndex_t { - VB_ALTFW_DIAGNOSTIC = -1, - VB_ALTFW_DEFAULT = 0, - VB_ALTFW_FIRST = 1, - VB_ALTFW_SECOND, - VB_ALTFW_THIRD, - VB_ALTFW_FOURTH, - VB_ALTFW_FIFTH, - VB_ALTFW_SIXTH, - VB_ALTFW_SEVENTH, - VB_ALTFW_EIGHTH, - VB_ALTFW_NINTH, -}; - -/** - * Execute legacy boot option. - * - * @param altfw_num Bootloader sequence number to execute. Use - * 0 to boot the default payload, if any - * >0 (i.e., positive #) run a payload by # based in altfw/list file - * <0 (i.e., negative #) run a specific payload by name without using - * the altfw/list file. Typically payloads in this category will be - * verified before they are run. Currently these #s are defined: - * -1 diagnostic payload - */ -vb2_error_t VbExLegacy(enum VbAltFwIndex_t altfw_num); - -enum vb_altfw { - VB_ALTFW_COUNT = 9, /* We allow 9 bootloaders, numbered 1-9 */ -}; - -/** - * Get a mask of available alternative firmware options - * - * There are up to 9 bootloaders, numbered 1 to 9, using bits 1 to 9 of this - * mask. Bit 0 is unused. - * - * @return Bit mask indicating which bootloaders are present (bit n indicates - * bootloader n is present) - */ -uint32_t VbExGetAltFwIdxMask(void); - #ifdef __cplusplus } #endif /* __cplusplus */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/cgptlib/cgptlib.c vboot-utils-0~R99-14469.B/firmware/lib/cgptlib/cgptlib.c --- vboot-utils-0~R88-13597.B/firmware/lib/cgptlib/cgptlib.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/cgptlib/cgptlib.c 2022-02-11 14:46:09.000000000 +0000 @@ -142,7 +142,7 @@ break; } /* Out of tries, so drop through and mark partition bad. */ - __attribute__ ((fallthrough)); + VBOOT_FALLTHROUGH; } case GPT_UPDATE_ENTRY_BAD: { /* Giving up on this partition entirely. */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/gpt_misc.c vboot-utils-0~R99-14469.B/firmware/lib/gpt_misc.c --- vboot-utils-0~R88-13597.B/firmware/lib/gpt_misc.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/gpt_misc.c 2022-02-11 14:46:09.000000000 +0000 @@ -35,6 +35,11 @@ gptdata->primary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE); gptdata->secondary_entries = (uint8_t *)malloc(GPT_ENTRIES_ALLOC_SIZE); + /* In some cases we try to validate header1 with entries2 or vice versa, + so make sure the entries buffers always got fully initialized. */ + memset(gptdata->primary_entries, 0, GPT_ENTRIES_ALLOC_SIZE); + memset(gptdata->secondary_entries, 0, GPT_ENTRIES_ALLOC_SIZE); + if (gptdata->primary_header == NULL || gptdata->secondary_header == NULL || gptdata->primary_entries == NULL || @@ -66,7 +71,6 @@ entries_sectors, gptdata->primary_entries)) { VB2_DEBUG("Read error in primary GPT entries\n"); - memset(gptdata->primary_entries, 0, entries_bytes); primary_valid = 0; } } else { @@ -103,7 +107,6 @@ entries_sectors, gptdata->secondary_entries)) { VB2_DEBUG("Read error in secondary GPT entries\n"); - memset(gptdata->secondary_entries, 0, entries_bytes); secondary_valid = 0; } } else { diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/load_kernel_fw.h vboot-utils-0~R99-14469.B/firmware/lib/include/load_kernel_fw.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/load_kernel_fw.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/load_kernel_fw.h 2022-02-11 14:46:09.000000000 +0000 @@ -11,55 +11,31 @@ #include "vboot_api.h" -struct vb2_context; - -/* Interface provided by verified boot library to BDS */ - -/* Boot flags for LoadKernel().boot_flags */ -/* GPT is external */ -#define BOOT_FLAG_EXTERNAL_GPT (0x04ULL) - -typedef struct LoadKernelParams { - /* Inputs to LoadKernel() */ - /* Disk handle for current device */ - VbExDiskHandle_t disk_handle; - /* Bytes per lba sector on current device */ - uint64_t bytes_per_lba; - /* Number of LBA-addressable sectors on the main device */ - uint64_t streaming_lba_count; - /* Random-access GPT size */ - uint64_t gpt_lba_count; - /* Destination buffer for kernel (normally at 0x100000) */ - void *kernel_buffer; - /* Size of kernel buffer in bytes */ - uint64_t kernel_buffer_size; - /* Boot flags */ - uint64_t boot_flags; - - /* - * Outputs from LoadKernel(); valid only if LoadKernel() returns - * LOAD_KERNEL_SUCCESS - */ - /* Partition number to boot on current device (1...M) */ - uint32_t partition_number; - /* Address of bootloader image in RAM */ - uint64_t bootloader_address; - /* Size of bootloader image in bytes */ - uint32_t bootloader_size; - /* UniquePartitionGuid for boot partition */ - uint8_t partition_guid[16]; - /* Flags passed in by signer */ - uint32_t flags; -} LoadKernelParams; +/** + * Attempt to load kernel from the specified device. + * + * @param ctx Vboot context + * @param params Params specific to loading the kernel + * @param disk_info Disk from which to read kernel + * + * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code. + */ +vb2_error_t LoadKernel(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info); /** - * Attempt to load the kernel from the current device. + * Attempt to load miniOS kernel from the specified device. * * @param ctx Vboot context * @param params Params specific to loading the kernel + * @param disk_info Disk from which to read kernel + * @param minios_flags Flags for miniOS * * Returns VB2_SUCCESS if successful. If unsuccessful, returns an error code. */ -vb2_error_t LoadKernel(struct vb2_context *ctx, LoadKernelParams *params); +vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info, uint32_t minios_flags); #endif /* VBOOT_REFERENCE_LOAD_KERNEL_FW_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_audio.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_audio.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_audio.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_audio.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Delay/beep functions used in dev-mode kernel selection. - */ - -#ifndef VBOOT_REFERENCE_VBOOT_AUDIO_H_ -#define VBOOT_REFERENCE_VBOOT_AUDIO_H_ - -#include "vboot_api.h" - -/** - * Initialization function. - */ -void vb2_audio_start(struct vb2_context *ctx); - -/** - * Caller should loop without extra delay until this returns false. - */ -int vb2_audio_looping(void); - -#endif /* VBOOT_REFERENCE_VBOOT_AUDIO_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_kernel.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_kernel.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_kernel.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_kernel.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,154 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Data structure and API definitions for a verified boot kernel image. - * (Firmware Portion) - */ - -#ifndef VBOOT_REFERENCE_VBOOT_KERNEL_H_ -#define VBOOT_REFERENCE_VBOOT_KERNEL_H_ - -#include "cgptlib.h" -#include "gpt_misc.h" -#include "load_kernel_fw.h" -#include "vboot_api.h" - -struct vb2_context; - -/* Flags for VbSharedDataKernelPart.flags */ -#define VBSD_LKP_FLAG_KEYBLOCK_VALID 0x01 - -/* Result codes for VbSharedDataKernelPart.check_result */ -#define VBSD_LKP_CHECK_NOT_DONE 0 -#define VBSD_LKP_CHECK_TOO_SMALL 1 -#define VBSD_LKP_CHECK_READ_START 2 -#define VBSD_LKP_CHECK_KEYBLOCK_SIG 3 -#define VBSD_LKP_CHECK_KEYBLOCK_HASH 4 -#define VBSD_LKP_CHECK_DEV_MISMATCH 5 -#define VBSD_LKP_CHECK_REC_MISMATCH 6 -#define VBSD_LKP_CHECK_KEY_ROLLBACK 7 -#define VBSD_LKP_CHECK_DATA_KEY_PARSE 8 -#define VBSD_LKP_CHECK_VERIFY_PREAMBLE 9 -#define VBSD_LKP_CHECK_KERNEL_ROLLBACK 10 -#define VBSD_LKP_CHECK_PREAMBLE_VALID 11 -/* - * Body load address check is omitted; this result code is deprecated and not - * used anywhere in the codebase. - */ -#define VBSD_LKP_CHECK_BODY_ADDRESS 12 -#define VBSD_LKP_CHECK_BODY_OFFSET 13 -#define VBSD_LKP_CHECK_SELF_SIGNED 14 -#define VBSD_LKP_CHECK_BODY_EXCEEDS_MEM 15 -#define VBSD_LKP_CHECK_BODY_EXCEEDS_PART 16 -#define VBSD_LKP_CHECK_READ_DATA 17 -#define VBSD_LKP_CHECK_VERIFY_DATA 18 -#define VBSD_LKP_CHECK_KERNEL_GOOD 19 - -/* Information about a single kernel partition check in LoadKernel() */ -typedef struct VbSharedDataKernelPart { - uint64_t sector_start; /* Start sector of partition */ - uint64_t sector_count; /* Sector count of partition */ - uint32_t combined_version; /* Combined key+kernel version */ - uint8_t gpt_index; /* Index of partition in GPT */ - uint8_t check_result; /* Check result; see VBSD_LKP_CHECK_* */ - uint8_t flags; /* Flags (see VBSD_LKP_FLAG_* */ - uint8_t reserved0; /* Reserved for padding */ -} VbSharedDataKernelPart; - -/* Number of kernel partitions to track per call. Must be power of 2. */ -#define VBSD_MAX_KERNEL_PARTS 8 - -/* Result codes for VbSharedDataKernelCall.check_result */ -#define VBSD_LKC_CHECK_NOT_DONE 0 -#define VBSD_LKC_CHECK_DEV_SWITCH_MISMATCH 1 -#define VBSD_LKC_CHECK_GPT_READ_ERROR 2 -#define VBSD_LKC_CHECK_GPT_PARSE_ERROR 3 -#define VBSD_LKC_CHECK_GOOD_PARTITION 4 -#define VBSD_LKC_CHECK_INVALID_PARTITIONS 5 -#define VBSD_LKC_CHECK_NO_PARTITIONS 6 - -/* Information about a single call to LoadKernel() */ -typedef struct VbSharedDataKernelCall { - /* Bottom 32 bits of flags passed in LoadKernelParams.boot_flags */ - uint32_t boot_flags; - /* Debug flags; see VBSD_LK_FLAG_* */ - uint32_t flags; - /* Number of sectors on drive */ - uint64_t sector_count; - /* Sector size in bytes */ - uint32_t sector_size; - /* Check result; see VBSD_LKC_CHECK_* */ - uint8_t check_result; - /* Boot mode for LoadKernel(); see VBSD_LK_BOOT_MODE_* constants */ - uint8_t boot_mode; - /* Test error number, if non-zero */ - uint8_t test_error_num; - /* Return code from LoadKernel() */ - uint8_t return_code; - /* Number of kernel partitions found */ - uint8_t kernel_parts_found; - /* Reserved for padding */ - uint8_t reserved0[7]; - /* Data on kernels */ - VbSharedDataKernelPart parts[VBSD_MAX_KERNEL_PARTS]; -} VbSharedDataKernelCall; - -/** - * Attempt loading a kernel from the specified type(s) of disks. - * - * If successful, sets lkp.disk_handle to the disk for the kernel and returns - * VB2_SUCCESS. - * - * @param ctx Vboot context - * @param get_info_flags Flags to pass to VbExDiskGetInfo() - * @return VB2_SUCCESS or the most specific VB2_ERROR_LK error. - */ -vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t get_info_flags); - -/* Flags for VbUserConfirms() */ -#define VB_CONFIRM_MUST_TRUST_KEYBOARD (1 << 0) -#define VB_CONFIRM_SPACE_MEANS_NO (1 << 1) - -/** - * Ask the user to confirm something. - * - * We should display whatever the question is first, then call this. ESC is - * always "no", ENTER is always "yes", and we'll specify what SPACE means. We - * don't return until one of those keys is pressed, or until asked to shut - * down. - * - * Additionally, in some situations we don't accept confirmations from an - * untrusted keyboard (such as a USB device). In those cases, a recovery - * button press is needed for confirmation, instead of ENTER. - * - * Returns: 1=yes, 0=no, -1 = shutdown. - */ -int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags); - -/** - * Handle a developer-mode boot using legacy clamshell UI. - */ -vb2_error_t VbBootDeveloperLegacyClamshell(struct vb2_context *ctx); - -/** - * Handle a diagnostic-mode boot using legacy clamshell UI. - */ -vb2_error_t VbBootDiagnosticLegacyClamshell(struct vb2_context *ctx); - -/** - * Handle a recovery-mode boot using legacy clamshell UI. - */ -vb2_error_t VbBootRecoveryLegacyClamshell(struct vb2_context *ctx); - -/** - * Handle a developer-mode boot using legacy menu UI. - */ -vb2_error_t VbBootDeveloperLegacyMenu(struct vb2_context *ctx); - -/** - * Handle a recovery-mode boot using legacy menu UI. - */ -vb2_error_t VbBootRecoveryLegacyMenu(struct vb2_context *ctx); - -#endif /* VBOOT_REFERENCE_VBOOT_KERNEL_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_struct.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_struct.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_struct.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_struct.h 2022-02-11 14:46:09.000000000 +0000 @@ -10,7 +10,7 @@ #include -#include "vboot_kernel.h" +#include "2sysincludes.h" #ifdef __cplusplus extern "C" { @@ -53,9 +53,6 @@ /* NvStorage uses 64-byte record, not 16-byte */ #define VBSD_NVDATA_V2 0x00100000 -/* Number of kernel calls to track. Must be power of 2. */ -#define VBSD_MAX_KERNEL_CALLS 4 - /* Data shared to OS. */ typedef struct VbSharedDataHeader { /* Fields present in version 1 */ @@ -117,8 +114,8 @@ /* Debugging information from LoadKernel() */ /* Number of times LoadKernel() called */ uint32_t lk_call_count; - /* Info on calls */ - VbSharedDataKernelCall lk_calls[VBSD_MAX_KERNEL_CALLS]; + /* Reserved for padding */ + uint8_t reserved3[896]; /* * Offset and size of supplemental kernel data. Reserve space for @@ -137,7 +134,7 @@ /* Recovery reason for current boot */ uint8_t recovery_reason; /* Reserved for padding */ - uint8_t reserved3[7]; + uint8_t reserved4[7]; /* Flags from firmware keyblock */ uint64_t fw_keyblock_flags; /* Kernel TPM version at start of VbSelectAndLoadKernel() */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_test.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_test.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_test.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_test.h 2022-02-11 14:46:09.000000000 +0000 @@ -9,35 +9,9 @@ #define VBOOT_REFERENCE_TEST_API_H_ /**************************************************************************** - * 2rsa.c - * - * Internal functions from 2rsa.c that have error conditions we can't trigger - * from the public APIs. These include checks for bad algorithms where the - * next call level up already checks for bad algorithms, etc. - * - * These functions aren't in 2rsa.h because they're not part of the public - * APIs. - */ -struct vb2_public_key; -int vb2_mont_ge(const struct vb2_public_key *key, uint32_t *a); -vb2_error_t vb2_check_padding(const uint8_t *sig, - const struct vb2_public_key *key); - -/**************************************************************************** * vboot_api_kernel.c */ -struct LoadKernelParams; -struct LoadKernelParams *VbApiKernelGetParams(void); - -/**************************************************************************** - * 2secdata_kernel.c */ - -/** - * Calculate crc8 of kernel secure storage. - * - * @param ctx Context pointer - * @return Calculated crc8 value. - */ -uint8_t vb2_secdata_kernel_crc(struct vb2_context *ctx); +struct VbSelectAndLoadKernelParams; +struct VbSelectAndLoadKernelParams **VbApiKernelGetParamsPtr(void); #endif /* VBOOT_REFERENCE_TEST_API_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_ui_legacy.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_ui_legacy.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_ui_legacy.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_ui_legacy.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,86 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Common code used by both legacy_clamshell_ui and legacy_menu_ui. - */ - -#ifndef VBOOT_REFERENCE_VBOOT_UI_LEGACY_H_ -#define VBOOT_REFERENCE_VBOOT_UI_LEGACY_H_ - -extern const char dev_disable_msg[]; - -vb2_error_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, - const VbScreenData *data); -vb2_error_t VbDisplayMenu(struct vb2_context *ctx, - uint32_t screen, int force, uint32_t selected_index, - uint32_t disabled_idx_mask); -vb2_error_t VbDisplayDebugInfo(struct vb2_context *ctx); -vb2_error_t VbCheckDisplayKey(struct vb2_context *ctx, uint32_t key, - uint32_t screen, const VbScreenData *data); - -#define KEY_DELAY_MS 20 /* Delay between key scans in UI loops */ - -enum vb2_beep_type { - VB_BEEP_FAILED, /* Permitted but the operation failed */ - VB_BEEP_NOT_ALLOWED, /* Operation disabled by user setting */ -}; - -/** - * Reinitialize global state. This should only need to be called - * by vboot_ui::vb2_init_ui() for init tests. - */ -void vb2_reset_power_button(void); - -/** - * Emit beeps to indicate an error - */ -void vb2_error_beep(enum vb2_beep_type beep); - -/** - * Prints a message to screen, logs a possibly different message to log, - * and beeps to notify user. - * - * @print_msg Display message. NULL message will be ignored. - * @log_msg Log message. If NULL, uses @print_msg (if that's not NULL). - * @beep Type of beep sound. - */ -void vb2_error_notify(const char *print_msg, - const char *log_msg, - enum vb2_beep_type beep); - -/** Display an error and beep to indicate that altfw is not available */ -void vb2_error_no_altfw(void); - -/** - * Jump to a bootloader if possible - * - * This checks if the operation is permitted. If it is, then it jumps to the - * selected bootloader and execution continues there, never returning. - * - * Will beep and return if one of the following is true: - * - operation is not permitted (allowed == 0) - * - vboot data fails to commit - * - secdata_kernel fails to lock - * - bootloader cannot be found - * - bootloader fails to start - * - * @param ctx Context pointer - * @param allowed 1 if allowed, 0 if not allowed - * @param altfw_num Number of bootloader to start (0=any, 1=first, etc.) - */ -void vb2_try_altfw(struct vb2_context *ctx, int allowed, - enum VbAltFwIndex_t altfw_num); - -/** - * Checks GBB flags against VbExIsShutdownRequested() shutdown request to - * determine if a shutdown is required. - * - * Returns zero or more of the following flags (if any are set then typically - * shutdown is required): - * VB_SHUTDOWN_REQUEST_LID_CLOSED - * VB_SHUTDOWN_REQUEST_POWER_BUTTON - */ -int vb2_want_shutdown(struct vb2_context *ctx, uint32_t key); - -#endif /* VBOOT_REFERENCE_VBOOT_UI_LEGACY_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_ui_legacy_menu_private.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_ui_legacy_menu_private.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_ui_legacy_menu_private.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_ui_legacy_menu_private.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -/* Copyright 2017 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 declarations for vboot_ui_legacy_menu.c. Defined here for easier - * testing. - */ - -#ifndef VBOOT_REFERENCE_VBOOT_UI_LEGACY_MENU_PRIVATE_H_ -#define VBOOT_REFERENCE_VBOOT_UI_LEGACY_MENU_PRIVATE_H_ - -#include "2api.h" - -struct vb2_menu_item { - const char *text; - vb2_error_t (*action)(struct vb2_context *ctx); -}; - -struct vb2_menu { - const char *name; - uint16_t size; - uint16_t screen; - struct vb2_menu_item *items; -}; - -typedef enum _VB_MENU { - VB_MENU_DEV_WARNING, - VB_MENU_DEV, - VB_MENU_TO_NORM, - VB_MENU_TO_DEV, - VB_MENU_LANGUAGES, - VB_MENU_OPTIONS, - VB_MENU_RECOVERY_INSERT, - VB_MENU_RECOVERY_NO_GOOD, - VB_MENU_RECOVERY_BROKEN, - VB_MENU_TO_NORM_CONFIRMED, - VB_MENU_ALT_FW, - VB_MENU_COUNT, -} VB_MENU; - -typedef enum _VB_DEV_WARNING_MENU { - VB_WARN_OPTIONS, - VB_WARN_DBG_INFO, - VB_WARN_ENABLE_VER, - VB_WARN_POWER_OFF, - VB_WARN_LANGUAGE, - VB_WARN_COUNT, -} VB_DEV_WARNING_MENU; - -typedef enum _VB_DEV_MENU { - VB_DEV_NETWORK, - VB_DEV_LEGACY, - VB_DEV_USB, - VB_DEV_DISK, - VB_DEV_CANCEL, - VB_DEV_POWER_OFF, - VB_DEV_LANGUAGE, - VB_DEV_COUNT, -} VB_DEV_MENU; - -typedef enum _VB_TO_NORM_MENU { - VB_TO_NORM_CONFIRM, - VB_TO_NORM_CANCEL, - VB_TO_NORM_POWER_OFF, - VB_TO_NORM_LANGUAGE, - VB_TO_NORM_COUNT, -} VB_TO_NORM_MENU; - -typedef enum _VB_TO_DEV_MENU { - VB_TO_DEV_CONFIRM, - VB_TO_DEV_CANCEL, - VB_TO_DEV_POWER_OFF, - VB_TO_DEV_LANGUAGE, - VB_TO_DEV_COUNT, -} VB_TO_DEV_MENU; - -// TODO: currently we're only supporting -// english. Will need to somehow find mapping -// from language to localization index. -typedef enum _VB_LANGUAGES_MENU { - VB_LANGUAGES_EN_US, - VB_LANGUAGES_COUNT, -} VB_LANGUAGES_MENU; - -typedef enum _VB_OPTIONS_MENU { - VB_OPTIONS_DBG_INFO, - VB_OPTIONS_CANCEL, - VB_OPTIONS_POWER_OFF, - VB_OPTIONS_LANGUAGE, - VB_OPTIONS_COUNT, -} VB_OPTIONS_MENU; - -#endif /* VBOOT_REFERENCE_VBOOT_UI_LEGACY_MENU_PRIVATE_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_ui_legacy_wilco.h vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_ui_legacy_wilco.h --- vboot-utils-0~R88-13597.B/firmware/lib/include/vboot_ui_legacy_wilco.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/include/vboot_ui_legacy_wilco.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -/* Copyright 2020 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. - * - * Wilco-specific feature support for vboot_ui - */ - -#ifndef VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ -#define VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ - -#define CURSOR_BLINK_MS 400 /* Speed that the vendor data cursor blinks */ - -/* - * User interface for setting the vendor data in VPD - */ -vb2_error_t vb2_vendor_data_ui(struct vb2_context *ctx); - -/* - * Determine whether the user has pressed the keys to enter diagnostics mode - */ -vb2_error_t vb2_check_diagnostic_key(struct vb2_context *ctx, uint32_t key); - -/* - * User interface for confirming launch of diagnostics rom - * - * This asks the user to confirm the launch of the diagnostics rom. The user - * can press the power button to confirm or press escape. There is a 30-second - * timeout which acts the same as escape. - */ -vb2_error_t vb2_diagnostics_ui(struct vb2_context *ctx); - -#endif /* VBOOT_REFERENCE_VBOOT_UI_WILCO_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/tpm2_lite/marshaling.c vboot-utils-0~R99-14469.B/firmware/lib/tpm2_lite/marshaling.c --- vboot-utils-0~R88-13597.B/firmware/lib/tpm2_lite/marshaling.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/tpm2_lite/marshaling.c 2022-02-11 14:46:09.000000000 +0000 @@ -283,7 +283,7 @@ } memcpy(*buffer, blob, blob_size); - buffer_space -= blob_size; + *buffer_space -= blob_size; *buffer = (void *)((uintptr_t)(*buffer) + blob_size); } @@ -327,6 +327,7 @@ #define marshal_TPM_HANDLE(a, b, c) marshal_u32(a, b, c) #define marshal_TPM_SU(a, b, c) marshal_u16(a, b, c) #define marshal_ALG_ID(a, b, c) marshal_u16(a, b, c) +#define marshal_TPMI_ALG_HASH(a, b, c) marshal_u16(a, b, c) /* * For TPM2B* structures the size field (16 or 32 bits) goes before the data. @@ -671,6 +672,48 @@ marshal_TPM_SU(buffer, command_body->shutdown_type, buffer_space); } +static void marshal_TPMT_HA(void **buffer, + TPMT_HA *data, + int *buffer_space) +{ + if (data->hashAlg != TPM_ALG_SHA256) + { + VB2_DEBUG("Unsupported TPMT_HA hash algorithm: %#x\n", + data->hashAlg); + *buffer_space = -1; + return; + } + marshal_TPMI_ALG_HASH(buffer, data->hashAlg, buffer_space); + /* We only support SHA256 now. */ + marshal_blob(buffer, data->digest.sha256, + SHA256_DIGEST_SIZE, buffer_space); +} + +static void marshal_TPML_DIGEST_VALUES(void **buffer, + TPML_DIGEST_VALUES *data, + int *buffer_space) +{ + int i; + + marshal_u32(buffer, data->count, buffer_space); + for (i = 0; i < data->count; i++) + marshal_TPMT_HA(buffer, &data->digests[i], buffer_space); +} + +static void marshal_pcr_extend(void **buffer, + struct tpm2_pcr_extend_cmd *command_body, + int *buffer_space) +{ + struct tpm2_session_header session_header; + + tpm_tag = TPM_ST_SESSIONS; + marshal_TPM_HANDLE(buffer, command_body->pcrHandle, buffer_space); + memset(&session_header, 0, sizeof(session_header)); + session_header.session_handle = TPM_RS_PW; + marshal_session_header(buffer, &session_header, buffer_space); + marshal_TPML_DIGEST_VALUES(buffer, &command_body->digests, buffer_space); +} + int tpm_marshal_command(TPM_CC command, void *tpm_command_body, void *buffer, int buffer_size) { @@ -740,6 +783,10 @@ marshal_shutdown(&cmd_body, tpm_command_body, &body_size); break; + case TPM2_PCR_Extend: + marshal_pcr_extend(&cmd_body, tpm_command_body, &body_size); + break; + default: body_size = -1; VB2_DEBUG("Request to marshal unsupported command %#x\n", @@ -811,6 +858,7 @@ case TPM2_Shutdown: case TPM2_NV_DefineSpace: case TPM2_NV_UndefineSpace: + case TPM2_PCR_Extend: /* Session data included in response can be safely ignored. */ cr_size = 0; break; diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/tpm2_lite/tlcl.c vboot-utils-0~R99-14469.B/firmware/lib/tpm2_lite/tlcl.c --- vboot-utils-0~R88-13597.B/firmware/lib/tpm2_lite/tlcl.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/tpm2_lite/tlcl.c 2022-02-11 14:46:09.000000000 +0000 @@ -314,8 +314,15 @@ uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest) { - VB2_DEBUG("NOT YET IMPLEMENTED\n"); - return TPM_SUCCESS; + struct tpm2_pcr_extend_cmd pcr_ext_cmd; + + pcr_ext_cmd.pcrHandle = HR_PCR + pcr_num; + pcr_ext_cmd.digests.count = 1; + pcr_ext_cmd.digests.digests[0].hashAlg = TPM_ALG_SHA256; + memcpy(pcr_ext_cmd.digests.digests[0].digest.sha256, in_digest, + sizeof(pcr_ext_cmd.digests.digests[0].digest.sha256)); + + return tpm_get_response_code(TPM2_PCR_Extend, &pcr_ext_cmd); } diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_api_kernel.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_api_kernel.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_api_kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_api_kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -13,22 +13,19 @@ #include "2rsa.h" #include "2secdata.h" #include "2sysincludes.h" -#include "2ui.h" #include "load_kernel_fw.h" -#include "vb2_common.h" #include "vboot_api.h" -#include "vboot_kernel.h" #include "vboot_struct.h" #include "vboot_test.h" /* Global variables */ -static LoadKernelParams lkp; +static VbSelectAndLoadKernelParams *kparams_ptr; #ifdef CHROMEOS_ENVIRONMENT /* Global variable accessor for unit tests */ -struct LoadKernelParams *VbApiKernelGetParams(void) +struct VbSelectAndLoadKernelParams **VbApiKernelGetParamsPtr(void) { - return &lkp; + return &kparams_ptr; } #endif @@ -54,37 +51,41 @@ return VB2_SUCCESS; } -test_mockable -vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t get_info_flags) +static int is_valid_disk(VbDiskInfo *info, uint32_t disk_flags) +{ + return info->bytes_per_lba >= 512 && + (info->bytes_per_lba & (info->bytes_per_lba - 1)) == 0 && + info->lba_count >= 16 && + (info->flags & disk_flags & VB_DISK_FLAG_SELECT_MASK) && + ((info->flags & VB_DISK_FLAG_SELECT_MASK) & + ((info->flags & VB_DISK_FLAG_SELECT_MASK) - 1)) == 0; +} + +static vb2_error_t VbTryLoadKernelImpl(struct vb2_context *ctx, + uint32_t disk_flags, int minios, + uint32_t minios_flags) { vb2_error_t rv = VB2_ERROR_LK_NO_DISK_FOUND; VbDiskInfo* disk_info = NULL; uint32_t disk_count = 0; uint32_t i; + vb2_error_t new_rv; - lkp.disk_handle = NULL; + /* TODO: Should have been set by VbSelectAndLoadKernel. Remove when + this global is no longer needed. */ + VB2_ASSERT(kparams_ptr); + + kparams_ptr->disk_handle = NULL; /* Find disks */ - if (VB2_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, - get_info_flags)) + if (VB2_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count, disk_flags)) disk_count = 0; /* Loop over disks */ for (i = 0; i < disk_count; i++) { VB2_DEBUG("trying disk %d\n", (int)i); - /* - * Validity-check what we can. FWIW, VbTryLoadKernel() is always - * called with only a single bit set in get_info_flags. - * - * Ensure that we got a partition with only the flags we asked - * for. - */ - if (disk_info[i].bytes_per_lba < 512 || - (disk_info[i].bytes_per_lba & - (disk_info[i].bytes_per_lba - 1)) != 0 || - 16 > disk_info[i].lba_count || - get_info_flags != (disk_info[i].flags & - ~VB_DISK_FLAG_EXTERNAL_GPT)) { + + if (!is_valid_disk(&disk_info[i], disk_flags)) { VB2_DEBUG(" skipping: bytes_per_lba=%" PRIu64 " lba_count=%" PRIu64 " flags=%#x\n", disk_info[i].bytes_per_lba, @@ -92,20 +93,20 @@ disk_info[i].flags); continue; } - lkp.disk_handle = disk_info[i].handle; - lkp.bytes_per_lba = disk_info[i].bytes_per_lba; - lkp.gpt_lba_count = disk_info[i].lba_count; - lkp.streaming_lba_count = disk_info[i].streaming_lba_count - ?: lkp.gpt_lba_count; - lkp.boot_flags |= disk_info[i].flags & VB_DISK_FLAG_EXTERNAL_GPT - ? BOOT_FLAG_EXTERNAL_GPT : 0; + kparams_ptr->disk_handle = disk_info[i].handle; - vb2_error_t new_rv = LoadKernel(ctx, &lkp); - VB2_DEBUG("LoadKernel() = %#x\n", new_rv); + if (minios) { + new_rv = LoadMiniOsKernel(ctx, kparams_ptr, + &disk_info[i], minios_flags); + VB2_DEBUG("LoadMiniOsKernel() = %#x\n", new_rv); + } else { + new_rv = LoadKernel(ctx, kparams_ptr, &disk_info[i]); + VB2_DEBUG("LoadKernel() = %#x\n", new_rv); + } /* Stop now if we found a kernel. */ if (VB2_SUCCESS == new_rv) { - VbExDiskFreeInfo(disk_info, lkp.disk_handle); + VbExDiskFreeInfo(disk_info, disk_info[i].handle); return VB2_SUCCESS; } @@ -115,7 +116,8 @@ } /* If we drop out of the loop, we didn't find any usable kernel. */ - if (get_info_flags & VB_DISK_FLAG_FIXED) { + if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && + !(ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)) { switch (rv) { case VB2_ERROR_LK_INVALID_KERNEL_FOUND: vb2api_fail(ctx, VB2_RECOVERY_RW_INVALID_OS, rv); @@ -138,38 +140,17 @@ return rv; } -static vb2_error_t vb2_kernel_init_kparams(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *kparams) +test_mockable +vb2_error_t VbTryLoadKernel(struct vb2_context *ctx, uint32_t disk_flags) { - /* Fill in params for calls to LoadKernel() */ - memset(&lkp, 0, sizeof(lkp)); - lkp.kernel_buffer = kparams->kernel_buffer; - lkp.kernel_buffer_size = kparams->kernel_buffer_size; - - /* Clear output params in case we fail */ - kparams->disk_handle = NULL; - kparams->partition_number = 0; - kparams->bootloader_address = 0; - kparams->bootloader_size = 0; - kparams->flags = 0; - memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid)); - - return VB2_SUCCESS; + return VbTryLoadKernelImpl(ctx, disk_flags, 0, 0); } -static void vb2_kernel_fill_kparams(struct vb2_context *ctx, - VbSelectAndLoadKernelParams *kparams) +test_mockable +vb2_error_t VbTryLoadMiniOsKernel(struct vb2_context *ctx, + uint32_t minios_flags) { - /* Save disk parameters */ - kparams->disk_handle = lkp.disk_handle; - kparams->partition_number = lkp.partition_number; - kparams->bootloader_address = lkp.bootloader_address; - kparams->bootloader_size = lkp.bootloader_size; - kparams->flags = lkp.flags; - kparams->kernel_buffer = lkp.kernel_buffer; - kparams->kernel_buffer_size = lkp.kernel_buffer_size; - memcpy(kparams->partition_guid, lkp.partition_guid, - sizeof(kparams->partition_guid)); + return VbTryLoadKernelImpl(ctx, VB_DISK_FLAG_FIXED, 1, minios_flags); } vb2_error_t VbSelectAndLoadKernel(struct vb2_context *ctx, @@ -178,12 +159,14 @@ struct vb2_shared_data *sd = vb2_get_sd(ctx); vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx); + /* TODO: Send this argument through subsequent function calls, rather + than relying on a global to pass it to VbTryLoadKernel. */ + kparams_ptr = kparams; + /* Init nvstorage space. TODO(kitching): Remove once we add assertions to vb2_nv_get and vb2_nv_set. */ vb2_nv_init(ctx); - VB2_TRY(vb2_kernel_init_kparams(ctx, kparams)); - VB2_TRY(vb2api_kernel_phase1(ctx)); VB2_DEBUG("GBB flags are %#x\n", gbb_flags); @@ -199,13 +182,15 @@ } /* - * If in non-manual recovery mode, save the recovery reason as subcode. + * If in the broken screen, save the recovery reason as subcode. * Otherwise, clear any leftover recovery requests or subcodes. */ vb2_clear_recovery(ctx); /* Select boot path */ - if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { + switch (ctx->boot_mode) { + case VB2_BOOT_MODE_MANUAL_RECOVERY: + case VB2_BOOT_MODE_BROKEN_SCREEN: /* If we're in recovery mode just to do memory retraining, all we need to do is reboot. */ if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) { @@ -230,46 +215,37 @@ VB2_DEBUG("NO_BOOT in RECOVERY mode\n"); /* Recovery boot. This has UI. */ - if (MENU_UI) { - if (vb2_allow_recovery(ctx)) - VB2_TRY(vb2_manual_recovery_menu(ctx)); - else - VB2_TRY(vb2_broken_recovery_menu(ctx)); - } else if (LEGACY_MENU_UI) { - VB2_TRY(VbBootRecoveryLegacyMenu(ctx)); - } else { - VB2_TRY(VbBootRecoveryLegacyClamshell(ctx)); - } - } else if (DIAGNOSTIC_UI && vb2api_diagnostic_ui_enabled(ctx) && - vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) { + if (ctx->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY) + VB2_TRY(vb2ex_manual_recovery_ui(ctx)); + else + VB2_TRY(vb2ex_broken_screen_ui(ctx)); + break; + case VB2_BOOT_MODE_DIAGNOSTICS: + /* + * Need to clear the request flag and commit nvdata changes + * immediately to avoid booting back into diagnostic tool when a + * forced system reset occurs. + */ vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0); + vb2ex_commit_data(ctx); /* Diagnostic boot. This has UI. */ - if (MENU_UI) - VB2_TRY(vb2_diagnostic_menu(ctx)); - else - /* - * Only power button is used for input so no - * detachable-specific UI is needed. This mode is also - * 1-shot so it's placed before developer mode. - */ - VB2_TRY(VbBootDiagnosticLegacyClamshell(ctx)); + VB2_TRY(vb2ex_diagnostic_ui(ctx)); /* * The diagnostic menu should either boot a rom, or * return either of reboot or shutdown. */ return VB2_REQUEST_REBOOT; - } else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) { + case VB2_BOOT_MODE_DEVELOPER: /* Developer boot. This has UI. */ - if (MENU_UI) - VB2_TRY(vb2_developer_menu(ctx)); - else if (LEGACY_MENU_UI) - VB2_TRY(VbBootDeveloperLegacyMenu(ctx)); - else - VB2_TRY(VbBootDeveloperLegacyClamshell(ctx)); - } else { + VB2_TRY(vb2ex_developer_ui(ctx)); + break; + case VB2_BOOT_MODE_NORMAL: /* Normal boot */ VB2_TRY(vb2_normal_boot(ctx)); + break; + default: + return VB2_ERROR_ESCAPE_NO_BOOT; } /* @@ -283,6 +259,5 @@ return VB2_ERROR_ESCAPE_NO_BOOT; } - vb2_kernel_fill_kparams(ctx, kparams); return VB2_SUCCESS; } diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_audio.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_audio.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_audio.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_audio.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Delay/beep functions used in dev-mode kernel selection. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2sysincludes.h" -#include "vboot_api.h" -#include "vboot_audio.h" - -int audio_open_count = 0; /* Times audio has been opened */ -static int audio_use_short; /* Use short delay? */ -static uint32_t open_time; /* Time of last open */ -static int beep_count; /* Number of beeps so far */ - -/** - * Initialization function. - */ -void vb2_audio_start(struct vb2_context *ctx) -{ - open_time = vb2ex_mtime(); /* "zero" starts now */ - beep_count = 0; - - if (vb2api_use_short_dev_screen_delay(ctx) && - (audio_open_count++ == 0)) { - VB2_DEBUG("vb2_audio_start() - using short dev screen delay\n"); - audio_use_short = 1; - } else { - audio_use_short = 0; - } -} - -/** - * Caller should loop without extra delay until this returns false. - */ -int vb2_audio_looping(void) -{ - uint32_t now = vb2ex_mtime() - open_time; - - /* If we're using short delay, wait 2 seconds and don't beep */ - if (audio_use_short) - return now < 2 * VB2_MSEC_PER_SEC; - - /* Otherwise, beep at 20 and 20.5 seconds */ - if ((beep_count == 0 && now > 20 * VB2_MSEC_PER_SEC) || - (beep_count == 1 && now > 20 * VB2_MSEC_PER_SEC + 500)) { - vb2ex_beep(250, 400); - beep_count++; - } - - /* Stop after 30 seconds */ - return (now < 30 * VB2_MSEC_PER_SEC); -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_kernel.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_kernel.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -6,67 +6,55 @@ * (Firmware portion) */ +#include "2api.h" #include "2common.h" #include "2misc.h" #include "2nvstorage.h" -#include "2rsa.h" -#include "2sha.h" +#include "2packed_key.h" #include "2secdata.h" #include "2sysincludes.h" #include "cgptlib.h" #include "cgptlib_internal.h" #include "gpt_misc.h" #include "load_kernel_fw.h" -#include "vb2_common.h" #include "vboot_api.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#define LOWEST_TPM_VERSION 0xffffffff - -enum vboot_mode { - kBootRecovery = 0, /* Recovery firmware, any dev switch position */ - kBootNormal = 1, /* Normal boot - kernel must be verified */ - kBootDev = 2 /* Developer boot - self-signed kernel ok */ +enum vb2_load_partition_flags { + VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY = (1 << 0), + VB2_LOAD_PARTITION_FLAG_MINIOS = (1 << 1), }; -/** - * Return the boot mode based on the parameters. - * - * @param params Load kernel parameters - * @return The current boot mode. - */ -static enum vboot_mode get_kernel_boot_mode(struct vb2_context *ctx) -{ - if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) - return kBootRecovery; +#define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */ - if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) - return kBootDev; +/* Minimum context work buffer size needed for vb2_load_partition() */ +#define VB2_LOAD_PARTITION_WORKBUF_BYTES \ + (VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES + KBUF_SIZE) - return kBootNormal; -}; +#define LOWEST_TPM_VERSION 0xffffffff /** - * Check if the parameters require an officially signed OS. + * Check if a valid keyblock is required. * - * @param params Load kernel parameters - * @return 1 if official OS required; 0 if self-signed kernels are ok + * @param ctx Vboot context + * @return 1 if valid keyblock required (officially signed kernel); + * 0 if valid hash is enough (self-signed kernel). */ -static int require_official_os(struct vb2_context *ctx, - const LoadKernelParams *params) +static int need_valid_keyblock(struct vb2_context *ctx) { /* Normal and recovery modes always require official OS */ - if (get_kernel_boot_mode(ctx) != kBootDev) + if (ctx->boot_mode != VB2_BOOT_MODE_DEVELOPER) return 1; - /* FWMP can require developer mode to use official OS */ + /* FWMP can require developer mode to use signed kernels */ if (vb2_secdata_fwmp_get_flag( ctx, VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY)) return 1; - /* Developer can request official OS via nvstorage */ - return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY); + /* Developers may require signed kernels */ + if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY)) + return 1; + + return 0; } /** @@ -111,53 +99,111 @@ } /** + * Verify developer mode key hash. + * + * @param ctx Vboot context + * @param keyblock Keyblock to verify + * @return VB2_SUCCESS, or non-zero error code. + */ +static vb2_error_t vb2_verify_kernel_dev_key_hash( + struct vb2_context *ctx, struct vb2_keyblock *keyblock) +{ + struct vb2_packed_key *key = &keyblock->data_key; + uint8_t *buf = ((uint8_t *)key) + key->key_offset; + uint32_t buflen = key->key_size; + uint8_t digest[VB2_SHA256_DIGEST_SIZE]; + + VB2_DEBUG("Checking developer key hash.\n"); + VB2_TRY(vb2_digest_buffer(buf, buflen, VB2_HASH_SHA256, digest, + sizeof(digest))); + + uint8_t *fwmp_dev_key_hash = + vb2_secdata_fwmp_get_dev_key_hash(ctx); + if (fwmp_dev_key_hash == NULL) { + VB2_DEBUG("Couldn't retrieve developer key hash.\n"); + return VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH; + } + + if (vb2_safe_memcmp(digest, fwmp_dev_key_hash, + VB2_SHA256_DIGEST_SIZE)) { + int i; + + VB2_DEBUG("Wrong developer key hash.\n"); + VB2_DEBUG("Want: "); + for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++) + VB2_DEBUG_RAW("%02x ", fwmp_dev_key_hash[i]); + VB2_DEBUG_RAW("\n"); + VB2_DEBUG("Got: "); + for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++) + VB2_DEBUG_RAW("%02x ", digest[i]); + VB2_DEBUG_RAW("\n"); + + return VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH; + } + + return VB2_SUCCESS; +} + +/** * Verify a kernel vblock. * + * @param ctx Vboot context * @param kbuf Buffer containing the vblock * @param kbuf_size Size of the buffer in bytes - * @param kernel_subkey Packed kernel subkey to use in validating keyblock - * @param params Load kernel parameters - * @param min_version Minimum kernel version - * @param shpart Destination for verification results + * @param lpflags Flags (one or more of vb2_load_partition_flags) * @param wb Work buffer. Must be at least * VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES bytes. * @return VB2_SUCCESS, or non-zero error code. */ static vb2_error_t vb2_verify_kernel_vblock( struct vb2_context *ctx, uint8_t *kbuf, uint32_t kbuf_size, - const struct vb2_packed_key *kernel_subkey, - const LoadKernelParams *params, uint32_t min_version, - VbSharedDataKernelPart *shpart, struct vb2_workbuf *wb) -{ - /* Unpack kernel subkey */ - struct vb2_public_key kernel_subkey2; - if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2, kernel_subkey)) { - VB2_DEBUG("Unable to unpack kernel subkey\n"); - return VB2_ERROR_VBLOCK_KERNEL_SUBKEY; - } + uint32_t lpflags, struct vb2_workbuf *wb) +{ + struct vb2_shared_data *sd = vb2_get_sd(ctx); - /* Verify the keyblock. */ + uint8_t *key_data; + uint32_t key_size; + struct vb2_public_key kernel_key; + + int need_keyblock_valid = need_valid_keyblock(ctx); int keyblock_valid = 1; /* Assume valid */ + + vb2_error_t rv; + + /* Locate key to verify kernel. This will either be a recovery key, or + a kernel subkey passed from firmware verification. */ + key_data = vb2_member_of(sd, sd->kernel_key_offset); + key_size = sd->kernel_key_size; + VB2_TRY(vb2_unpack_key_buffer(&kernel_key, key_data, key_size)); + + if (vb2_hwcrypto_allowed(ctx)) + kernel_key.allow_hwcrypto = 1; + + /* + * Clear any previous keyblock-valid flag (for example, from a previous + * kernel where the keyblock was signed but the preamble failed + * verification). + */ + sd->flags &= ~VB2_SD_FLAG_KERNEL_SIGNED; + + /* Verify the keyblock. */ struct vb2_keyblock *keyblock = get_keyblock(kbuf); - if (VB2_SUCCESS != vb2_verify_keyblock(keyblock, kbuf_size, - &kernel_subkey2, wb)) { + rv = vb2_verify_keyblock(keyblock, kbuf_size, &kernel_key, wb); + if (rv) { VB2_DEBUG("Verifying keyblock signature failed.\n"); - shpart->check_result = VBSD_LKP_CHECK_KEYBLOCK_SIG; keyblock_valid = 0; /* Check if we must have an officially signed kernel */ - if (require_official_os(ctx, params)) { + if (need_keyblock_valid) { VB2_DEBUG("Self-signed kernels not enabled.\n"); - shpart->check_result = VBSD_LKP_CHECK_SELF_SIGNED; - return VB2_ERROR_VBLOCK_SELF_SIGNED; + return rv; } /* Otherwise, allow the kernel if the keyblock hash is valid */ - if (VB2_SUCCESS != - vb2_verify_keyblock_hash(keyblock, kbuf_size, wb)) { + rv = vb2_verify_keyblock_hash(keyblock, kbuf_size, wb); + if (rv) { VB2_DEBUG("Verifying keyblock hash failed.\n"); - shpart->check_result = VBSD_LKP_CHECK_KEYBLOCK_HASH; - return VB2_ERROR_VBLOCK_KEYBLOCK_HASH; + return rv; } } @@ -167,182 +213,165 @@ VB2_KEYBLOCK_FLAG_DEVELOPER_1 : VB2_KEYBLOCK_FLAG_DEVELOPER_0))) { VB2_DEBUG("Keyblock developer flag mismatch.\n"); - shpart->check_result = VBSD_LKP_CHECK_DEV_MISMATCH; keyblock_valid = 0; + if (need_keyblock_valid) + return VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG; } if (!(keyblock->keyblock_flags & ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) ? VB2_KEYBLOCK_FLAG_RECOVERY_1 : VB2_KEYBLOCK_FLAG_RECOVERY_0))) { VB2_DEBUG("Keyblock recovery flag mismatch.\n"); - shpart->check_result = VBSD_LKP_CHECK_REC_MISMATCH; keyblock_valid = 0; + if (need_keyblock_valid) + return VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG; + } + if (!(keyblock->keyblock_flags & + ((lpflags & VB2_LOAD_PARTITION_FLAG_MINIOS) ? + VB2_KEYBLOCK_FLAG_MINIOS_1 : + VB2_KEYBLOCK_FLAG_MINIOS_0))) { + VB2_DEBUG("Keyblock miniOS flag mismatch.\n"); + keyblock_valid = 0; + if (need_keyblock_valid) + return VB2_ERROR_KERNEL_KEYBLOCK_MINIOS_FLAG; } /* Check for rollback of key version except in recovery mode. */ - enum vboot_mode boot_mode = get_kernel_boot_mode(ctx); uint32_t key_version = keyblock->data_key.key_version; - if (kBootRecovery != boot_mode) { - if (key_version < (min_version >> 16)) { - VB2_DEBUG("Key version too old.\n"); - shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK; + if (ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) { + if (key_version < (sd->kernel_version_secdata >> 16)) { keyblock_valid = 0; + if (need_keyblock_valid) { + VB2_DEBUG("Key version too old.\n"); + return VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK; + } } - if (key_version > 0xFFFF) { + if (key_version > VB2_MAX_KEY_VERSION) { /* * Key version is stored in 16 bits in the TPM, so key * versions greater than 0xFFFF can't be stored * properly. */ VB2_DEBUG("Key version > 0xFFFF.\n"); - shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK; keyblock_valid = 0; + if (need_keyblock_valid) + return VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE; } } - /* If not in developer mode, keyblock required to be valid. */ - if (kBootDev != boot_mode && !keyblock_valid) { - VB2_DEBUG("Keyblock is invalid.\n"); - return VB2_ERROR_VBLOCK_KEYBLOCK; - } - - /* If in developer mode and using key hash, check it */ - if ((kBootDev == boot_mode) && + /* If in developer mode and using key hash, check it. */ + if (ctx->boot_mode == VB2_BOOT_MODE_DEVELOPER && vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_USE_KEY_HASH)) { - struct vb2_packed_key *key = &keyblock->data_key; - uint8_t *buf = ((uint8_t *)key) + key->key_offset; - uint32_t buflen = key->key_size; - uint8_t digest[VB2_SHA256_DIGEST_SIZE]; - - VB2_DEBUG("Checking developer key hash.\n"); - vb2_digest_buffer(buf, buflen, VB2_HASH_SHA256, - digest, sizeof(digest)); - - uint8_t *fwmp_dev_key_hash = - vb2_secdata_fwmp_get_dev_key_hash(ctx); - if (fwmp_dev_key_hash == NULL) { - VB2_DEBUG("Couldn't retrieve developer key hash.\n"); - return VB2_ERROR_VBLOCK_DEV_KEY_HASH; - } - - if (0 != vb2_safe_memcmp(digest, fwmp_dev_key_hash, - VB2_SHA256_DIGEST_SIZE)) { - int i; - - VB2_DEBUG("Wrong developer key hash.\n"); - VB2_DEBUG("Want: "); - for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++) - VB2_DEBUG("%02x", fwmp_dev_key_hash[i]); - VB2_DEBUG("\nGot: "); - for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++) - VB2_DEBUG("%02x", digest[i]); - VB2_DEBUG("\n"); - - return VB2_ERROR_VBLOCK_DEV_KEY_HASH; - } + VB2_TRY(vb2_verify_kernel_dev_key_hash(ctx, keyblock)); } + /* + * At this point, we've checked everything. The kernel keyblock is at + * least self-consistent, and has either a valid signature or a valid + * hash. Track if it had a valid signature (that is, would we have + * been willing to boot it even if developer mode was off). + */ + if (keyblock_valid) + sd->flags |= VB2_SD_FLAG_KERNEL_SIGNED; + /* Get key for preamble verification from the keyblock. */ struct vb2_public_key data_key; - if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) { + rv = vb2_unpack_key(&data_key, &keyblock->data_key); + if (rv) { VB2_DEBUG("Unable to unpack kernel data key\n"); - shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE; - return VB2_ERROR_UNKNOWN; + return rv; } /* Verify the preamble, which follows the keyblock */ struct vb2_kernel_preamble *preamble = get_preamble(kbuf); - if (VB2_SUCCESS != - vb2_verify_kernel_preamble(preamble, - kbuf_size - keyblock->keyblock_size, - &data_key, - wb)) { + rv = vb2_verify_kernel_preamble(preamble, + kbuf_size - keyblock->keyblock_size, + &data_key, + wb); + if (rv) { VB2_DEBUG("Preamble verification failed.\n"); - shpart->check_result = VBSD_LKP_CHECK_VERIFY_PREAMBLE; - return VB2_ERROR_UNKNOWN; + return rv; } - /* - * If the keyblock is valid and we're not in recovery mode, check for - * rollback of the kernel version. - */ - uint32_t combined_version = (key_version << 16) | - (preamble->kernel_version & 0xFFFF); - shpart->combined_version = combined_version; - if (keyblock_valid && kBootRecovery != boot_mode) { - if (combined_version < min_version) { - VB2_DEBUG("Kernel version too low.\n"); - shpart->check_result = VBSD_LKP_CHECK_KERNEL_ROLLBACK; + /* Rollback check for miniOS */ + if (need_keyblock_valid && (lpflags & VB2_LOAD_PARTITION_FLAG_MINIOS)) { + if (preamble->kernel_version < + (sd->kernel_version_secdata >> 24)) { + keyblock_valid = 0; + if (need_keyblock_valid) { + VB2_DEBUG("miniOS kernel version too old.\n"); + return VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK; + } + } + if (preamble->kernel_version > 0xff) { /* - * If not in developer mode, kernel version - * must be valid. + * Key version is stored in the top 8 bits of 16 bits + * in the TPM, so key versions greater than 0xFF can't + * be stored properly. */ - if (kBootDev != boot_mode) - return VB2_ERROR_UNKNOWN; + VB2_DEBUG("Key version > 0xFF.\n"); + keyblock_valid = 0; + if (need_keyblock_valid) + return VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE; } } - VB2_DEBUG("Kernel preamble is good.\n"); - shpart->check_result = VBSD_LKP_CHECK_PREAMBLE_VALID; - if (keyblock_valid) - shpart->flags |= VBSD_LKP_FLAG_KEYBLOCK_VALID; + /* + * Kernel preamble version is the lower 16 bits of the composite + * kernel version. + */ + if (preamble->kernel_version > VB2_MAX_PREAMBLE_VERSION) + return VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE; - return VB2_SUCCESS; -} + /* Combine with the key version. */ + sd->kernel_version = key_version << 16 | preamble->kernel_version; -enum vb2_load_partition_flags { - /* Only check the vblock to */ - VB2_LOAD_PARTITION_VBLOCK_ONLY = (1 << 0), -}; - -#define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */ + /* If not in recovery mode, check for rollback of the kernel version. */ + if (need_keyblock_valid && + ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY && + sd->kernel_version < sd->kernel_version_secdata) { + VB2_DEBUG("Kernel version too low.\n"); + return VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK; + } -/* Minimum context work buffer size needed for vb2_load_partition() */ -#define VB2_LOAD_PARTITION_WORKBUF_BYTES \ - (VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES + KBUF_SIZE) + VB2_DEBUG("Kernel preamble is good.\n"); + return VB2_SUCCESS; +} /** * Load and verify a partition from the stream. * * @param ctx Vboot context - * @param stream Stream to load kernel from - * @param kernel_subkey Key to use to verify vblock - * @param flags Flags (one or more of vb2_load_partition_flags) * @param params Load-kernel parameters - * @param min_version Minimum kernel version from TPM - * @param shpart Destination for verification results - * @param wb Workbuf for data storage + * @param stream Stream to load kernel from + * @param lpflags Flags (one or more of vb2_load_partition_flags) * @return VB2_SUCCESS, or non-zero error code. */ static vb2_error_t vb2_load_partition( - struct vb2_context *ctx, VbExStream_t stream, - const struct vb2_packed_key *kernel_subkey, uint32_t flags, - LoadKernelParams *params, uint32_t min_version, - VbSharedDataKernelPart *shpart, struct vb2_workbuf *wb) + struct vb2_context *ctx, VbSelectAndLoadKernelParams *params, + VbExStream_t stream, uint32_t lpflags) { uint32_t read_ms = 0, start_ts; - struct vb2_workbuf wblocal = *wb; + struct vb2_workbuf wb; + + vb2_workbuf_from_ctx(ctx, &wb); /* Allocate kernel header buffer in workbuf */ - uint8_t *kbuf = vb2_workbuf_alloc(&wblocal, KBUF_SIZE); + uint8_t *kbuf = vb2_workbuf_alloc(&wb, KBUF_SIZE); if (!kbuf) return VB2_ERROR_LOAD_PARTITION_WORKBUF; start_ts = vb2ex_mtime(); if (VbExStreamRead(stream, KBUF_SIZE, kbuf)) { VB2_DEBUG("Unable to read start of partition.\n"); - shpart->check_result = VBSD_LKP_CHECK_READ_START; return VB2_ERROR_LOAD_PARTITION_READ_VBLOCK; } read_ms += vb2ex_mtime() - start_ts; - if (VB2_SUCCESS != - vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, kernel_subkey, - params, min_version, shpart, &wblocal)) { + if (vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, lpflags, &wb)) return VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK; - } - if (flags & VB2_LOAD_PARTITION_VBLOCK_ONLY) + if (lpflags & VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY) return VB2_SUCCESS; struct vb2_keyblock *keyblock = get_keyblock(kbuf); @@ -357,7 +386,6 @@ */ uint32_t body_offset = get_body_offset(kbuf); if (body_offset > KBUF_SIZE) { - shpart->check_result = VBSD_LKP_CHECK_BODY_OFFSET; VB2_DEBUG("Kernel body offset is %u > 64KB.\n", body_offset); return VB2_ERROR_LOAD_PARTITION_BODY_OFFSET; } @@ -370,7 +398,6 @@ kernbuf_size = preamble->body_signature.data_size; } else if (preamble->body_signature.data_size > kernbuf_size) { VB2_DEBUG("Kernel body doesn't fit in memory.\n"); - shpart->check_result = VBSD_LKP_CHECK_BODY_EXCEEDS_MEM; return VB2_ERROR_LOAD_PARTITION_BODY_SIZE; } @@ -392,7 +419,6 @@ start_ts = vb2ex_mtime(); if (body_toread && VbExStreamRead(stream, body_toread, body_readptr)) { VB2_DEBUG("Unable to read kernel data.\n"); - shpart->check_result = VBSD_LKP_CHECK_READ_DATA; return VB2_ERROR_LOAD_PARTITION_READ_BODY; } read_ms += vb2ex_mtime() - start_ts; @@ -405,24 +431,23 @@ /* Get key for preamble/data verification from the keyblock. */ struct vb2_public_key data_key; - if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) { + if (vb2_unpack_key(&data_key, &keyblock->data_key)) { VB2_DEBUG("Unable to unpack kernel data key\n"); - shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE; return VB2_ERROR_LOAD_PARTITION_DATA_KEY; } + if (vb2_hwcrypto_allowed(ctx)) + data_key.allow_hwcrypto = 1; + /* Verify kernel data */ - if (VB2_SUCCESS != vb2_verify_data(kernbuf, kernbuf_size, - &preamble->body_signature, - &data_key, &wblocal)) { + if (vb2_verify_data(kernbuf, kernbuf_size, &preamble->body_signature, + &data_key, &wb)) { VB2_DEBUG("Kernel data verification failed.\n"); - shpart->check_result = VBSD_LKP_CHECK_VERIFY_DATA; return VB2_ERROR_LOAD_PARTITION_VERIFY_BODY; } /* If we're still here, the kernel is valid */ VB2_DEBUG("Partition is good.\n"); - shpart->check_result = VBSD_LKP_CHECK_KERNEL_GOOD; /* Save kernel data back to parameters */ params->bootloader_address = preamble->bootloader_address; @@ -436,94 +461,196 @@ return VB2_SUCCESS; } -vb2_error_t LoadKernel(struct vb2_context *ctx, LoadKernelParams *params) +static vb2_error_t try_minios_kernel(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info, + uint64_t sector) { + VbExStream_t stream; + uint64_t sectors_left = disk_info->lba_count - sector; + const uint32_t lpflags = VB2_LOAD_PARTITION_FLAG_MINIOS; + vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND; + + /* Re-open stream at correct offset to pass to vb2_load_partition. */ + if (VbExStreamOpen(params->disk_handle, sector, sectors_left, + &stream)) { + VB2_DEBUG("Unable to open disk handle.\n"); + return rv; + } + + rv = vb2_load_partition(ctx, params, stream, lpflags); + VB2_DEBUG("vb2_load_partition returned: %d\n", rv); + + VbExStreamClose(stream); + + if (rv) + return VB2_ERROR_LK_NO_KERNEL_FOUND; + return rv; +} + +static vb2_error_t try_minios_sectors(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info, + uint64_t start, uint64_t count) +{ + const uint32_t buf_size = count * disk_info->bytes_per_lba; + char *buf; + VbExStream_t stream; + uint64_t isector; + vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND; + + buf = malloc(buf_size); + if (buf == NULL) { + VB2_DEBUG("Unable to allocate disk read buffer.\n"); + return rv; + } + + if (VbExStreamOpen(params->disk_handle, start, count, &stream)) { + VB2_DEBUG("Unable to open disk handle.\n"); + free(buf); + return rv; + } + if (VbExStreamRead(stream, buf_size, buf)) { + VB2_DEBUG("Unable to read disk.\n"); + free(buf); + VbExStreamClose(stream); + return rv; + } + VbExStreamClose(stream); + + for (isector = 0; isector < count; isector++) { + if (memcmp(buf + isector * disk_info->bytes_per_lba, + VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE)) + continue; + VB2_DEBUG("Match on sector %" PRIu64 " / %" PRIu64 "\n", + start + isector, + disk_info->lba_count - 1); + rv = try_minios_kernel(ctx, params, disk_info, start + isector); + if (rv == VB2_SUCCESS) + break; + } + + free(buf); + return rv; +} + +static vb2_error_t try_minios_sector_region(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info, + int end_region) +{ + const uint64_t disk_count_half = (disk_info->lba_count + 1) / 2; + const uint64_t check_count_256 = 256 * 1024 + * 1024 / disk_info->bytes_per_lba; // 256 MB + const uint64_t batch_count_1 = 1024 + * 1024 / disk_info->bytes_per_lba; // 1 MB + const uint64_t check_count = VB2_MIN(disk_count_half, check_count_256); + const uint64_t batch_count = VB2_MIN(disk_count_half, batch_count_1); + uint64_t sector; + uint64_t start; + uint64_t end; + const char *region_name; + vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND; + + if (!end_region) { + start = 0; + end = check_count; + region_name = "start"; + } else { + start = disk_info->lba_count - check_count; + end = disk_info->lba_count; + region_name = "end"; + } + + VB2_DEBUG("Checking %s of disk for kernels...\n", region_name); + for (sector = start; sector < end; sector += batch_count) { + rv = try_minios_sectors(ctx, params, disk_info, sector, + batch_count); + if (rv == VB2_SUCCESS) + return rv; + } + + return rv; +} + +/* + * Search for kernels by sector, rather than by partition. Only sectors near + * the start and end of disks are considered, and the kernel must start exactly + * at the first byte of the sector. + */ +vb2_error_t LoadMiniOsKernel(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info, uint32_t minios_flags) +{ + vb2_error_t rv; + int end_region_first = vb2_nv_get(ctx, VB2_NV_MINIOS_PRIORITY); + + if (minios_flags & VB_MINIOS_FLAG_NON_ACTIVE) + rv = VB2_ERROR_UNKNOWN; /* Ignore active partition */ + else + rv = try_minios_sector_region(ctx, params, disk_info, + end_region_first); + + if (rv) + rv = try_minios_sector_region(ctx, params, disk_info, + !end_region_first); + if (rv) + return rv; + + rv = vb2ex_tpm_set_mode(VB2_TPM_MODE_DISABLED); + if (rv) + VB2_DEBUG("Failed to disable TPM\n"); + + return rv; +} + +vb2_error_t LoadKernel(struct vb2_context *ctx, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info) { struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_workbuf wb; - VbSharedDataKernelCall shcall; int found_partitions = 0; uint32_t lowest_version = LOWEST_TPM_VERSION; vb2_error_t rv; - vb2_workbuf_from_ctx(ctx, &wb); - - /* Clear output params in case we fail */ + /* Clear output params */ params->partition_number = 0; - params->bootloader_address = 0; - params->bootloader_size = 0; - params->flags = 0; - - /* - * Set up tracking for this call. This wraps around if called many - * times, so we need to initialize the call entry each time. - */ - memset(&shcall, 0, sizeof(shcall)); - shcall.boot_flags = (uint32_t)params->boot_flags; - shcall.boot_mode = get_kernel_boot_mode(ctx); - shcall.sector_size = (uint32_t)params->bytes_per_lba; - shcall.sector_count = params->streaming_lba_count; - - /* Locate key to verify kernel. This will either be a recovery key, or - a kernel subkey passed from firmware verification. */ - struct vb2_packed_key *kernel_subkey = - vb2_member_of(sd, sd->kernel_key_offset); /* Read GPT data */ GptData gpt; - gpt.sector_bytes = (uint32_t)params->bytes_per_lba; - gpt.streaming_drive_sectors = params->streaming_lba_count; - gpt.gpt_drive_sectors = params->gpt_lba_count; - gpt.flags = params->boot_flags & BOOT_FLAG_EXTERNAL_GPT + gpt.sector_bytes = (uint32_t)disk_info->bytes_per_lba; + gpt.streaming_drive_sectors = disk_info->streaming_lba_count + ?: disk_info->lba_count; + gpt.gpt_drive_sectors = disk_info->lba_count; + gpt.flags = disk_info->flags & VB_DISK_FLAG_EXTERNAL_GPT ? GPT_FLAG_EXTERNAL : 0; - if (0 != AllocAndReadGptData(params->disk_handle, &gpt)) { + if (AllocAndReadGptData(disk_info->handle, &gpt)) { VB2_DEBUG("Unable to read GPT data\n"); - shcall.check_result = VBSD_LKC_CHECK_GPT_READ_ERROR; goto gpt_done; } /* Initialize GPT library */ - if (GPT_SUCCESS != GptInit(&gpt)) { + if (GptInit(&gpt)) { VB2_DEBUG("Error parsing GPT\n"); - shcall.check_result = VBSD_LKC_CHECK_GPT_PARSE_ERROR; goto gpt_done; } /* Loop over candidate kernel partitions */ uint64_t part_start, part_size; - while (GPT_SUCCESS == - GptNextKernelEntry(&gpt, &part_start, &part_size)) { + while (GptNextKernelEntry(&gpt, &part_start, &part_size) == + GPT_SUCCESS) { VB2_DEBUG("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n", part_start, part_size); - /* - * Set up tracking for this partition. This wraps around if - * called many times, so initialize the partition entry each - * time. - */ - VbSharedDataKernelPart *shpart = - shcall.parts + (shcall.kernel_parts_found - & (VBSD_MAX_KERNEL_PARTS - 1)); - memset(shpart, 0, sizeof(VbSharedDataKernelPart)); - shpart->sector_start = part_start; - shpart->sector_count = part_size; - /* - * TODO: GPT partitions start at 1, but cgptlib starts them at - * 0. Adjust here, until cgptlib is fixed. - */ - shpart->gpt_index = (uint8_t)(gpt.current_kernel + 1); - shcall.kernel_parts_found++; - /* Found at least one kernel partition. */ found_partitions++; /* Set up the stream */ VbExStream_t stream = NULL; - if (VbExStreamOpen(params->disk_handle, + if (VbExStreamOpen(disk_info->handle, part_start, part_size, &stream)) { VB2_DEBUG("Partition error getting stream.\n"); - shpart->check_result = VBSD_LKP_CHECK_TOO_SMALL; VB2_DEBUG("Marking kernel as invalid.\n"); GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD); continue; @@ -535,41 +662,31 @@ * If we already have a good kernel, we only needed to * look at the vblock versions to check for rollback. */ - lpflags |= VB2_LOAD_PARTITION_VBLOCK_ONLY; + lpflags |= VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY; } - rv = vb2_load_partition(ctx, - stream, - kernel_subkey, - lpflags, - params, - sd->kernel_version, - shpart, - &wb); + rv = vb2_load_partition(ctx, params, stream, lpflags); VbExStreamClose(stream); - if (rv != VB2_SUCCESS) { - VB2_DEBUG("Marking kernel as invalid.\n"); + if (rv) { + VB2_DEBUG("Marking kernel as invalid (err=%x).\n", rv); GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD); continue; } - int keyblock_valid = (shpart->flags & - VBSD_LKP_FLAG_KEYBLOCK_VALID); - if (keyblock_valid) { - sd->flags |= VB2_SD_FLAG_KERNEL_SIGNED; - /* Track lowest version from a valid header. */ - if (lowest_version > shpart->combined_version) - lowest_version = shpart->combined_version; + int keyblock_valid = sd->flags & VB2_SD_FLAG_KERNEL_SIGNED; + /* Track lowest version from a valid header. */ + if (keyblock_valid && lowest_version > sd->kernel_version) { + lowest_version = sd->kernel_version; } VB2_DEBUG("Keyblock valid: %d\n", keyblock_valid); - VB2_DEBUG("Combined version: %u\n", shpart->combined_version); + VB2_DEBUG("Combined version: %u\n", sd->kernel_version); /* * If we're only looking at headers, we're done with this * partition. */ - if (lpflags & VB2_LOAD_PARTITION_VBLOCK_ONLY) + if (lpflags & VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY) continue; /* @@ -599,7 +716,8 @@ * non-officially-signed kernel, there's no rollback * protection, so we can stop at the first valid kernel. */ - if (kBootRecovery == shcall.boot_mode || !keyblock_valid) { + if (ctx->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY || + !keyblock_valid) { VB2_DEBUG("In recovery mode or dev-signed kernel\n"); break; } @@ -611,7 +729,7 @@ * Otherwise, we'll check all the other headers to see if they * contain a newer key. */ - if (shpart->combined_version == sd->kernel_version) { + if (sd->kernel_version == sd->kernel_version_secdata) { VB2_DEBUG("Same kernel version\n"); break; } @@ -619,12 +737,11 @@ gpt_done: /* Write and free GPT data */ - WriteAndFreeGptData(params->disk_handle, &gpt); + WriteAndFreeGptData(disk_info->handle, &gpt); /* Handle finding a good partition */ if (params->partition_number > 0) { VB2_DEBUG("Good partition %d\n", params->partition_number); - shcall.check_result = VBSD_LKC_CHECK_GOOD_PARTITION; /* * Validity check - only store a new TPM version if we found * one. If lowest_version is still at its initial value, we @@ -632,19 +749,16 @@ * just didn't look. */ if (lowest_version != LOWEST_TPM_VERSION && - lowest_version > sd->kernel_version) + lowest_version > sd->kernel_version_secdata) sd->kernel_version = lowest_version; /* Success! */ rv = VB2_SUCCESS; } else if (found_partitions > 0) { - shcall.check_result = VBSD_LKC_CHECK_INVALID_PARTITIONS; rv = VB2_ERROR_LK_INVALID_KERNEL_FOUND; } else { - shcall.check_result = VBSD_LKC_CHECK_NO_PARTITIONS; rv = VB2_ERROR_LK_NO_KERNEL_FOUND; } - shcall.return_code = (uint8_t)rv; return rv; } diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,305 +0,0 @@ -/* Copyright 2018 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware wrapper API - user interface for RW firmware - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2sysincludes.h" -#include "vboot_api.h" -#include "vboot_kernel.h" -#include "vboot_test.h" -#include "vboot_ui_legacy.h" - -const char dev_disable_msg[] = - "Developer mode is disabled on this device by system policy.\n" - "For more information, see http://dev.chromium.org/chromium-os/fwmp\n" - "\n"; - -static void Uint8ToString(char *buf, uint8_t val) -{ - const char *trans = "0123456789abcdef"; - *buf++ = trans[val >> 4]; - *buf = trans[val & 0xF]; -} - -static void FillInSha1Sum(char *outbuf, struct vb2_packed_key *key) -{ - uint8_t *buf = ((uint8_t *)key) + key->key_offset; - uint64_t buflen = key->key_size; - uint8_t digest[VB2_SHA1_DIGEST_SIZE]; - int i; - - vb2_digest_buffer(buf, buflen, VB2_HASH_SHA1, digest, sizeof(digest)); - for (i = 0; i < sizeof(digest); i++) { - Uint8ToString(outbuf, digest[i]); - outbuf += 2; - } - *outbuf = '\0'; -} - -#define DEBUG_INFO_SIZE 1024 -#define DEBUG_INFO_APPEND(format, args...) do { \ - if (used < DEBUG_INFO_SIZE) \ - used += snprintf(buf + used, DEBUG_INFO_SIZE - used, format, \ - ## args); \ -} while (0) - -vb2_error_t VbDisplayDebugInfo(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - struct vb2_workbuf wb; - char buf[DEBUG_INFO_SIZE] = ""; - char sha1sum[VB2_SHA1_DIGEST_SIZE * 2 + 1]; - int32_t used = 0; - vb2_error_t ret; - uint32_t i; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Add hardware ID */ - { - char hwid[VB2_GBB_HWID_MAX_SIZE]; - uint32_t size = sizeof(hwid); - ret = vb2api_gbb_read_hwid(ctx, hwid, &size); - if (ret) - strcpy(hwid, "{INVALID}"); - DEBUG_INFO_APPEND("HWID: %s", hwid); - } - - /* Add recovery reason and subcode */ - i = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE); - DEBUG_INFO_APPEND("\nrecovery_reason: %#.2x / %#.2x %s", - sd->recovery_reason, i, - vb2_get_recovery_reason_string(sd->recovery_reason)); - - /* Add vb2_context and vb2_shared_data flags */ - DEBUG_INFO_APPEND("\ncontext.flags: %#.16" PRIx64, ctx->flags); - DEBUG_INFO_APPEND("\nshared_data.flags: %#.8x", sd->flags); - DEBUG_INFO_APPEND("\nshared_data.status: %#.8x", sd->status); - - /* Add raw contents of nvdata */ - DEBUG_INFO_APPEND("\nnvdata:"); - if (vb2_nv_get_size(ctx) > 16) /* Multi-line starts on next line */ - DEBUG_INFO_APPEND("\n "); - for (i = 0; i < vb2_nv_get_size(ctx); i++) { - /* Split into 16-byte blocks */ - if (i > 0 && i % 16 == 0) - DEBUG_INFO_APPEND("\n "); - DEBUG_INFO_APPEND(" %02x", ctx->nvdata[i]); - } - - /* Add dev_boot_usb flag */ - i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL); - DEBUG_INFO_APPEND("\ndev_boot_usb: %d", i); - - /* Add dev_boot_legacy flag */ - i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY); - DEBUG_INFO_APPEND("\ndev_boot_legacy: %d", i); - - /* Add dev_default_boot flag */ - i = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); - DEBUG_INFO_APPEND("\ndev_default_boot: %d", i); - - /* Add dev_boot_signed_only flag */ - i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY); - DEBUG_INFO_APPEND("\ndev_boot_signed_only: %d", i); - - /* Add TPM versions */ - DEBUG_INFO_APPEND("\nTPM: fwver=%#.8x kernver=%#.8x", - sd->fw_version_secdata, sd->kernel_version_secdata); - - /* Add GBB flags */ - DEBUG_INFO_APPEND("\ngbb.flags: %#.8x", gbb->flags); - - /* Add sha1sum for Root & Recovery keys */ - { - struct vb2_packed_key *key; - struct vb2_workbuf wblocal = wb; - ret = vb2_gbb_read_root_key(ctx, &key, NULL, &wblocal); - if (!ret) { - FillInSha1Sum(sha1sum, key); - DEBUG_INFO_APPEND("\ngbb.rootkey: %s", sha1sum); - } - } - - { - struct vb2_packed_key *key; - struct vb2_workbuf wblocal = wb; - ret = vb2_gbb_read_recovery_key(ctx, &key, NULL, &wblocal); - if (!ret) { - FillInSha1Sum(sha1sum, key); - DEBUG_INFO_APPEND("\ngbb.recovery_key: %s", sha1sum); - } - } - - /* If we're in dev-mode, show the kernel subkey that we expect, too. */ - if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && - sd->kernel_key_offset) { - struct vb2_packed_key *key = - vb2_member_of(sd, sd->kernel_key_offset); - FillInSha1Sum(sha1sum, key); - DEBUG_INFO_APPEND("\nkernel_subkey: %s", sha1sum); - } - - /* Make sure we finish with a newline */ - DEBUG_INFO_APPEND("\n"); - - /* TODO: add more interesting data: - * - Information on current disks */ - - buf[DEBUG_INFO_SIZE - 1] = '\0'; - VB2_DEBUG("[TAB] Debug Info:\n%s", buf); - return VbExDisplayDebugInfo(buf, 1); -} - -vb2_error_t VbCheckDisplayKey(struct vb2_context *ctx, uint32_t key, - uint32_t screen, const VbScreenData *data) -{ - uint32_t loc = 0; - uint32_t count = 0; - - switch (key) { - case '\t': - /* Tab = display debug info */ - return VbDisplayDebugInfo(ctx); - case VB_KEY_ESC: - /* Force redraw current screen (to clear Tab debug output) */ - return VbDisplayScreen(ctx, screen, 1, data); - case VB_KEY_LEFT: - case VB_KEY_RIGHT: - case VB_KEY_UP: - case VB_KEY_DOWN: - /* Arrow keys = change localization */ - loc = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - count = vb2ex_get_locale_count(); - if (count == 0) - loc = 0; /* No localization count (bad GBB?) */ - else if (VB_KEY_RIGHT == key || VB_KEY_UP == key) - loc = (loc < count - 1 ? loc + 1 : 0); - else - loc = (loc > 0 ? loc - 1 : count - 1); - VB2_DEBUG("VbCheckDisplayKey() - change localization to %d\n", - (int)loc); - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, loc); - vb2_nv_set(ctx, VB2_NV_BACKUP_NVRAM_REQUEST, 1); - - /* - * Non-manual recovery mode is meant to be left via three-finger - * salute (into manual recovery mode). Need to commit nvdata - * changes immediately. Ignore commit errors in recovery mode. - */ - if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && - !vb2_allow_recovery(ctx)) - vb2ex_commit_data(ctx); - - /* Force redraw of current screen */ - return VbDisplayScreen(ctx, screen, 1, data); - } - - return VB2_SUCCESS; -} - -static enum { - POWER_BUTTON_HELD_SINCE_BOOT = 0, - POWER_BUTTON_RELEASED, - POWER_BUTTON_PRESSED, /* Must have been previously released */ -} power_button_state; - -void vb2_reset_power_button(void) { - power_button_state = POWER_BUTTON_HELD_SINCE_BOOT; -} - -void vb2_error_beep(enum vb2_beep_type beep) -{ - switch (beep) { - case VB_BEEP_FAILED: - vb2ex_beep(250, 200); - break; - default: - case VB_BEEP_NOT_ALLOWED: - vb2ex_beep(120, 400); - vb2ex_msleep(120); - vb2ex_beep(120, 400); - break; - } -} - -void vb2_error_notify(const char *print_msg, - const char *log_msg, - enum vb2_beep_type beep) -{ - if (print_msg) - VbExDisplayDebugInfo(print_msg, 0); - if (!log_msg) - log_msg = print_msg; - if (log_msg) - VB2_DEBUG(log_msg); - vb2_error_beep(beep); -} - -void vb2_error_no_altfw(void) -{ - VB2_DEBUG("Legacy boot is disabled\n"); - VbExDisplayDebugInfo("WARNING: Booting legacy BIOS has not been " - "enabled. Refer to the developer-mode " - "documentation for details.\n", 0); - vb2_error_beep(VB_BEEP_NOT_ALLOWED); -} - -void vb2_try_altfw(struct vb2_context *ctx, int allowed, - enum VbAltFwIndex_t altfw_num) -{ - if (!allowed) { - vb2_error_no_altfw(); - return; - } - - if (vb2ex_commit_data(ctx)) { - vb2_error_notify("Error committing data on legacy boot.\n", - NULL, VB_BEEP_FAILED); - return; - } - - /* Will not return if successful */ - VbExLegacy(altfw_num); - - vb2_error_notify("Legacy boot failed. Missing BIOS?\n", NULL, - VB_BEEP_FAILED); -} - -int vb2_want_shutdown(struct vb2_context *ctx, uint32_t key) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - uint32_t shutdown_request = VbExIsShutdownRequested(); - - /* - * Ignore power button push until after we have seen it released. - * This avoids shutting down immediately if the power button is still - * being held on startup. After we've recognized a valid power button - * push then don't report the event until after the button is released. - */ - if (shutdown_request & VB_SHUTDOWN_REQUEST_POWER_BUTTON) { - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - if (power_button_state == POWER_BUTTON_RELEASED) - power_button_state = POWER_BUTTON_PRESSED; - } else { - if (power_button_state == POWER_BUTTON_PRESSED) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - power_button_state = POWER_BUTTON_RELEASED; - } - - if (key == VB_BUTTON_POWER_SHORT_PRESS) - shutdown_request |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - /* If desired, ignore shutdown request due to lid closure. */ - if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; - - return shutdown_request; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy_clamshell.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy_clamshell.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy_clamshell.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy_clamshell.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,545 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware wrapper API - user interface for RW firmware - */ - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "load_kernel_fw.h" -#include "tlcl.h" -#include "vb2_common.h" -#include "vboot_api.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#include "vboot_test.h" -#include "vboot_ui_legacy.h" -#include "vboot_ui_legacy_wilco.h" - -static uint32_t disp_current_screen = VB_SCREEN_BLANK; - -test_mockable -vb2_error_t VbDisplayScreen(struct vb2_context *ctx, uint32_t screen, int force, - const VbScreenData *data) -{ - uint32_t locale; - - /* If requested screen is the same as the current one, we're done. */ - if (disp_current_screen == screen && !force) - return VB2_SUCCESS; - - /* Keep track of the currently displayed screen */ - disp_current_screen = screen; - - /* Read the locale last saved */ - locale = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - - return VbExDisplayScreen(screen, locale, data); -} - -static vb2_error_t VbTryUsb(struct vb2_context *ctx) -{ - int retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); - if (VB2_SUCCESS == retval) { - VB2_DEBUG("developer UI - booting USB\n"); - } else { - vb2_error_notify("Could not boot from USB\n", - "developer UI - no kernel found on USB\n", - VB_BEEP_FAILED); - } - return retval; -} - -int VbUserConfirms(struct vb2_context *ctx, uint32_t confirm_flags) -{ - uint32_t key; - uint32_t key_flags; - uint32_t btn; - int button_pressed = 0; - int shutdown_requested = 0; - - VB2_DEBUG("Entering(%x)\n", confirm_flags); - - /* Await further instructions */ - do { - key = VbExKeyboardReadWithFlags(&key_flags); - shutdown_requested = vb2_want_shutdown(ctx, key); - switch (key) { - case VB_KEY_ENTER: - /* If we are using a trusted keyboard or a trusted - * keyboard is not required then return yes, otherwise - * keep waiting (for instance if the user is using a - * USB keyboard). - */ - if (!(confirm_flags & VB_CONFIRM_MUST_TRUST_KEYBOARD) || - (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { - VB2_DEBUG("Yes (1)\n"); - return 1; - } - - /* - * If physical presence is confirmed using the keyboard, - * beep and notify the user when the ENTER key comes - * from an untrusted keyboard. - * - * If physical presence is confirmed using a physical - * button, the existing message on the screen will - * instruct the user which button to push. Silently - * ignore any ENTER presses. - */ - if (PHYSICAL_PRESENCE_KEYBOARD) - vb2_error_notify("Please use internal keyboard " - "to confirm\n", - "VbUserConfirms() - " - "Trusted keyboard is required\n", - VB_BEEP_NOT_ALLOWED); - - break; - case ' ': - VB2_DEBUG("Space (%d)\n", - confirm_flags & VB_CONFIRM_SPACE_MEANS_NO); - if (confirm_flags & VB_CONFIRM_SPACE_MEANS_NO) - return 0; - break; - case VB_KEY_ESC: - VB2_DEBUG("No (0)\n"); - return 0; - default: - /* - * If the physical presence button is separate from the - * keyboard, and is pressed, this is also a YES, but - * must wait for release. - */ - if (!PHYSICAL_PRESENCE_KEYBOARD) { - btn = vb2ex_physical_presence_pressed(); - if (btn) { - VB2_DEBUG("Presence button pressed, " - "awaiting release\n"); - button_pressed = 1; - } else if (button_pressed) { - VB2_DEBUG("Presence button released " - "(1)\n"); - return 1; - } - } - VbCheckDisplayKey(ctx, key, disp_current_screen, NULL); - } - vb2ex_msleep(KEY_DELAY_MS); - } while (!shutdown_requested); - - return -1; -} - -/* - * User interface for selecting alternative firmware - * - * This shows the user a list of bootloaders and allows selection of one of - * them. We loop forever until something is chosen or Escape is pressed. - */ -static vb2_error_t vb2_altfw_ui(struct vb2_context *ctx) -{ - int active = 1; - - VbDisplayScreen(ctx, VB_SCREEN_ALT_FW_PICK, 0, NULL); - - /* We'll loop until the user decides what to do */ - do { - uint32_t key = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key)) { - VB2_DEBUG("developer UI - shutdown requested!\n"); - return VB2_REQUEST_SHUTDOWN; - } - switch (key) { - case 0: - /* nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - return to developer screen */ - VB2_DEBUG("developer UI - user pressed Esc; " - "exit to Developer screen\n"); - active = 0; - break; - /* We allow selection of the default '0' bootloader here */ - case '0'...'9': - VB2_DEBUG("developer UI - user pressed key '%c';" - "Boot alternative firmware\n", key); - /* - * This will not return if successful. Drop out to - * developer mode on failure. - */ - vb2_try_altfw(ctx, 1, key - '0'); - active = 0; - break; - default: - VB2_DEBUG("developer UI - pressed key %#x\n", key); - VbCheckDisplayKey(ctx, key, disp_current_screen, NULL); - break; - } - vb2ex_msleep(KEY_DELAY_MS); - } while (active); - - /* Back to developer screen */ - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); - - return 0; -} - -static vb2_error_t vb2_developer_ui(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - - uint32_t disable_dev_boot = 0; - uint32_t use_usb = 0; - uint32_t use_legacy = 0; - uint32_t ctrl_d_pressed = 0; - - VB2_DEBUG("Entering\n"); - - /* Check if booting from external disk is allowed */ - uint32_t allow_usb = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL); - uint32_t allow_legacy = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY); - - /* Check if the default boot target: internal/external disk or legacy */ - uint32_t default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); - - if (default_boot == VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL) - use_usb = 1; - if (default_boot == VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY) - use_legacy = 1; - - /* Handle GBB flag override */ - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) - allow_usb = 1; - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) - allow_legacy = 1; - if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) { - use_legacy = 1; - use_usb = 0; - } - - /* Handle FWMP override */ - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL)) - allow_usb = 1; - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY)) - allow_legacy = 1; - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) { - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by " - "FORCE_DEV_SWITCH_ON\n"); - } else { - disable_dev_boot = 1; - } - } - - /* If dev mode is disabled, only allow TONORM */ - while (disable_dev_boot) { - VB2_DEBUG("dev_disable_boot is set\n"); - VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_TO_NORM, 0, NULL); - VbExDisplayDebugInfo(dev_disable_msg, 0); - - /* Ignore space in VbUserConfirms()... */ - switch (VbUserConfirms(ctx, 0)) { - case 1: - VB2_DEBUG("leaving dev-mode\n"); - vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - VbDisplayScreen(ctx, - VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); - vb2ex_msleep(5 * VB2_MSEC_PER_SEC); - return VB2_REQUEST_REBOOT; - case -1: - VB2_DEBUG("shutdown requested\n"); - return VB2_REQUEST_SHUTDOWN; - default: - /* Ignore user attempt to cancel */ - VB2_DEBUG("ignore cancel TONORM\n"); - } - } - - if ((ctx->flags & VB2_CONTEXT_VENDOR_DATA_SETTABLE) && - VENDOR_DATA_LENGTH > 0) { - vb2_error_t ret; - VB2_DEBUG("developer UI - Vendor data not set\n"); - ret = vb2_vendor_data_ui(ctx); - if (ret) - return ret; - } - - /* Show the dev mode warning screen */ - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_WARNING, 0, NULL); - - /* Initialize audio/delay context */ - vb2_audio_start(ctx); - - /* We'll loop until we finish the delay or are interrupted */ - do { - uint32_t key = VbExKeyboardRead(); - if (vb2_want_shutdown(ctx, key)) { - VB2_DEBUG("developer UI - shutdown requested!\n"); - return VB2_REQUEST_SHUTDOWN; - } - - switch (key) { - case 0: - /* nothing pressed */ - break; - case VB_KEY_ENTER: - /* Only disable virtual dev switch if allowed by GBB */ - if (!(gbb->flags & VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM)) - break; - __attribute__ ((fallthrough)); - case ' ': - /* See if we should disable virtual dev-mode switch. */ - VB2_DEBUG("sd->flags=%#x\n", sd->flags); - - /* Validity check, should never fail. */ - VB2_ASSERT(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED); - - /* Stop the countdown while we go ask... */ - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - /* - * TONORM won't work (only for - * non-shipping devices). - */ - vb2_error_notify( - "WARNING: TONORM prohibited by " - "GBB FORCE_DEV_SWITCH_ON.\n", - NULL, VB_BEEP_NOT_ALLOWED); - break; - } - VbDisplayScreen(ctx, VB_SCREEN_DEVELOPER_TO_NORM, - 0, NULL); - /* Ignore space in VbUserConfirms()... */ - switch (VbUserConfirms(ctx, 0)) { - case 1: - VB2_DEBUG("leaving dev-mode\n"); - vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - VbDisplayScreen(ctx, - VB_SCREEN_TO_NORM_CONFIRMED, 0, NULL); - vb2ex_msleep(5 * VB2_MSEC_PER_SEC); - return VB2_REQUEST_REBOOT; - case -1: - VB2_DEBUG("shutdown requested\n"); - return VB2_REQUEST_SHUTDOWN; - default: - /* Stay in dev-mode */ - VB2_DEBUG("stay in dev-mode\n"); - VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_WARNING, 0, NULL); - /* Start new countdown */ - vb2_audio_start(ctx); - } - break; - case VB_KEY_CTRL('D'): - /* Ctrl+D = dismiss warning; advance to timeout */ - VB2_DEBUG("developer UI - user pressed Ctrl+D; " - "skip delay\n"); - ctrl_d_pressed = 1; - goto fallout; - case VB_KEY_CTRL('L'): - VB2_DEBUG("developer UI - user pressed Ctrl+L; " - "Try alt firmware\n"); - if (allow_legacy) { - vb2_error_t ret; - - ret = vb2_altfw_ui(ctx); - if (ret) - return ret; - } else { - vb2_error_no_altfw(); - } - break; - case VB_KEY_CTRL_ENTER: - /* - * The Ctrl-Enter is special for Lumpy test purpose; - * fall through to Ctrl+U handler. - */ - case VB_KEY_CTRL('U'): - /* Ctrl+U = try USB boot, or beep if failure */ - VB2_DEBUG("developer UI - user pressed Ctrl+U; " - "try USB\n"); - if (!allow_usb) { - vb2_error_notify( - "WARNING: Booting from external media " - "(USB/SD) has not been enabled. Refer " - "to the developer-mode documentation " - "for details.\n", - "developer UI - " - "USB booting is disabled\n", - VB_BEEP_NOT_ALLOWED); - } else { - /* - * Clear the screen to show we get the Ctrl+U - * key press. - */ - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - if (VB2_SUCCESS == VbTryUsb(ctx)) { - return VB2_SUCCESS; - } else { - /* Show dev mode warning screen again */ - VbDisplayScreen(ctx, - VB_SCREEN_DEVELOPER_WARNING, - 0, NULL); - } - } - break; - /* We allow selection of the default '0' bootloader here */ - case '0'...'9': - VB2_DEBUG("developer UI - user pressed key '%c'; " - "Boot alternative firmware\n", key); - vb2_try_altfw(ctx, allow_legacy, key - '0'); - break; - default: - VB2_DEBUG("developer UI - pressed key %#x\n", key); - VbCheckDisplayKey(ctx, key, disp_current_screen, NULL); - break; - } - - vb2ex_msleep(KEY_DELAY_MS); - } while(vb2_audio_looping()); - - fallout: - - /* If defaulting to legacy boot, try that unless Ctrl+D was pressed */ - if (use_legacy && !ctrl_d_pressed) { - VB2_DEBUG("developer UI - defaulting to legacy\n"); - vb2_try_altfw(ctx, allow_legacy, 0); - } - - if ((use_usb && !ctrl_d_pressed) && allow_usb) { - if (VB2_SUCCESS == VbTryUsb(ctx)) { - return VB2_SUCCESS; - } - } - - /* Timeout or Ctrl+D; attempt loading from fixed disk */ - VB2_DEBUG("developer UI - trying fixed disk\n"); - return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED); -} - -vb2_error_t VbBootDeveloperLegacyClamshell(struct vb2_context *ctx) -{ - vb2_reset_power_button(); - vb2_error_t retval = vb2_developer_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} - -vb2_error_t VbBootDiagnosticLegacyClamshell(struct vb2_context *ctx) -{ - vb2_reset_power_button(); - vb2_error_t retval = vb2_diagnostics_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} - -static vb2_error_t recovery_ui(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - uint32_t retval; - uint32_t key; - const char release_button_msg[] = - "Release the recovery button and try again\n"; - const char recovery_pressed_msg[] = - "^D but recovery switch is pressed\n"; - - VB2_DEBUG("recovery UI - start\n"); - - if (!vb2_allow_recovery(ctx)) { - VbDisplayScreen(ctx, VB_SCREEN_OS_BROKEN, 0, NULL); - VB2_DEBUG("recovery UI - waiting for manual recovery\n"); - while (1) { - key = VbExKeyboardRead(); - VbCheckDisplayKey(ctx, key, disp_current_screen, NULL); - if (vb2_want_shutdown(ctx, key)) - return VB2_REQUEST_SHUTDOWN; - else if ((retval = - vb2_check_diagnostic_key(ctx, key)) != - VB2_SUCCESS) - return retval; - vb2ex_msleep(KEY_DELAY_MS); - } - } - - /* Loop and wait for a recovery image */ - VB2_DEBUG("recovery UI - waiting for a recovery image\n"); - while (1) { - retval = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); - - if (VB2_SUCCESS == retval) - break; /* Found a recovery kernel */ - - enum VbScreenType_t next_screen = - retval == VB2_ERROR_LK_NO_DISK_FOUND ? - VB_SCREEN_RECOVERY_INSERT : VB_SCREEN_RECOVERY_NO_GOOD; - VbDisplayScreen(ctx, next_screen, 0, NULL); - - key = VbExKeyboardRead(); - /* - * We might want to enter dev-mode from the Insert - * screen if all of the following are true: - * - user pressed Ctrl-D - * - we can honor the virtual dev switch - * - not already in dev mode - * - user forced recovery mode - */ - if (key == VB_KEY_CTRL('D') && - !(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) && - (sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY)) { - if (!PHYSICAL_PRESENCE_KEYBOARD && - vb2ex_physical_presence_pressed()) { - /* - * Is the presence button stuck? In any case - * we don't like this. Beep and ignore. - */ - vb2_error_notify(release_button_msg, - recovery_pressed_msg, - VB_BEEP_NOT_ALLOWED); - continue; - } - - /* Ask the user to confirm entering dev-mode */ - VbDisplayScreen(ctx, VB_SCREEN_RECOVERY_TO_DEV, - 0, NULL); - /* SPACE means no... */ - uint32_t vbc_flags = VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD; - switch (VbUserConfirms(ctx, vbc_flags)) { - case 1: - vb2_enable_developer_mode(ctx); - return VB2_REQUEST_REBOOT_EC_TO_RO; - case -1: - VB2_DEBUG("Shutdown requested\n"); - return VB2_REQUEST_SHUTDOWN; - default: /* zero, actually */ - VB2_DEBUG("Not enabling dev-mode\n"); - break; - } - } else if ((retval = vb2_check_diagnostic_key(ctx, key)) != - VB2_SUCCESS) { - return retval; - } else { - VbCheckDisplayKey(ctx, key, disp_current_screen, NULL); - } - if (vb2_want_shutdown(ctx, key)) - return VB2_REQUEST_SHUTDOWN; - vb2ex_msleep(KEY_DELAY_MS); - } - - return VB2_SUCCESS; -} - -vb2_error_t VbBootRecoveryLegacyClamshell(struct vb2_context *ctx) -{ - vb2_error_t retval = recovery_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy_menu.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy_menu.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy_menu.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy_menu.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,935 +0,0 @@ -/* Copyright 2017 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. - * - * High-level firmware wrapper API - user interface for RW firmware - */ - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "load_kernel_fw.h" -#include "vb2_common.h" -#include "vboot_api.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#include "vboot_ui_legacy.h" -#include "vboot_ui_legacy_menu_private.h" - -static VB_MENU current_menu, prev_menu; -static int current_menu_idx, cur_disabled_idx_mask, usb_nogood, force_redraw; -static uint32_t default_boot; -static uint32_t disable_dev_boot; -static uint32_t altfw_allowed; -static struct vb2_menu menus[]; -static const char no_legacy[] = "Legacy boot failed. Missing BIOS?\n"; - -static uint32_t disp_current_screen = VB_SCREEN_BLANK; -static uint32_t disp_current_index = 0; -static uint32_t disp_disabled_idx_mask = 0; - -test_mockable -vb2_error_t VbDisplayMenu(struct vb2_context *ctx, uint32_t screen, int force, - uint32_t selected_index, uint32_t disabled_idx_mask) -{ - uint32_t locale; - uint32_t redraw_base_screen = 0; - - /* - * If requested screen/selected_index is the same as the current one, - * we're done. - */ - if (disp_current_screen == screen && - disp_current_index == selected_index && - !force) - return VB2_SUCCESS; - - /* - * If current screen is not the same, make sure we redraw the base - * screen as well to avoid having artifacts from the menu. - */ - if (disp_current_screen != screen || force) - redraw_base_screen = 1; - - /* - * Keep track of the currently displayed screen and - * selected_index - */ - disp_current_screen = screen; - disp_current_index = selected_index; - disp_disabled_idx_mask = disabled_idx_mask; - - /* Read the locale last saved */ - locale = vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - - return VbExDisplayMenu(screen, locale, selected_index, - disabled_idx_mask, redraw_base_screen); -} - -/** - * Checks GBB flags against VbExIsShutdownRequested() shutdown request to - * determine if a shutdown is required. - * - * Returns true if a shutdown is required and false if no shutdown is required. - */ -static int VbWantShutdownMenu(struct vb2_context *ctx) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - uint32_t shutdown_request = VbExIsShutdownRequested(); - - /* If desired, ignore shutdown request due to lid closure. */ - if (gbb->flags & VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN) - shutdown_request &= ~VB_SHUTDOWN_REQUEST_LID_CLOSED; - - /* - * In detachables, disabling shutdown due to power button. - * We are using it for selection instead. - */ - shutdown_request &= ~VB_SHUTDOWN_REQUEST_POWER_BUTTON; - - return !!shutdown_request; -} - -/* (Re-)Draw the menu identified by current_menu[_idx] to the screen. */ -static vb2_error_t vb2_draw_current_screen(struct vb2_context *ctx) { - vb2_error_t ret = VbDisplayMenu(ctx, menus[current_menu].screen, - force_redraw, current_menu_idx, cur_disabled_idx_mask); - force_redraw = 0; - return ret; -} - -/* Flash the screen to black to catch user awareness, then redraw menu. */ -static void vb2_flash_screen(struct vb2_context *ctx) -{ - VbDisplayMenu(ctx, VB_SCREEN_BLANK, 0, 0, 0); - vb2ex_msleep(50); - vb2_draw_current_screen(ctx); -} - -static void vb2_log_menu_change(void) -{ - if (menus[current_menu].size) - VB2_DEBUG("================ %s Menu ================ [ %s ]\n", - menus[current_menu].name, - menus[current_menu].items[current_menu_idx].text); - else - VB2_DEBUG("=============== %s Screen ===============\n", - menus[current_menu].name); -} - -/** - * Switch to a new menu (but don't draw it yet). - * - * @param new_current_menu: new menu to set current_menu to - * @param new_current_menu_idx: new idx to set current_menu_idx to - */ -static void vb2_change_menu(VB_MENU new_current_menu, - int new_current_menu_idx) -{ - prev_menu = current_menu; - current_menu = new_current_menu; - - /* Reconfigure cur_disabled_idx_mask for the new menu */ - cur_disabled_idx_mask = 0; - /* Disable Network Boot Option */ - if (current_menu == VB_MENU_DEV) - cur_disabled_idx_mask |= 1 << VB_DEV_NETWORK; - /* Disable cancel option if enterprise disabled dev mode */ - if (current_menu == VB_MENU_TO_NORM && - disable_dev_boot == 1) - cur_disabled_idx_mask |= 1 << VB_TO_NORM_CANCEL; - - /* Enable menu items for the selected bootloaders */ - if (current_menu == VB_MENU_ALT_FW) { - cur_disabled_idx_mask = ~(VbExGetAltFwIdxMask() >> 1); - - /* Make sure 'cancel' is shown even with an invalid mask */ - cur_disabled_idx_mask &= (1 << VB_ALTFW_COUNT) - 1; - } - /* We assume that there is at least one enabled item */ - while ((1 << new_current_menu_idx) & cur_disabled_idx_mask) - new_current_menu_idx++; - if (new_current_menu_idx < menus[current_menu].size) - current_menu_idx = new_current_menu_idx; - - vb2_log_menu_change(); -} - -/************************ - * Menu Actions * - ************************/ - -/* Boot from internal disk if allowed. */ -static vb2_error_t boot_disk_action(struct vb2_context *ctx) -{ - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_notify("Developer mode disabled\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - VB2_DEBUG("trying fixed disk\n"); - return VbTryLoadKernel(ctx, VB_DISK_FLAG_FIXED); -} - -/* Boot legacy BIOS if allowed and available. */ -static vb2_error_t boot_legacy_action(struct vb2_context *ctx) -{ - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_notify("Developer mode disabled\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - - if (!altfw_allowed) { - vb2_flash_screen(ctx); - vb2_error_notify("WARNING: Booting legacy BIOS has not " - "been enabled. Refer to the developer" - "-mode documentation for details.\n", - "Legacy boot is disabled\n", - VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - - vb2_try_altfw(ctx, 1, VB_ALTFW_DEFAULT); - vb2_flash_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -/* Boot from USB or SD card if allowed and available. */ -static vb2_error_t boot_usb_action(struct vb2_context *ctx) -{ - const char no_kernel[] = "No bootable kernel found on USB/SD.\n"; - - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_notify("Developer mode disabled\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - - if (!vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) && - !(vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) && - !vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL)) { - vb2_flash_screen(ctx); - vb2_error_notify("WARNING: Booting from external media " - "(USB/SD) has not been enabled. Refer " - "to the developer-mode documentation " - "for details.\n", - "USB booting is disabled\n", - VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - - if (VB2_SUCCESS == VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE)) { - VB2_DEBUG("booting USB\n"); - return VB2_SUCCESS; - } - - vb2_flash_screen(ctx); - vb2_error_notify(no_kernel, NULL, VB_BEEP_FAILED); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_developer_menu(struct vb2_context *ctx) -{ - int menu_idx; - switch(default_boot) { - default: - case VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL: - menu_idx = VB_DEV_DISK; - break; - case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL: - menu_idx = VB_DEV_USB; - break; - case VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY: - menu_idx = VB_DEV_LEGACY; - break; - } - vb2_change_menu(VB_MENU_DEV, menu_idx); - vb2_draw_current_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_dev_warning_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_DEV_WARNING, VB_WARN_POWER_OFF); - vb2_draw_current_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_language_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_LANGUAGES, - vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX)); - vb2_draw_current_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_recovery_base_screen(struct vb2_context *ctx) -{ - if (!vb2_allow_recovery(ctx)) - vb2_change_menu(VB_MENU_RECOVERY_BROKEN, 0); - else if (usb_nogood) - vb2_change_menu(VB_MENU_RECOVERY_NO_GOOD, 0); - else - vb2_change_menu(VB_MENU_RECOVERY_INSERT, 0); - vb2_draw_current_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_options_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_OPTIONS, VB_OPTIONS_CANCEL); - vb2_draw_current_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_to_dev_menu(struct vb2_context *ctx) -{ - const char dev_already_on[] = - "WARNING: TODEV rejected, developer mode is already on.\n"; - if (vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) { - vb2_flash_screen(ctx); - vb2_error_notify(dev_already_on, NULL, VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - vb2_change_menu(VB_MENU_TO_DEV, VB_TO_DEV_CANCEL); - vb2_draw_current_screen(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t enter_to_norm_menu(struct vb2_context *ctx) -{ - vb2_change_menu(VB_MENU_TO_NORM, VB_TO_NORM_CONFIRM); - vb2_draw_current_screen(ctx); - /* Make sure user knows dev mode disabled */ - if (disable_dev_boot) - VbExDisplayDebugInfo(dev_disable_msg, 0); - return VB2_REQUEST_UI_CONTINUE; -} - -/* Boot alternative bootloader if allowed and available. */ -static vb2_error_t enter_altfw_menu(struct vb2_context *ctx) -{ - VB2_DEBUG("enter_altfw_menu()\n"); - if (disable_dev_boot) { - vb2_flash_screen(ctx); - vb2_error_beep(VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - if (!altfw_allowed) { - vb2_flash_screen(ctx); - vb2_error_no_altfw(); - return VB2_REQUEST_UI_CONTINUE; - } - vb2_change_menu(VB_MENU_ALT_FW, 0); - vb2_draw_current_screen(ctx); - - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t debug_info_action(struct vb2_context *ctx) -{ - force_redraw = 1; - VbDisplayDebugInfo(ctx); - return VB2_REQUEST_UI_CONTINUE; -} - -/* Action when selecting a language entry in the language menu. */ -static vb2_error_t language_action(struct vb2_context *ctx) -{ - /* Write selected language ID back to NVRAM. */ - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, current_menu_idx); - - /* - * Non-manual recovery mode is meant to be left via three-finger - * salute (into manual recovery mode). Need to commit nvdata - * changes immediately. Ignore commit errors in recovery mode. - */ - if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) && - !vb2_allow_recovery(ctx)) - vb2ex_commit_data(ctx); - - /* Return to previous menu. */ - switch (prev_menu) { - case VB_MENU_DEV_WARNING: - return enter_dev_warning_menu(ctx); - case VB_MENU_DEV: - return enter_developer_menu(ctx); - case VB_MENU_TO_NORM: - return enter_to_norm_menu(ctx); - case VB_MENU_TO_DEV: - return enter_to_dev_menu(ctx); - case VB_MENU_OPTIONS: - return enter_options_menu(ctx); - default: - /* This should never happen. */ - VB2_DEBUG("ERROR: prev_menu state corrupted, force shutdown\n"); - return VB2_REQUEST_SHUTDOWN; - } -} - -/* Action when selecting a bootloader in the alternative firmware menu. */ -static vb2_error_t altfw_action(struct vb2_context *ctx) -{ - vb2_try_altfw(ctx, 1, current_menu_idx + 1); - vb2_flash_screen(ctx); - VB2_DEBUG(no_legacy); - VbExDisplayDebugInfo(no_legacy, 0); - - return VB2_REQUEST_UI_CONTINUE; -} - -/* Action that enables developer mode and reboots. */ -static vb2_error_t to_dev_action(struct vb2_context *ctx) -{ - /* Validity check, should never happen. */ - if ((vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DEV_MODE_ENABLED) || - !vb2_allow_recovery(ctx)) - return VB2_REQUEST_UI_CONTINUE; - - vb2_enable_developer_mode(ctx); - - return VB2_REQUEST_REBOOT_EC_TO_RO; -} - -/* Action that disables developer mode, shows TO_NORM_CONFIRMED and reboots. */ -static vb2_error_t to_norm_action(struct vb2_context *ctx) -{ - if (vb2_get_gbb(ctx)->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - vb2_flash_screen(ctx); - vb2_error_notify("WARNING: TONORM prohibited by " - "GBB FORCE_DEV_SWITCH_ON.\n", NULL, - VB_BEEP_NOT_ALLOWED); - return VB2_REQUEST_UI_CONTINUE; - } - - VB2_DEBUG("leaving dev-mode.\n"); - vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1); - vb2_change_menu(VB_MENU_TO_NORM_CONFIRMED, 0); - vb2_draw_current_screen(ctx); - vb2ex_msleep(5 * VB2_MSEC_PER_SEC); - return VB2_REQUEST_REBOOT; -} - -/* Action that will power off the system. */ -static vb2_error_t power_off_action(struct vb2_context *ctx) -{ - VB2_DEBUG("Power off requested from screen %#x\n", - menus[current_menu].screen); - return VB2_REQUEST_SHUTDOWN; -} - -/** - * Updates current_menu_idx upon an up/down key press, taking into - * account disabled indices (from cur_disabled_idx_mask). The cursor - * will not wrap, meaning that we block on the 0 or max index when - * we hit the ends of the menu. - * - * @param key VOL_KEY_UP = increase index selection - * VOL_KEY_DOWN = decrease index selection. - * Every other key has no effect now. - */ -static void vb2_update_selection(uint32_t key) { - int idx; - - switch (key) { - case VB_BUTTON_VOL_UP_SHORT_PRESS: - case VB_KEY_UP: - idx = current_menu_idx - 1; - while (idx >= 0 && - ((1 << idx) & cur_disabled_idx_mask)) - idx--; - /* Only update if idx is valid */ - if (idx >= 0) - current_menu_idx = idx; - break; - case VB_BUTTON_VOL_DOWN_SHORT_PRESS: - case VB_KEY_DOWN: - idx = current_menu_idx + 1; - while (idx < menus[current_menu].size && - ((1 << idx) & cur_disabled_idx_mask)) - idx++; - /* Only update if idx is valid */ - if (idx < menus[current_menu].size) - current_menu_idx = idx; - break; - default: - VB2_DEBUG("ERROR: %s called with key %#x!\n", __func__, key); - break; - } - - vb2_log_menu_change(); -} - -static vb2_error_t vb2_handle_menu_input(struct vb2_context *ctx, - uint32_t key, uint32_t key_flags) -{ - switch (key) { - case 0: - /* nothing pressed */ - break; - case '\t': - /* Tab = display debug info */ - return debug_info_action(ctx); - case VB_KEY_ESC: - /* Esc = redraw screen (to clear old debug info) */ - vb2_draw_current_screen(ctx); - break; - case VB_KEY_UP: - case VB_KEY_DOWN: - case VB_BUTTON_VOL_UP_SHORT_PRESS: - case VB_BUTTON_VOL_DOWN_SHORT_PRESS: - /* Untrusted (USB keyboard) input disabled for TO_DEV menu. */ - if (current_menu == VB_MENU_TO_DEV && - !(key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD)) { - vb2_flash_screen(ctx); - vb2_error_notify("Please use the on-device volume " - "buttons to navigate\n", - "vb2_handle_menu_input() - Untrusted " - "(USB keyboard) input disabled\n", - VB_BEEP_NOT_ALLOWED); - break; - } - - /* Menuless screens enter OPTIONS on volume button press. */ - if (!menus[current_menu].size) { - enter_options_menu(ctx); - break; - } - - vb2_update_selection(key); - vb2_draw_current_screen(ctx); - break; - case VB_BUTTON_POWER_SHORT_PRESS: - case VB_KEY_ENTER: - /* Menuless screens shut down on power button press. */ - if (!menus[current_menu].size) - return VB2_REQUEST_SHUTDOWN; - - return menus[current_menu].items[current_menu_idx].action(ctx); - default: - VB2_DEBUG("pressed key %#x\n", key); - break; - } - - if (VbWantShutdownMenu(ctx)) { - VB2_DEBUG("shutdown requested!\n"); - return VB2_REQUEST_SHUTDOWN; - } - - return VB2_REQUEST_UI_CONTINUE; -} - -/* Master table of all menus. Menus with size == 0 count as menuless screens. */ -static struct vb2_menu menus[VB_MENU_COUNT] = { - [VB_MENU_DEV_WARNING] = { - .name = "Developer Warning", - .size = VB_WARN_COUNT, - .screen = VB_SCREEN_DEVELOPER_WARNING_MENU, - .items = (struct vb2_menu_item[]){ - [VB_WARN_OPTIONS] = { - .text = "Developer Options", - .action = enter_developer_menu, - }, - [VB_WARN_DBG_INFO] = { - .text = "Show Debug Info", - .action = debug_info_action, - }, - [VB_WARN_ENABLE_VER] = { - .text = "Enable OS Verification", - .action = enter_to_norm_menu, - }, - [VB_WARN_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_WARN_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_DEV] = { - .name = "Developer Boot Options", - .size = VB_DEV_COUNT, - .screen = VB_SCREEN_DEVELOPER_MENU, - .items = (struct vb2_menu_item[]){ - [VB_DEV_NETWORK] = { - .text = "Boot From Network", - .action = NULL, /* unimplemented */ - }, - [VB_DEV_LEGACY] = { - .text = "Boot Legacy BIOS", - .action = enter_altfw_menu, - }, - [VB_DEV_USB] = { - .text = "Boot From USB or SD Card", - .action = boot_usb_action, - }, - [VB_DEV_DISK] = { - .text = "Boot From Internal Disk", - .action = boot_disk_action, - }, - [VB_DEV_CANCEL] = { - .text = "Cancel", - .action = enter_dev_warning_menu, - }, - [VB_DEV_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_DEV_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_TO_NORM] = { - .name = "TO_NORM Confirmation", - .size = VB_TO_NORM_COUNT, - .screen = VB_SCREEN_DEVELOPER_TO_NORM_MENU, - .items = (struct vb2_menu_item[]){ - [VB_TO_NORM_CONFIRM] = { - .text = "Confirm Enabling OS Verification", - .action = to_norm_action, - }, - [VB_TO_NORM_CANCEL] = { - .text = "Cancel", - .action = enter_dev_warning_menu, - }, - [VB_TO_NORM_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_TO_NORM_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_TO_DEV] = { - .name = "TO_DEV Confirmation", - .size = VB_TO_DEV_COUNT, - .screen = VB_SCREEN_RECOVERY_TO_DEV_MENU, - .items = (struct vb2_menu_item[]){ - [VB_TO_DEV_CONFIRM] = { - .text = "Confirm Disabling OS Verification", - .action = to_dev_action, - }, - [VB_TO_DEV_CANCEL] = { - .text = "Cancel", - .action = enter_recovery_base_screen, - }, - [VB_TO_DEV_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_TO_DEV_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_LANGUAGES] = { - .name = "Language Selection", - .screen = VB_SCREEN_LANGUAGES_MENU, - /* Rest is filled out dynamically by vb2_init_menus() */ - }, - [VB_MENU_OPTIONS] = { - .name = "Options", - .size = VB_OPTIONS_COUNT, - .screen = VB_SCREEN_OPTIONS_MENU, - .items = (struct vb2_menu_item[]){ - [VB_OPTIONS_DBG_INFO] = { - .text = "Show Debug Info", - .action = debug_info_action, - }, - [VB_OPTIONS_CANCEL] = { - .text = "Cancel", - .action = enter_recovery_base_screen, - }, - [VB_OPTIONS_POWER_OFF] = { - .text = "Power Off", - .action = power_off_action, - }, - [VB_OPTIONS_LANGUAGE] = { - .text = "Language", - .action = enter_language_menu, - }, - }, - }, - [VB_MENU_RECOVERY_INSERT] = { - .name = "Recovery INSERT", - .size = 0, - .screen = VB_SCREEN_RECOVERY_INSERT, - .items = NULL, - }, - [VB_MENU_RECOVERY_NO_GOOD] = { - .name = "Recovery NO_GOOD", - .size = 0, - .screen = VB_SCREEN_RECOVERY_NO_GOOD, - .items = NULL, - }, - [VB_MENU_RECOVERY_BROKEN] = { - .name = "Non-manual Recovery (BROKEN)", - .size = 0, - .screen = VB_SCREEN_OS_BROKEN, - .items = NULL, - }, - [VB_MENU_TO_NORM_CONFIRMED] = { - .name = "TO_NORM Interstitial", - .size = 0, - .screen = VB_SCREEN_TO_NORM_CONFIRMED, - .items = NULL, - }, - [VB_MENU_ALT_FW] = { - .name = "Alternative Firmware Selection", - .screen = VB_SCREEN_ALT_FW_MENU, - .size = VB_ALTFW_COUNT + 1, - .items = (struct vb2_menu_item[]) {{ - .text = "Bootloader 1", - .action = altfw_action, - }, { - .text = "Bootloader 2", - .action = altfw_action, - }, { - .text = "Bootloader 3", - .action = altfw_action, - }, { - .text = "Bootloader 4", - .action = altfw_action, - }, { - .text = "Bootloader 5", - .action = altfw_action, - }, { - .text = "Bootloader 6", - .action = altfw_action, - }, { - .text = "Bootloader 7", - .action = altfw_action, - }, { - .text = "Bootloader 8", - .action = altfw_action, - }, { - .text = "Bootloader 9", - .action = altfw_action, - }, { - .text = "Cancel", - .action = enter_developer_menu, - }, - }, - }, -}; - -/* Initialize menu state. Must be called once before displaying any menus. */ -static vb2_error_t vb2_init_menus(struct vb2_context *ctx) -{ - struct vb2_menu_item *items; - uint32_t count; - int i; - - /* Initialize language menu with the correct amount of entries. */ - count = vb2ex_get_locale_count(); - if (count == 0) - count = 1; /* Fall back to 1 language entry on failure */ - - items = malloc(count * sizeof(struct vb2_menu_item)); - if (!items) - return VB2_ERROR_UNKNOWN; - - for (i = 0; i < count; i++) { - /* The actual language is drawn by the bootloader */ - items[i].text = "Some Language"; - items[i].action = language_action; - } - menus[VB_MENU_LANGUAGES].size = count; - menus[VB_MENU_LANGUAGES].items = items; - - return VB2_SUCCESS; -} - -/** - * Main function that handles developer warning menu functionality - * - * @param ctx Vboot2 context - * @return VB2_SUCCESS, or non-zero error code if error. - */ -static vb2_error_t vb2_developer_legacy_menu(struct vb2_context *ctx) -{ - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - vb2_error_t ret; - - /* Check if the default is to boot using disk, usb, or legacy */ - default_boot = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT); - if (gbb->flags & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY) - default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY; - - /* Check if developer mode is disabled by FWMP */ - disable_dev_boot = 0; - if (vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_DISABLE_BOOT)) { - if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) { - VB2_DEBUG("FWMP_DEV_DISABLE_BOOT rejected by" - "FORCE_DEV_SWITCH_ON\n"); - } else { - /* If dev mode is disabled, only allow TONORM */ - disable_dev_boot = 1; - VB2_DEBUG("dev_disable_boot is set.\n"); - } - } - - altfw_allowed = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY) || - (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY) || - vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY); - - /* Show appropriate initial menu */ - if (disable_dev_boot) - enter_to_norm_menu(ctx); - else - enter_dev_warning_menu(ctx); - - /* Get audio/delay context */ - vb2_audio_start(ctx); - - /* We'll loop until we finish the delay or are interrupted */ - do { - uint32_t key = VbExKeyboardRead(); - - switch (key) { - case VB_BUTTON_VOL_DOWN_LONG_PRESS: - case VB_KEY_CTRL('D'): - /* Ctrl+D = boot from internal disk */ - ret = boot_disk_action(ctx); - break; - case VB_KEY_CTRL('L'): - /* Ctrl+L = boot alternative bootloader */ - ret = enter_altfw_menu(ctx); - break; - case VB_BUTTON_VOL_UP_LONG_PRESS: - case VB_KEY_CTRL('U'): - /* Ctrl+U = boot from USB or SD card */ - ret = boot_usb_action(ctx); - break; - /* We allow selection of the default '0' bootloader here */ - case '0'...'9': - VB2_DEBUG("developer UI - " - "user pressed key '%c': Boot alternative " - "firmware\n", key); - vb2_try_altfw(ctx, altfw_allowed, key - '0'); - ret = VB2_REQUEST_UI_CONTINUE; - break; - default: - ret = vb2_handle_menu_input(ctx, key, 0); - break; - } - - /* We may have loaded a kernel or decided to shut down now. */ - if (ret != VB2_REQUEST_UI_CONTINUE) - return ret; - - /* Reset 30 second timer whenever we see a new key. */ - if (key != 0) - vb2_audio_start(ctx); - - vb2ex_msleep(KEY_DELAY_MS); - - /* If dev mode was disabled, loop forever (never timeout) */ - } while (disable_dev_boot ? 1 : vb2_audio_looping()); - - if (default_boot == VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY) - boot_legacy_action(ctx); /* Doesn't return on success. */ - - if (default_boot == VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL) - if (VB2_SUCCESS == boot_usb_action(ctx)) - return VB2_SUCCESS; - - return boot_disk_action(ctx); -} - -/* Developer mode entry point. */ -vb2_error_t VbBootDeveloperLegacyMenu(struct vb2_context *ctx) -{ - vb2_error_t retval = vb2_init_menus(ctx); - if (VB2_SUCCESS != retval) - return retval; - retval = vb2_developer_legacy_menu(ctx); - VbDisplayMenu(ctx, VB_SCREEN_BLANK, 0, 0, 0); - return retval; -} - -/* Main function that handles non-manual recovery (BROKEN) menu functionality */ -static vb2_error_t broken_ui(struct vb2_context *ctx) -{ - enter_recovery_base_screen(ctx); - - /* Loop and wait for the user to reset or shut down. */ - VB2_DEBUG("waiting for manual recovery\n"); - while (1) { - uint32_t key = VbExKeyboardRead(); - vb2_error_t ret = vb2_handle_menu_input(ctx, key, 0); - if (ret != VB2_REQUEST_UI_CONTINUE) - return ret; - } -} - -/** - * Main function that handles recovery menu functionality - * - * @param ctx Vboot2 context - * @return VB2_SUCCESS, or non-zero error code if error. - */ -static vb2_error_t recovery_ui(struct vb2_context *ctx) -{ - uint32_t key; - uint32_t key_flags; - vb2_error_t ret; - - /* Loop and wait for a recovery image */ - VB2_DEBUG("waiting for a recovery image\n"); - usb_nogood = -1; - while (1) { - ret = VbTryLoadKernel(ctx, VB_DISK_FLAG_REMOVABLE); - - if (VB2_SUCCESS == ret) - return ret; /* Found a recovery kernel */ - - if (usb_nogood != (ret != VB2_ERROR_LK_NO_DISK_FOUND)) { - /* USB state changed, force back to base screen */ - usb_nogood = ret != VB2_ERROR_LK_NO_DISK_FOUND; - enter_recovery_base_screen(ctx); - } - - key = VbExKeyboardReadWithFlags(&key_flags); - if (key == VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS) { - if (key_flags & VB_KEY_FLAG_TRUSTED_KEYBOARD) - enter_to_dev_menu(ctx); - else - VB2_DEBUG("ERROR: untrusted combo?!\n"); - } else { - ret = vb2_handle_menu_input(ctx, key, key_flags); - if (ret != VB2_REQUEST_UI_CONTINUE) - return ret; - } - vb2ex_msleep(KEY_DELAY_MS); - } -} - -/* Recovery mode entry point. */ -vb2_error_t VbBootRecoveryLegacyMenu(struct vb2_context *ctx) -{ - vb2_error_t retval = vb2_init_menus(ctx); - if (VB2_SUCCESS != retval) - return retval; - if (vb2_allow_recovery(ctx)) - retval = recovery_ui(ctx); - else - retval = broken_ui(ctx); - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - return retval; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy_wilco.c vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy_wilco.c --- vboot-utils-0~R88-13597.B/firmware/lib/vboot_ui_legacy_wilco.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib/vboot_ui_legacy_wilco.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,367 +0,0 @@ -/* Copyright 2020 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. - * - * Code used by vboot_ui_legacy_clamshell for Wilco-specific features. - */ - -#include "2common.h" -#include "2nvstorage.h" -#include "2sysincludes.h" -#include "vboot_api.h" -#include "vboot_ui_legacy.h" -#include "vboot_ui_legacy_wilco.h" - -static inline int is_vowel(uint32_t key) -{ - return key == 'A' || key == 'E' || key == 'I' || - key == 'O' || key == 'U'; -} - -static int vendor_data_length(char *data_value) -{ - for (int len = 0; len <= VENDOR_DATA_LENGTH; len++) { - if (data_value[len] == '\0') - return len; - } - - return VENDOR_DATA_LENGTH; -} - -/* - * Prompt the user to enter the serial number - */ -static vb2_error_t vb2_enter_vendor_data_ui(struct vb2_context *ctx, - char *data_value) -{ - int len = vendor_data_length(data_value); - int blinks = CURSOR_BLINK_MS / KEY_DELAY_MS; - int blink_count = 0; - VbScreenData data = { - .vendor_data = { - .input_text = data_value, - .flags = VB_VENDOR_DATA_SHOW_CURSOR, - .selected_index = 1, - } - }; - - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, 1, &data); - - /* We'll loop until the user decides what to do */ - do { - uint32_t key = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key)) { - VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); - return VB2_REQUEST_SHUTDOWN; - } - switch (key) { - case 0: - /* Nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - return to developer screen */ - VB2_DEBUG("Vendor Data UI - user pressed Esc: " - "exit to Developer screen\n"); - data_value[0] = '\0'; - return VB2_SUCCESS; - case 'a'...'z': - key = toupper(key); - __attribute__ ((fallthrough)); - case '0'...'9': - case 'A'...'Z': - if ((len > 0 && is_vowel(key)) || - len >= VENDOR_DATA_LENGTH) { - vb2_error_beep(VB_BEEP_NOT_ALLOWED); - } else { - data_value[len++] = key; - data_value[len] = '\0'; - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, - 1, &data); - } - - VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", - data_value); - break; - case VB_KEY_BACKSPACE: - if (len > 0) { - data_value[--len] = '\0'; - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, - 1, &data); - } - - VB2_DEBUG("Vendor Data UI - vendor_data: %s\n", - data_value); - break; - case VB_KEY_ENTER: - if (len == VENDOR_DATA_LENGTH) { - /* Enter pressed - confirm input */ - VB2_DEBUG("Vendor Data UI - user pressed " - "Enter: confirm vendor data\n"); - return VB2_SUCCESS; - } else { - vb2_error_beep(VB_BEEP_NOT_ALLOWED); - } - break; - default: - VB2_DEBUG("Vendor Data UI - pressed key %#x\n", key); - VbCheckDisplayKey(ctx, key, VB_SCREEN_SET_VENDOR_DATA, - &data); - break; - } - vb2ex_msleep(KEY_DELAY_MS); - - if (++blink_count == blinks) { - blink_count = 0; - data.vendor_data.flags ^= VB_VENDOR_DATA_SHOW_CURSOR; - data.vendor_data.flags |= - VB_VENDOR_DATA_ONLY_DRAW_CURSOR; - - VbDisplayScreen(ctx, VB_SCREEN_SET_VENDOR_DATA, - 1, &data); - - data.vendor_data.flags &= - ~(VB_VENDOR_DATA_ONLY_DRAW_CURSOR); - } - } while (1); - - return VB2_SUCCESS; -} - -/* - * Prompt the user to confirm the serial number and write to memory - */ -static vb2_error_t vb2_confirm_vendor_data_ui(struct vb2_context *ctx, - char* data_value, VbScreenData *data) -{ - VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, 1, data); - /* We'll loop until the user decides what to do */ - do { - uint32_t key_confirm = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key_confirm)) { - VB2_DEBUG("Confirm Vendor Data UI " - "- shutdown requested!\n"); - return VB2_REQUEST_SHUTDOWN; - } - switch (key_confirm) { - case 0: - /* Nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - return to developer screen */ - VB2_DEBUG("Confirm Vendor Data UI - user " - "pressed Esc: exit to Developer screen\n"); - return VB2_SUCCESS; - case VB_KEY_RIGHT: - case VB_KEY_LEFT: - data->vendor_data.selected_index = - data->vendor_data.selected_index ^ 1; - VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_VENDOR_DATA, - 1, data); - VB2_DEBUG("selected_index:%d\n", - data->vendor_data.selected_index); - break; - case VB_KEY_ENTER: - /* Enter pressed - write vendor data */ - if (data->vendor_data.selected_index == 0) { - VB2_DEBUG("Confirm Vendor Data UI - user " - "selected YES: " - "write vendor data (%s) to VPD\n", - data_value); - vb2_error_t ret = VbExSetVendorData(data_value); - - if (ret == VB2_SUCCESS) { - vb2_nv_set(ctx, - VB2_NV_DISABLE_DEV_REQUEST, - 1); - return VB2_REQUEST_REBOOT; - } else { - vb2_error_notify( - "ERROR: Vendor data was not " - "set.\n" - "System will now shutdown\n", - NULL, VB_BEEP_FAILED); - vb2ex_msleep(5 * VB2_MSEC_PER_SEC); - return VB2_REQUEST_SHUTDOWN; - } - } else { - VB2_DEBUG("Confirm Vendor Data UI - user " - "selected NO: " - "Returning to set screen\n"); - return VB2_SUCCESS; - } - default: - VB2_DEBUG("Confirm Vendor Data UI - pressed " - "key %#x\n", key_confirm); - VbCheckDisplayKey(ctx, key_confirm, - VB_SCREEN_CONFIRM_VENDOR_DATA, data); - break; - } - vb2ex_msleep(KEY_DELAY_MS); - } while (1); - return VB2_SUCCESS; -} - -vb2_error_t vb2_vendor_data_ui(struct vb2_context *ctx) -{ - char data_value[VENDOR_DATA_LENGTH + 1]; - - VbScreenData data = {.vendor_data = {data_value, 0, 0}}; - VbDisplayScreen(ctx, VB_COMPLETE_VENDOR_DATA, 0, NULL); - - do { - uint32_t key_set = VbExKeyboardRead(); - - if (vb2_want_shutdown(ctx, key_set)) { - VB2_DEBUG("Vendor Data UI - shutdown requested!\n"); - return VB2_REQUEST_SHUTDOWN; - } - - switch (key_set) { - case 0: - /* Nothing pressed - do nothing. */ - break; - case VB_KEY_ESC: - /* ESC pressed - boot normally */ - VB2_DEBUG("Vendor Data UI - boot normally\n"); - return VB2_SUCCESS; - break; - case VB_KEY_ENTER: - data_value[0] = '\0'; - do { - /* ENTER pressed - - enter vendor data set screen */ - VB2_DEBUG("Vendor Data UI - Enter VD set " - "screen\n"); - vb2_error_t ret = vb2_enter_vendor_data_ui( - ctx, data_value); - - if (ret) - return ret; - - /* Vendor data was not entered just return */ - if (vendor_data_length(data_value) == 0) { - return VB2_SUCCESS; - } - - /* Reset confirmation answer to YES */ - data.vendor_data.selected_index = 0; - - ret = vb2_confirm_vendor_data_ui( - ctx, data_value, &data); - - if (ret) - return ret; - - /* Break if vendor data confirmed */ - if (data.vendor_data.selected_index == 0) - return VB2_SUCCESS; - } while (1); - break; - default: - break; - } - } while (1); - return VB2_SUCCESS; -} - -vb2_error_t vb2_check_diagnostic_key(struct vb2_context *ctx, uint32_t key) -{ - if (DIAGNOSTIC_UI && (key == VB_KEY_CTRL('C') || key == VB_KEY_F(12))) { - VB2_DEBUG("Diagnostic mode requested, rebooting\n"); - vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); - - return VB2_REQUEST_REBOOT; - } - - return VB2_SUCCESS; -} - -vb2_error_t vb2_diagnostics_ui(struct vb2_context *ctx) -{ - int active = 1; - int button_released = 0; - int button_pressed = 0; - vb2_error_t result = VB2_REQUEST_REBOOT; - int action_confirmed = 0; - uint32_t start_time_ms; - - VbDisplayScreen(ctx, VB_SCREEN_CONFIRM_DIAG, 0, NULL); - - start_time_ms = vb2ex_mtime(); - - /* We'll loop until the user decides what to do */ - do { - uint32_t key = VbExKeyboardRead(); - /* Note that we need to check that the physical presence button - was pressed *and then* released. */ - if (vb2ex_physical_presence_pressed()) { - /* Wait for a release before registering a press. */ - if (button_released) - button_pressed = 1; - } else { - button_released = 1; - if (button_pressed) { - VB2_DEBUG("vb2_diagnostics_ui() - power released\n"); - action_confirmed = 1; - active = 0; - break; - } - } - - /* Check the lid and ignore the power button. */ - if (vb2_want_shutdown(ctx, 0) & ~VB_SHUTDOWN_REQUEST_POWER_BUTTON) { - VB2_DEBUG("vb2_diagnostics_ui() - shutdown request\n"); - result = VB2_REQUEST_SHUTDOWN; - active = 0; - break; - } - - switch (key) { - case 0: - /* Nothing pressed */ - break; - case VB_KEY_ESC: - /* Escape pressed - reboot */ - VB2_DEBUG("vb2_diagnostics_ui() - user pressed Esc\n"); - active = 0; - break; - default: - VB2_DEBUG("vb2_diagnostics_ui() - pressed key %#x\n", - key); - VbCheckDisplayKey(ctx, key, VB_SCREEN_CONFIRM_DIAG, - NULL); - break; - } - if (vb2ex_mtime() - start_time_ms >= 30 * VB2_MSEC_PER_SEC) { - VB2_DEBUG("vb2_diagnostics_ui() - timeout\n"); - break; - } - if (active) { - vb2ex_msleep(KEY_DELAY_MS); - } - } while (active); - - VbDisplayScreen(ctx, VB_SCREEN_BLANK, 0, NULL); - - if (action_confirmed) { - VB2_DEBUG("Diagnostic requested, running\n"); - - if (vb2ex_tpm_set_mode(VB2_TPM_MODE_DISABLED) != - VB2_SUCCESS) { - VB2_DEBUG("Failed to disable TPM\n"); - vb2api_fail(ctx, VB2_RECOVERY_TPM_DISABLE_FAILED, 0); - } else { - vb2_try_altfw(ctx, 1, VB_ALTFW_DIAGNOSTIC); - VB2_DEBUG("Diagnostic failed to run\n"); - /* - * Assuming failure was due to bad hash, though - * the rom could just be missing or invalid. - */ - vb2api_fail(ctx, VB2_RECOVERY_ALTFW_HASH_FAILED, 0); - } - } - - return result; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib20/api_kernel.c vboot-utils-0~R99-14469.B/firmware/lib20/api_kernel.c --- vboot-utils-0~R88-13597.B/firmware/lib20/api_kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib20/api_kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -7,14 +7,13 @@ */ #include "2api.h" +#include "2common.h" #include "2misc.h" #include "2nvstorage.h" #include "2rsa.h" #include "2secdata.h" #include "2sha.h" #include "2sysincludes.h" -#include "vb2_common.h" -#include "vboot_struct.h" vb2_error_t vb2api_load_kernel_vblock(struct vb2_context *ctx) { diff -Nru vboot-utils-0~R88-13597.B/firmware/lib20/include/vb2_common.h vboot-utils-0~R99-14469.B/firmware/lib20/include/vb2_common.h --- vboot-utils-0~R88-13597.B/firmware/lib20/include/vb2_common.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib20/include/vb2_common.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Common functions between firmware and kernel verified boot. - */ - -#ifndef VBOOT_REFERENCE_VB2_COMMON_H_ -#define VBOOT_REFERENCE_VB2_COMMON_H_ - -#include "2api.h" -#include "2common.h" -#include "2return_codes.h" -#include "2sha.h" -#include "2struct.h" -#include "2sysincludes.h" - -struct vb2_public_key; - -/** - * Unpack a vboot1-format key buffer for use in verification - * - * The elements of the unpacked key will point into the source buffer, so don't - * free the source buffer until you're done with the key. - * - * @param key Destintion for unpacked key - * @param buf Source buffer containing packed key - * @param size Size of buffer in bytes - * @return VB2_SUCCESS, or non-zero error code if error. - */ -vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, - const uint8_t *buf, uint32_t size); - -/** - * Unpack a vboot1-format key for use in verification - * - * The elements of the unpacked key will point into the source packed key, so - * don't free the source until you're done with the public key. - * - * @param key Destintion for unpacked key - * @param packed_key Source packed key - * @param size Size of buffer in bytes - * @return VB2_SUCCESS, or non-zero error code if error. - */ -vb2_error_t vb2_unpack_key(struct vb2_public_key *key, - const struct vb2_packed_key *packed_key); - -/** - * Verify a keyblock using its hash. - * - * Header fields are also checked for validity. Does not verify key index or key - * block flags. Use this for self-signed keyblocks in developer mode. - * - * @param block Keyblock to verify - * @param size Size of keyblock buffer - * @param key Key to use to verify block - * @param wb Work buffer - * @return VB2_SUCCESS, or non-zero error code if error. - */ -vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block, - uint32_t size, - const struct vb2_workbuf *wb); - -/** - * Check the validity of a kernel preamble using a public key. - * - * The signature in the preamble is destroyed during the check. - * - * @param preamble Preamble to verify - * @param size Size of preamble buffer - * @param key Key to use to verify preamble - * @param wb Work buffer - * @return VB2_SUCCESS, or non-zero error code if error. - */ -vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, - uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb); - -/** - * Retrieve the 16-bit vmlinuz header address and size from the preamble. - * - * Size 0 means there is no 16-bit vmlinuz header present. Old preamble - * versions (<2.1) return 0 for both fields. - * - * @param preamble Preamble to check - * @param vmlinuz_header_address Destination for header address - * @param vmlinuz_header_size Destination for header size - */ -void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble, - uint64_t *vmlinuz_header_address, - uint32_t *vmlinuz_header_size); - -/** - * Get the flags for the kernel preamble. - * - * @param preamble Preamble to check - * @return Flags for the preamble. Old preamble versions (<2.2) return 0. - */ -uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble); - -#endif /* VBOOT_REFERENCE_VB2_COMMON_H_ */ diff -Nru vboot-utils-0~R88-13597.B/firmware/lib20/kernel.c vboot-utils-0~R99-14469.B/firmware/lib20/kernel.c --- vboot-utils-0~R88-13597.B/firmware/lib20/kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib20/kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -12,7 +12,6 @@ #include "2secdata.h" #include "2sha.h" #include "2sysincludes.h" -#include "vb2_common.h" /** * Returns non-zero if the kernel needs to have a valid signature, instead of @@ -35,49 +34,6 @@ return 0; } -test_mockable -vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block, - uint32_t size, - const struct vb2_workbuf *wb) -{ - const struct vb2_signature *sig = &block->keyblock_hash; - struct vb2_workbuf wblocal = *wb; - struct vb2_digest_context *dc; - uint8_t *digest; - uint32_t digest_size; - - /* Validity check keyblock before attempting hash check of data */ - VB2_TRY(vb2_check_keyblock(block, size, sig)); - - VB2_DEBUG("Checking keyblock hash...\n"); - - /* Digest goes at start of work buffer */ - digest_size = vb2_digest_size(VB2_HASH_SHA512); - digest = vb2_workbuf_alloc(&wblocal, digest_size); - if (!digest) - return VB2_ERROR_VDATA_WORKBUF_DIGEST; - - /* Hashing requires temp space for the context */ - dc = vb2_workbuf_alloc(&wblocal, sizeof(*dc)); - if (!dc) - return VB2_ERROR_VDATA_WORKBUF_HASHING; - - VB2_TRY(vb2_digest_init(dc, VB2_HASH_SHA512)); - - VB2_TRY(vb2_digest_extend(dc, (const uint8_t *)block, sig->data_size)); - - VB2_TRY(vb2_digest_finalize(dc, digest, digest_size)); - - if (vb2_safe_memcmp(vb2_signature_data(sig), digest, - digest_size) != 0) { - VB2_DEBUG("Invalid keyblock hash.\n"); - return VB2_ERROR_KEYBLOCK_SIG_INVALID; - } - - /* Success */ - return VB2_SUCCESS; -} - vb2_error_t vb2_load_kernel_keyblock(struct vb2_context *ctx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); @@ -223,115 +179,6 @@ return VB2_SUCCESS; } -test_mockable -vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, - uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - struct vb2_signature *sig = &preamble->preamble_signature; - uint32_t min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_0_SIZE; - - VB2_DEBUG("Verifying kernel preamble.\n"); - - /* Make sure it's even safe to look at the struct */ - if(size < min_size) { - VB2_DEBUG("Not enough data for preamble header.\n"); - return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER; - } - if (preamble->header_version_major != - VB2_KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) { - VB2_DEBUG("Incompatible kernel preamble header version.\n"); - return VB2_ERROR_PREAMBLE_HEADER_VERSION; - } - - if (preamble->header_version_minor >= 2) - min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_2_SIZE; - else if (preamble->header_version_minor == 1) - min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_1_SIZE; - if(preamble->preamble_size < min_size) { - VB2_DEBUG("Preamble size too small for header.\n"); - return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER; - } - if (size < preamble->preamble_size) { - VB2_DEBUG("Not enough data for preamble.\n"); - return VB2_ERROR_PREAMBLE_SIZE; - } - - /* Check signature */ - if (vb2_verify_signature_inside(preamble, preamble->preamble_size, - sig)) { - VB2_DEBUG("Preamble signature off end of preamble\n"); - return VB2_ERROR_PREAMBLE_SIG_OUTSIDE; - } - - /* Make sure advertised signature data sizes are valid. */ - if (preamble->preamble_size < sig->data_size) { - VB2_DEBUG("Signature calculated past end of the block\n"); - return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH; - } - - if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) { - VB2_DEBUG("Preamble signature validation failed\n"); - return VB2_ERROR_PREAMBLE_SIG_INVALID; - } - - /* Verify we signed enough data */ - if (sig->data_size < sizeof(struct vb2_fw_preamble)) { - VB2_DEBUG("Didn't sign enough data\n"); - return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE; - } - - /* Verify body signature is inside the signed data */ - if (vb2_verify_signature_inside(preamble, sig->data_size, - &preamble->body_signature)) { - VB2_DEBUG("Body signature off end of preamble\n"); - return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE; - } - - /* - * If bootloader is present, verify it's covered by the body - * signature. - */ - if (preamble->bootloader_size) { - const void *body_ptr = - (const void *)(uintptr_t)preamble->body_load_address; - const void *bootloader_ptr = - (const void *)(uintptr_t)preamble->bootloader_address; - if (vb2_verify_member_inside(body_ptr, - preamble->body_signature.data_size, - bootloader_ptr, - preamble->bootloader_size, - 0, 0)) { - VB2_DEBUG("Bootloader off end of signed data\n"); - return VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE; - } - } - - /* - * If vmlinuz header is present, verify it's covered by the body - * signature. - */ - if (preamble->header_version_minor >= 1 && - preamble->vmlinuz_header_size) { - const void *body_ptr = - (const void *)(uintptr_t)preamble->body_load_address; - const void *vmlinuz_header_ptr = (const void *) - (uintptr_t)preamble->vmlinuz_header_address; - if (vb2_verify_member_inside(body_ptr, - preamble->body_signature.data_size, - vmlinuz_header_ptr, - preamble->vmlinuz_header_size, - 0, 0)) { - VB2_DEBUG("Vmlinuz header off end of signed data\n"); - return VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE; - } - } - - /* Success */ - return VB2_SUCCESS; -} - vb2_error_t vb2_load_kernel_preamble(struct vb2_context *ctx) { struct vb2_shared_data *sd = vb2_get_sd(ctx); @@ -421,30 +268,3 @@ return VB2_SUCCESS; } - -void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble, - uint64_t *vmlinuz_header_address, - uint32_t *vmlinuz_header_size) -{ - if (preamble->header_version_minor < 1) { - *vmlinuz_header_address = 0; - *vmlinuz_header_size = 0; - } else { - /* - * Set header and size only if the preamble header version is > - * 2.1 as they don't exist in version 2.0 (Note that we don't - * need to check header_version_major; if that's not 2 then - * vb2_verify_kernel_preamble() would have already failed. - */ - *vmlinuz_header_address = preamble->vmlinuz_header_address; - *vmlinuz_header_size = preamble->vmlinuz_header_size; - } -} - -uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble) -{ - if (preamble->header_version_minor < 2) - return 0; - - return preamble->flags; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib20/misc.c vboot-utils-0~R99-14469.B/firmware/lib20/misc.c --- vboot-utils-0~R88-13597.B/firmware/lib20/misc.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib20/misc.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,237 +0,0 @@ -/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Misc functions which need access to vb2_context but are not public APIs - */ - -#include "2api.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sha.h" -#include "2sysincludes.h" -#include "vb2_common.h" - -vb2_error_t vb2_load_fw_keyblock(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - struct vb2_workbuf wb; - - uint8_t *key_data; - uint32_t key_size; - struct vb2_public_key root_key; - - struct vb2_keyblock *kb; - uint32_t block_size; - - vb2_error_t rv = VB2_SUCCESS; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Read the root key */ - key_size = gbb->rootkey_size; - key_data = vb2_workbuf_alloc(&wb, key_size); - if (!key_data) - return VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY; - - VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB, gbb->rootkey_offset, - key_data, key_size)); - - /* Unpack the root key */ - VB2_TRY(vb2_unpack_key_buffer(&root_key, key_data, key_size)); - - root_key.allow_hwcrypto = vb2_hwcrypto_rsa_allowed(ctx); - - /* Load the firmware keyblock header after the root key */ - kb = vb2_workbuf_alloc(&wb, sizeof(*kb)); - if (!kb) - return VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER; - - VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, - kb, sizeof(*kb))); - - block_size = kb->keyblock_size; - - /* - * Load the entire keyblock, now that we know how big it is. Note that - * we're loading the entire keyblock instead of just the piece after - * the header. That means we re-read the header. But that's a tiny - * amount of data, and it makes the code much more straightforward. - */ - kb = vb2_workbuf_realloc(&wb, sizeof(*kb), block_size); - if (!kb) - return VB2_ERROR_FW_KEYBLOCK_WORKBUF; - - VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, 0, kb, block_size)); - - /* Verify the keyblock */ - VB2_TRY(vb2_verify_keyblock(kb, block_size, &root_key, &wb), - ctx, VB2_RECOVERY_FW_KEYBLOCK); - - /* Key version is the upper 16 bits of the composite firmware version */ - if (kb->data_key.key_version > VB2_MAX_KEY_VERSION) - rv = VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE; - if (!rv && kb->data_key.key_version < (sd->fw_version_secdata >> 16)) { - if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK) - VB2_DEBUG("Ignoring FW key rollback due to GBB flag\n"); - else - rv = VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK; - } - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_FW_KEY_ROLLBACK, rv); - return rv; - } - - sd->fw_version = kb->data_key.key_version << 16; - - /* Preamble follows the keyblock in the vblock. */ - sd->vblock_preamble_offset = kb->keyblock_size; - - /* - * Save the data key in the work buffer. We'll overwrite the root key - * we read above. That's ok, because now that we have the data key we - * no longer need the root key. First, let's double-check that it is - * well-formed though (although the keyblock was signed anyway). - */ - VB2_TRY(vb2_verify_packed_key_inside(kb, block_size, &kb->data_key)); - - /* Save the future offset and size while kb->data_key is still valid. - The check above made sure that key_offset and key_size are valid. */ - sd->data_key_offset = vb2_offset_of(sd, key_data); - sd->data_key_size = kb->data_key.key_offset + kb->data_key.key_size; - - /* - * Use memmove() instead of memcpy(). In theory, the destination will - * never overlap because with the source because the root key is likely - * to be at least as large as the data key, but there's no harm here in - * being paranoid. Make sure we immediately invalidate 'kb' after the - * move to guarantee we won't try to access it anymore. - */ - memmove(key_data, &kb->data_key, sd->data_key_size); - kb = NULL; - - /* - * Data key will persist in the workbuf after we return. - * - * Work buffer now contains: - * - vb2_shared_data - * - packed firmware data key - */ - vb2_set_workbuf_used(ctx, sd->data_key_offset + sd->data_key_size); - - return VB2_SUCCESS; -} - -vb2_error_t vb2_load_fw_preamble(struct vb2_context *ctx) -{ - struct vb2_shared_data *sd = vb2_get_sd(ctx); - struct vb2_gbb_header *gbb = vb2_get_gbb(ctx); - struct vb2_workbuf wb; - - uint8_t *key_data = vb2_member_of(sd, sd->data_key_offset); - uint32_t key_size = sd->data_key_size; - struct vb2_public_key data_key; - - /* Preamble goes in the next unused chunk of work buffer */ - struct vb2_fw_preamble *pre; - uint32_t pre_size; - - vb2_error_t rv = VB2_SUCCESS; - - vb2_workbuf_from_ctx(ctx, &wb); - - /* Unpack the firmware data key */ - if (!sd->data_key_size) - return VB2_ERROR_FW_PREAMBLE2_DATA_KEY; - - VB2_TRY(vb2_unpack_key_buffer(&data_key, key_data, key_size)); - - data_key.allow_hwcrypto = vb2_hwcrypto_rsa_allowed(ctx); - - /* Load the firmware preamble header */ - pre = vb2_workbuf_alloc(&wb, sizeof(*pre)); - if (!pre) - return VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER; - - VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, - sd->vblock_preamble_offset, - pre, sizeof(*pre))); - - pre_size = pre->preamble_size; - - /* Load the entire firmware preamble, now that we know how big it is */ - pre = vb2_workbuf_realloc(&wb, sizeof(*pre), pre_size); - if (!pre) - return VB2_ERROR_FW_PREAMBLE2_WORKBUF; - - VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_FW_VBLOCK, - sd->vblock_preamble_offset, - pre, pre_size)); - - /* Work buffer now contains the data subkey data and the preamble */ - - /* Verify the preamble */ - VB2_TRY(vb2_verify_fw_preamble(pre, pre_size, &data_key, &wb), - ctx, VB2_RECOVERY_FW_PREAMBLE); - - /* - * Firmware version is the lower 16 bits of the composite firmware - * version. - */ - if (pre->firmware_version > VB2_MAX_PREAMBLE_VERSION) - rv = VB2_ERROR_FW_PREAMBLE_VERSION_RANGE; - /* Combine with the key version from vb2_load_fw_keyblock() */ - sd->fw_version |= pre->firmware_version; - if (!rv && sd->fw_version < sd->fw_version_secdata) { - if (gbb->flags & VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK) - VB2_DEBUG("Ignoring FW rollback due to GBB flag\n"); - else - rv = VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK; - } - if (rv) { - vb2api_fail(ctx, VB2_RECOVERY_FW_ROLLBACK, rv); - return rv; - } - - /* - * If this is a newer version than in secure storage, and we - * successfully booted the same slot last boot, roll forward the - * version in secure storage. - * - * Note that this happens before we've verified the firmware data this - * boot; we're relying on the indicator that the last boot was - * successful. That's ok, because even if the firmware data has a - * valid hash, the only way we can know if it's functional is to trust - * the status from the last boot. - */ - if (sd->fw_version > sd->fw_version_secdata && - sd->last_fw_slot == sd->fw_slot && - sd->last_fw_result == VB2_FW_RESULT_SUCCESS) { - sd->fw_version_secdata = sd->fw_version; - vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, - sd->fw_version); - } - - /* Keep track of where we put the preamble */ - sd->preamble_offset = vb2_offset_of(sd, pre); - sd->preamble_size = pre_size; - - /* - * Preamble will persist in work buffer after we return. - * - * Work buffer now contains: - * - vb2_shared_data - * - vb2_gbb_header - * - packed firmware data key - * - firmware preamble - * - * TODO: we could move the preamble down over the firmware data key - * since we don't need it anymore. - */ - vb2_set_workbuf_used(ctx, sd->preamble_offset + pre_size); - - return VB2_SUCCESS; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/lib20/packed_key.c vboot-utils-0~R99-14469.B/firmware/lib20/packed_key.c --- vboot-utils-0~R88-13597.B/firmware/lib20/packed_key.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/lib20/packed_key.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Key unpacking functions - */ - -#include "2common.h" -#include "2rsa.h" -#include "2sysincludes.h" -#include "vb2_common.h" - -test_mockable -vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, - const uint8_t *buf, uint32_t size) -{ - const struct vb2_packed_key *packed_key = - (const struct vb2_packed_key *)buf; - const uint32_t *buf32; - uint32_t expected_key_size; - - /* Make sure passed buffer is big enough for the packed key */ - VB2_TRY(vb2_verify_packed_key_inside(buf, size, packed_key)); - - /* Unpack key algorithm */ - key->sig_alg = vb2_crypto_to_signature(packed_key->algorithm); - if (key->sig_alg == VB2_SIG_INVALID) { - VB2_DEBUG("Unsupported signature algorithm.\n"); - return VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; - } - - key->hash_alg = vb2_crypto_to_hash(packed_key->algorithm); - if (key->hash_alg == VB2_HASH_INVALID) { - VB2_DEBUG("Unsupported hash algorithm.\n"); - return VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM; - } - - expected_key_size = vb2_packed_key_size(key->sig_alg); - if (!expected_key_size || expected_key_size != packed_key->key_size) { - VB2_DEBUG("Wrong key size for algorithm\n"); - return VB2_ERROR_UNPACK_KEY_SIZE; - } - - /* Make sure source buffer is 32-bit aligned */ - buf32 = (const uint32_t *)vb2_packed_key_data(packed_key); - if (!vb2_aligned(buf32, sizeof(uint32_t))) - return VB2_ERROR_UNPACK_KEY_ALIGN; - - /* Validity check key array size */ - key->arrsize = buf32[0]; - if (key->arrsize * sizeof(uint32_t) != vb2_rsa_sig_size(key->sig_alg)) - return VB2_ERROR_UNPACK_KEY_ARRAY_SIZE; - - key->n0inv = buf32[1]; - - /* Arrays point inside the key data */ - key->n = buf32 + 2; - key->rr = buf32 + 2 + key->arrsize; - - /* disable hwcrypto for RSA by default */ - key->allow_hwcrypto = 0; - -#ifdef __COVERITY__ - __coverity_tainted_data_sanitize__(key); - __coverity_tainted_data_sanitize__(buf); -#endif - return VB2_SUCCESS; -} - -vb2_error_t vb2_unpack_key(struct vb2_public_key *key, - const struct vb2_packed_key *packed_key) -{ - if (!packed_key) - return VB2_ERROR_UNPACK_KEY_BUFFER; - - return vb2_unpack_key_buffer(key, - (const uint8_t *)packed_key, - packed_key->key_offset + - packed_key->key_size); -} diff -Nru vboot-utils-0~R88-13597.B/firmware/stub/tpm_lite_stub.c vboot-utils-0~R99-14469.B/firmware/stub/tpm_lite_stub.c --- vboot-utils-0~R88-13597.B/firmware/stub/tpm_lite_stub.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/stub/tpm_lite_stub.c 2022-02-11 14:46:09.000000000 +0000 @@ -43,15 +43,8 @@ */ static int exit_on_failure = 1; -/* Similar to VbExError, only handle the non-exit case. - */ -static int DoError(int result, const char* format, ...) +static inline uint32_t try_exit(uint32_t result) { - va_list ap; - va_start(ap, format); - fprintf(stderr, "ERROR: "); - vfprintf(stderr, format, ap); - va_end(ap); if (exit_on_failure) exit(1); return result; @@ -62,13 +55,13 @@ __attribute__((unused)) static void DbgPrintBytes(const uint8_t* a, int n) { int i; - fprintf(stderr, "DEBUG: "); + VB2_DEBUG_RAW("DEBUG: "); for (i = 0; i < n; i++) { if (i && i % 16 == 0) - fprintf(stderr, "\nDEBUG: "); - fprintf(stderr, "%02x ", a[i]); + VB2_DEBUG_RAW("\nDEBUG: "); + VB2_DEBUG_RAW("%02x ", a[i]); } - fprintf(stderr, "\n"); + VB2_DEBUG_RAW("\n"); } @@ -79,13 +72,13 @@ { uint8_t response[TPM_MAX_COMMAND_SIZE]; if (in_len <= 0) { - return DoError(TPM_E_INPUT_TOO_SMALL, - "invalid command length %d for command %#x\n", - in_len, in[9]); + VB2_DEBUG("ERROR: invalid command length %d for command %#x\n", + in_len, in[9]); + return try_exit(TPM_E_INPUT_TOO_SMALL); } else if (tpm_fd < 0) { - return DoError(TPM_E_NO_DEVICE, - "the TPM device was not opened. " \ - "Forgot to call TlclLibInit?\n"); + VB2_DEBUG("ERROR: the TPM device was not opened. " + "Forgot to call TlclLibInit?\n"); + return try_exit(TPM_E_NO_DEVICE); } else { int n; int retries = 0; @@ -105,15 +98,15 @@ retries + 1, strerror(errno)); } if (n < 0) { - return DoError(TPM_E_WRITE_FAILURE, - "write failure to TPM device: %s " - "(first error %d)\n", - strerror(errno), first_errno); + VB2_DEBUG("ERROR: write failure to TPM device: %s " + "(first error %d)\n", + strerror(errno), first_errno); + return try_exit(TPM_E_WRITE_FAILURE); } else if (n != in_len) { - return DoError(TPM_E_WRITE_FAILURE, - "bad write size to TPM device: %d vs %u " - "(%d retries, first error %d)\n", - n, in_len, retries, first_errno); + VB2_DEBUG("ERROR: bad write size to TPM device: " + "%d vs %u (%d retries, first error %d)\n", + n, in_len, retries, first_errno); + return try_exit(TPM_E_WRITE_FAILURE); } /* Read response. Retry in case of communication errors. @@ -131,18 +124,18 @@ retries + 1, strerror(errno)); } if (n == 0) { - return DoError(TPM_E_READ_EMPTY, - "null read from TPM device\n"); + VB2_DEBUG("ERROR: null read from TPM device\n"); + return try_exit(TPM_E_READ_EMPTY); } else if (n < 0) { - return DoError(TPM_E_READ_FAILURE, - "read failure from TPM device: %s " - "(first error %d)\n", - strerror(errno), first_errno); + VB2_DEBUG("ERROR: read failure from TPM device: %s " + "(first error %d)\n", + strerror(errno), first_errno); + return try_exit(TPM_E_READ_FAILURE); } else { if (n > *pout_len) { - return DoError(TPM_E_RESPONSE_TOO_LARGE, - "TPM response too long for " - "output buffer\n"); + VB2_DEBUG("ERROR: TPM response too long for " + "output buffer\n"); + return try_exit(TPM_E_RESPONSE_TOO_LARGE); } else { *pout_len = n; memcpy(out, response, n); @@ -221,9 +214,9 @@ delay.tv_nsec = OPEN_RETRY_DELAY_NS; nanosleep(&delay, NULL); } - return DoError(VB2_ERROR_UNKNOWN, - "TPM: Cannot open TPM device %s: %s\n", - device_path, strerror(saved_errno)); + VB2_DEBUG("ERROR: TPM: Cannot open TPM device %s: %s\n", + device_path, strerror(saved_errno)); + return try_exit(VB2_ERROR_UNKNOWN); } uint32_t vb2ex_tpm_send_recv(const uint8_t* request, uint32_t request_length, diff -Nru vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub.c vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub.c --- vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub.c 2022-02-11 14:46:09.000000000 +0000 @@ -18,145 +18,8 @@ #include "vboot_api.h" #include "vboot_test.h" -void vb2ex_msleep(uint32_t msec) -{ -} - -void vb2ex_beep(uint32_t msec, uint32_t frequency) -{ -} - -vb2_error_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale, - const VbScreenData *data) -{ - return VB2_SUCCESS; -} - -vb2_error_t VbExDisplayMenu(uint32_t screen_type, uint32_t locale, - uint32_t selected_index, uint32_t disabled_idx_mask, - uint32_t redraw_base) -{ - return VB2_SUCCESS; -} - -vb2_error_t VbExDisplayDebugInfo(const char *info_str, int full_info) -{ - return VB2_SUCCESS; -} - -uint32_t vb2ex_get_locale_count(void) -{ - return 0; -} - -uint32_t vb2ex_get_bootloader_count(void) -{ - return 0; -} - -uint32_t VbExGetAltFwIdxMask(void) -{ - return 0; -} - -uint32_t VbExKeyboardRead(void) -{ - return 0; -} - -uint32_t VbExKeyboardReadWithFlags(uint32_t *flags_ptr) -{ - return 0; -} - -int vb2ex_physical_presence_pressed(void) -{ - return 0; -} - -uint32_t VbExIsShutdownRequested(void) -{ - return 0; -} - -int vb2ex_ec_trusted(void) -{ - return 1; -} - -vb2_error_t vb2ex_ec_running_rw(int *in_rw) -{ - *in_rw = 0; - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_jump_to_rw(void) -{ - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_disable_jump(void) -{ - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_hash_image(enum vb2_firmware_selection select, - const uint8_t **hash, int *hash_size) -{ - static const uint8_t fake_hash[32] = {1, 2, 3, 4}; - - *hash = fake_hash; - *hash_size = sizeof(fake_hash); - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_get_expected_image_hash(enum vb2_firmware_selection select, - const uint8_t **hash, int *hash_size) -{ - static const uint8_t fake_hash[32] = {1, 2, 3, 4}; - - *hash = fake_hash; - *hash_size = sizeof(fake_hash); - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_update_image(enum vb2_firmware_selection select) -{ - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_protect(enum vb2_firmware_selection select) -{ - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_vboot_done(struct vb2_context *ctx) -{ - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_ec_battery_cutoff(void) -{ - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_auxfw_check(enum vb2_auxfw_update_severity *severity) -{ - *severity = VB2_AUXFW_NO_UPDATE; - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_auxfw_update(void) -{ - return VB2_SUCCESS; -} - -vb2_error_t VbExLegacy(enum VbAltFwIndex_t altfw_num) -{ - return VB2_SUCCESS; -} - -vb2_error_t VbExSetVendorData(const char *vendor_data_value) +__attribute__((weak)) +vb2_error_t vb2ex_run_altfw(uint32_t altfw_id) { return VB2_SUCCESS; } diff -Nru vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub_disk.c vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub_disk.c --- vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub_disk.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub_disk.c 2022-02-11 14:46:09.000000000 +0000 @@ -16,6 +16,7 @@ #include "vboot_api.h" +__attribute__((weak)) vb2_error_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count, uint32_t disk_flags) { @@ -25,6 +26,7 @@ } +__attribute__((weak)) vb2_error_t VbExDiskFreeInfo(VbDiskInfo* infos_ptr, VbExDiskHandle_t preserve_handle) { @@ -32,6 +34,7 @@ } +__attribute__((weak)) vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, uint64_t lba_count, void* buffer) { @@ -39,6 +42,7 @@ } +__attribute__((weak)) vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, uint64_t lba_count, const void* buffer) { diff -Nru vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub_init.c vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub_init.c --- vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub_init.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub_init.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Stub implementations of firmware-provided API functions. - */ - -#include -#include -#include -#include - -#include "2common.h" -#include "vboot_api.h" - -uint32_t vb2ex_mtime(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * VB2_MSEC_PER_SEC + tv.tv_usec / VB2_USEC_PER_MSEC; -} - -vb2_error_t vb2ex_commit_data(struct vb2_context *ctx) -{ - ctx->flags &= ~VB2_CONTEXT_SECDATA_FIRMWARE_CHANGED; - ctx->flags &= ~VB2_CONTEXT_SECDATA_KERNEL_CHANGED; - ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED; - return VB2_SUCCESS; -} diff -Nru vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub_stream.c vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub_stream.c --- vboot-utils-0~R88-13597.B/firmware/stub/vboot_api_stub_stream.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/firmware/stub/vboot_api_stub_stream.c 2022-02-11 14:46:09.000000000 +0000 @@ -25,6 +25,7 @@ uint64_t sectors_left; }; +__attribute__((weak)) vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start, uint64_t lba_count, VbExStream_t *stream) { @@ -45,6 +46,7 @@ return VB2_SUCCESS; } +__attribute__((weak)) vb2_error_t VbExStreamRead(VbExStream_t stream, uint32_t bytes, void *buffer) { struct disk_stream *s = (struct disk_stream *)stream; @@ -73,6 +75,7 @@ return VB2_SUCCESS; } +__attribute__((weak)) void VbExStreamClose(VbExStream_t stream) { struct disk_stream *s = (struct disk_stream *)stream; diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_create.c vboot-utils-0~R99-14469.B/futility/cmd_create.c --- vboot-utils-0~R88-13597.B/futility/cmd_create.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_create.c 2022-02-11 14:46:09.000000000 +0000 @@ -22,7 +22,6 @@ #include "host_misc21.h" #include "openssl_compat.h" #include "util_misc.h" -#include "vb2_common.h" #include "vboot_host.h" /* Command line options */ diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_dump_fmap.c vboot-utils-0~R99-14469.B/futility/cmd_dump_fmap.c --- vboot-utils-0~R88-13597.B/futility/cmd_dump_fmap.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_dump_fmap.c 2022-02-11 14:46:09.000000000 +0000 @@ -445,7 +445,7 @@ break; case 'H': opt_gaps = 1; - __attribute__ ((fallthrough)); + VBOOT_FALLTHROUGH; case 'h': opt_format = FMT_HUMAN; opt_overlap++; @@ -508,7 +508,7 @@ case FMT_NORMAL: printf("hit at 0x%08x\n", (uint32_t) ((char *)fmap - (char *)base_of_rom)); - __attribute__ ((fallthrough)); + VBOOT_FALLTHROUGH; default: retval = normal_fmap(fmap, argc - optind - 1, diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_gbb_utility.c vboot-utils-0~R99-14469.B/futility/cmd_gbb_utility.c --- vboot-utils-0~R88-13597.B/futility/cmd_gbb_utility.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_gbb_utility.c 2022-02-11 14:46:09.000000000 +0000 @@ -29,7 +29,6 @@ " --hwid \tReport hardware id (default).\n" " --flags \tReport header flags.\n" " --digest \tReport digest of hwid (>= v1.2)\n" - " --roothash \tCheck ryu root key hash\n" " -k, --rootkey=FILE \tFile name to export Root Key.\n" " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n" " -r --recoverykey=FILE\tFile name to export Recovery Key.\n" @@ -61,7 +60,6 @@ OPT_FLAGS, OPT_DIGEST, OPT_HELP, - OPT_ROOTHASH, }; /* Command line options */ @@ -78,7 +76,6 @@ {"flags", 0, NULL, OPT_FLAGS}, {"digest", 0, NULL, OPT_DIGEST}, {"help", 0, NULL, OPT_HELP}, - {"roothash", 0, NULL, OPT_ROOTHASH}, {NULL, 0, NULL, 0}, }; @@ -367,7 +364,6 @@ int sel_hwid = 0; int sel_digest = 0; int sel_flags = 0; - int sel_roothash = 0; uint8_t *inbuf = NULL; off_t filesize; uint8_t *outbuf = NULL; @@ -417,9 +413,6 @@ case OPT_DIGEST: sel_digest = 1; break; - case OPT_ROOTHASH: - sel_roothash = 1; - break; case OPT_HELP: print_help(argc, argv); return !!errorcnt; @@ -498,9 +491,6 @@ if (sel_digest) print_hwid_digest(gbb, "digest: ", "\n"); - if (sel_roothash) - verify_ryu_root_header(inbuf, filesize, gbb); - if (sel_flags) printf("flags: 0x%08x\n", gbb->flags); if (opt_rootkey) @@ -606,9 +596,6 @@ read_from_file("root_key", opt_rootkey, gbb_base + gbb->rootkey_offset, gbb->rootkey_size); - - if (fill_ryu_root_header(outbuf, filesize, gbb)) - errorcnt++; } if (opt_bmpfv) read_from_file("bmp_fv", opt_bmpfv, diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_gscvd.c vboot-utils-0~R99-14469.B/futility/cmd_gscvd.c --- vboot-utils-0~R88-13597.B/futility/cmd_gscvd.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_gscvd.c 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,1050 @@ +/* + * Copyright 2021 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 +#include +#include +#include +#include +#include +#include +#include + +#include "fmap.h" +#include "futility.h" +#include "gsc_ro.h" +#include "host_key21.h" +#include "host_keyblock.h" +#include "host_signature.h" + +/* + * for testing purposes let's use + * - tests/devkeys/arv_root.vbprivk as the root private key + * - tests/devkeys/arv_root.vbpubk as the root public key + * used for signing of the platform public key + * - tests/devkeys/arv_platform.vbprivk signing platform key + * - tests/devkeys/arv_platform.vbpubk - public key used for signature + * verification + *------------ + * Command to create the signed public key block in ~/tmp/packed: + * + ./build/futility/futility vbutil_keyblock --pack ~/tmp/packed \ + --datapubkey tests/devkeys/arv_platform.vbpubk \ + --signprivate tests/devkeys/arv_root.vbprivk + *------------ + * Command to fill RO_GSCVD FMAP area in an AP firmware file. The input AP + * firmware file is ~/tmp/image-guybrush.serial.bin, the output signed + * AP firmware file is ~/tmp/guybrush-signed: + * + ./build/futility/futility gscvd --outfile ~/tmp/guybrush-signed \ + -R 818100:10000,f00000:100,f80000:2000,f8c000:1000,0x00804000:0x00000800 \ + -k ~/tmp/packed -p tests/devkeys/arv_platform.vbprivk -b 5a5a4352 \ + -r tests/devkeys/arv_root.vbpubk ~/tmp/image-guybrush.serial.bin + *------------ + * Command to validate a previously signed AP firmware file. The hash is the + * sha256sum of tests/devkeys/kernel_subkey.vbpubk: + * + build/futility/futility gscvd ~/tmp/guybrush-signed \ + 3d74429f35be8d34bcb425d4397e2218e6961afed456a78ce30047f5b54ed158 + */ + +/* Command line options processing support. */ +enum no_short_opts { + OPT_OUTFILE = 1000, +}; + +static const struct option long_opts[] = { + /* name hasarg *flag val */ + {"outfile", 1, NULL, OPT_OUTFILE}, + {"ranges", 1, NULL, 'R'}, + {"board_id", 1, NULL, 'b'}, + {"root_pub_key", 1, NULL, 'r'}, + {"keyblock", 1, NULL, 'k'}, + {"platform_priv", 1, NULL, 'p'}, + {"help", 0, NULL, 'h'}, + {} +}; + +static const char *short_opts = "R:b:hk:p:r:"; + +static const char usage[] = + "\n" + "This utility creates an RO verification space in the Chrome OS AP\n" + "firmware image or allows to validate a previously prepared image\n" + "containing the RO verification space.\n\n" + "Usage: " MYNAME " gscvd PARAMS []\n" + "\n\nCreation of RO Verification space:\n\n" + "Required PARAMS:\n" + " -R|--ranges STRING Comma separated colon delimited\n" + " hex tuples :, the\n" + " areas of the RO covered by the\n" + " signature\n" + " -b|--board_id The Board ID of the board for which\n" + " the image is being signed\n" + " -r|--root_pub_key The main public key, in .vbpubk\n" + " format, used to verify platform\n" + " key\n" + " -k|--keyblock Signed platform public key in\n" + " .keyblock format, used for run\n" + " time RO verifcation\n" + " -p|--platform_priv Private platform key in .vbprivk\n" + " format, used for signing RO\n" + " verification data\n" + "Optional PARAMS:\n" + " [--outfile] OUTFILE Output firmware image containing\n" + " RO verification information\n" + "\n\n" + "Validation of RO Verification space:\n\n" + " The only required parameter is , if optional\n" + " is given, it is compared to the hash\n" + " of the root key found in .\n" + "\n\n" + " -h|--help Print this message\n\n"; + +/* Structure helping to keep track of the file mapped into memory. */ +struct file_buf { + uint32_t len; + uint8_t *data; + int fd; + FmapAreaHeader *ro_gscvd; +}; + +/* + * Max number of RO ranges to cover. 32 is more than enough, this must be kept + * in sync with APRO_MAX_NUM_RANGES declaration in + * common/ap_ro_integrity_check.c in the Cr50 tree. + */ +#define MAX_RANGES 32 + +/* + * Container keeping track of the set of ranges to include in hash + * calculation. + */ +struct gscvd_ro_ranges { + size_t range_count; + struct gscvd_ro_range ranges[MAX_RANGES]; +}; + +/** + * Load the AP firmware file into memory. + * + * Map the requested file into memory, find RO_GSCVD area in the file, and + * cache the information in the passed in file_buf structure. + * + * @param file_name name of the AP firmware file + * @param file_buf pointer to the helper structure keeping information about + * the file + * + * @return 0 on success 1 on failure. + */ +static int load_ap_firmware(const char *file_name, struct file_buf *file) +{ + int fd; + int rv; + + fd = open(file_name, O_RDWR); + if (fd < 0) { + ERROR("Can't open %s: %s\n", file_name, + strerror(errno)); + return 1; + } + + file->fd = fd; + do { + rv = 1; + + if (futil_map_file(fd, MAP_RW, &file->data, &file->len)) { + file->data = NULL; + break; + } + + if (!fmap_find_by_name(file->data, file->len, NULL, "RO_GSCVD", + &file->ro_gscvd)) { + ERROR("Could not find RO_GSCVD in the FMAP\n"); + break; + } + rv = 0; + } while (false); + + return rv; +} + +/** + * Check if the passed in offset falls into the passed in FMAP area. + */ +static bool in_range(uint32_t offset, const FmapAreaHeader *ah) +{ + return (offset >= ah->area_offset) && + (offset <= (ah->area_offset + ah->area_size)); +} + +/** + * Check if the passed in range fits into the passed in FMAP area. + */ +static bool range_fits(const struct gscvd_ro_range *range, + const FmapAreaHeader *ah) +{ + if (in_range(range->offset, ah) && + in_range(range->offset + range->size, ah)) + return true; + + ERROR("Range %#x..+%#x does not fit in %s\n", range->offset, + range->size, ah->area_name); + + return false; +} + +/** + * Check if the passed in range overlaps with the area. + * + * @param range pointer to the range to check + * @param offset offset of the area to check against + * @param size size of the area to check against + * + * @return true if range overlaps with the area, false otherwise. + */ +static bool range_overlaps(const struct gscvd_ro_range *range, uint32_t offset, + size_t size) +{ + if (((range->offset + range->size) <= offset) || + (offset + size) <= range->offset) + return false; + + ERROR("Range %x..+%x overlaps with %x..+%zx\n", range->offset, + range->size, offset, size); + + return true; +} + +/* + * Check validity of the passed in ranges. + * + * All ranges must + * - fit into the WP_RO FMAP area + * - not overlap with the RO_GSCVD FMAP area + * - not overlap with each other + * + * @param ranges - pointer to the container of ranges to check + * @param file - pointer to the file layout descriptor + * + * @return zero on success, -1 on failures + */ +static int verify_ranges(const struct gscvd_ro_ranges *ranges, + const struct file_buf *file) +{ + size_t i; + FmapAreaHeader *wp_ro; + int errorcount; + + if (!fmap_find_by_name(file->data, file->len, NULL, "WP_RO", &wp_ro)) { + ERROR("Could not find WP_RO in the FMAP\n"); + return 1; + } + + errorcount = 0; + for (i = 0; i < ranges->range_count; i++) { + size_t j; + + /* Must fit into WP_RO. */ + if (!range_fits(ranges->ranges + i, wp_ro)) + errorcount++; + + /* Must not overlap with RO_GSCVD. */ + if (range_overlaps(ranges->ranges + i, + file->ro_gscvd->area_offset, + file->ro_gscvd->area_size)) + errorcount++; + + /* The last range is nothing to compare against. */ + if (i == ranges->range_count - 1) + break; + + /* Must not overlap with all following ranges. */ + for (j = i + 1; j < ranges->range_count; j++) + if (range_overlaps(ranges->ranges + i, + ranges->ranges[j].offset, + ranges->ranges[j].size)) + errorcount++; + } + + return errorcount ? -1 : 0; +} + +/** + * Parse range specification supplied by the user. + * + * The input is a string of the following format: + * :[,:[,...]] + * + * @param input user input, part of the command line + * @param output pointer to the ranges container + * + * @return zero on success, -1 on failure + */ +static int parse_ranges(const char *input, struct gscvd_ro_ranges *output) +{ + char *cursor; + char *delim; + char *str = strdup(input); + int rv = 0; + + if (!str) { + ERROR("Failed to allocate memory for ranges string copy!\n"); + return -1; + } + + output->range_count = 0; + cursor = str; + do { + char *colon; + char *e; + + if (output->range_count >= ARRAY_SIZE(output->ranges)) { + ERROR("Too many ranges!\n"); + rv = -1; + break; + } + + delim = strchr(cursor, ','); + if (delim) + *delim = '\0'; + colon = strchr(cursor, ':'); + if (!colon) { + rv = -1; + break; + } + *colon = '\0'; + + errno = 0; + output->ranges[output->range_count].offset = + strtol(cursor, &e, 16); + if (errno || *e) { + rv = -1; + break; + } + + output->ranges[output->range_count].size = + strtol(colon + 1, &e, 16); + if (errno || *e) { + rv = -1; + break; + } + + output->range_count++; + cursor = delim + 1; + /* Iterate until there is no more commas. */ + } while (delim); + + free(str); + if (rv) + ERROR("Misformatted ranges string\n"); + + return rv; +} + +/** + * Calculate hash of the RO ranges. + * + * @param ap_firmware_file pointer to the AP firmware file layout descriptor + * @param ranges pointer to the container of ranges to include in hash + * calculation + * @param hash_alg algorithm to use for hashing + * @param digest memory to copy the calculated hash to + * @param digest_ size requested size of the digest, padded with zeros if the + * SHA digest size is smaller than digest_size + * + * @return zero on success, -1 on failure. + */ +static int calculate_ranges_digest(const struct file_buf *ap_firmware_file, + const struct gscvd_ro_ranges *ranges, + enum vb2_hash_algorithm hash_alg, + void *digest, size_t digest_size) +{ + struct vb2_digest_context dc; + size_t i; + + /* Calculate the ranges digest. */ + if (vb2_digest_init(&dc, hash_alg) != VB2_SUCCESS) { + ERROR("Failed to init digest!\n"); + return 1; + } + + for (i = 0; i < ranges->range_count; i++) { + if (vb2_digest_extend(&dc, + ap_firmware_file->data + + ranges->ranges[i].offset, + ranges->ranges[i].size) != VB2_SUCCESS) { + ERROR("Failed to extend digest!\n"); + return -1; + } + } + + memset(digest, 0, digest_size); + if (vb2_digest_finalize(&dc, digest, digest_size) != VB2_SUCCESS) { + ERROR("Failed to finalize digest!\n"); + return -1; + } + + return 0; +} + +/** + * Build GSC verification data. + * + * Calculate size of the structure including the signature and the root key, + * allocate memory, fill up the structure, calculate AP RO ranges digest and + * then the GVD signature. + * + * @param ap_firmware_file pointer to the AP firmware file layout descriptor + * @param ranges pointer to the container of ranges to include in verification + * @param root_pubk pointer to the root pubk container + * @param privk pointer to the private key to use for signing + * @param board_id Board ID value to use. + * + * @return pointer to the created GVD (to be freed by the caller) on success, + * NULL on failure. + */ +static +struct gsc_verification_data *create_gvd(struct file_buf *ap_firmware_file, + struct gscvd_ro_ranges *ranges, + const struct vb2_packed_key *root_pubk, + const struct vb2_private_key *privk, + uint32_t board_id) +{ + struct gsc_verification_data *gvd; + size_t total_size; + size_t sig_size; + size_t ranges_size; + struct vb2_signature *sig; + const FmapHeader *fmh; + + sig_size = vb2_rsa_sig_size(privk->sig_alg); + ranges_size = ranges->range_count * sizeof(struct gscvd_ro_range); + total_size = sizeof(struct gsc_verification_data) + + root_pubk->key_size + sig_size + ranges_size; + + gvd = calloc(total_size, 1); + + if (!gvd) { + ERROR("Failed to allocate %zd bytes for gvd\n", total_size); + return NULL; + } + + gvd->gv_magic = GSC_VD_MAGIC; + gvd->size = total_size; + gvd->gsc_board_id = board_id; + gvd->rollback_counter = GSC_VD_ROLLBACK_COUNTER; + + /* Guaranteed to succeed. */ + fmh = fmap_find(ap_firmware_file->data, ap_firmware_file->len); + + gvd->fmap_location = (uintptr_t)fmh - (uintptr_t)ap_firmware_file->data; + + gvd->hash_alg = VB2_HASH_SHA256; + + if (calculate_ranges_digest(ap_firmware_file, ranges, gvd->hash_alg, + gvd->ranges_digest, + sizeof(gvd->ranges_digest))) { + free(gvd); + return NULL; + } + + /* Prepare signature header. */ + vb2_init_signature(&gvd->sig_header, + (uint8_t *)(gvd + 1) + ranges_size, + sig_size, + sizeof(struct gsc_verification_data) + ranges_size); + + /* Copy root key into the structure. */ + vb2_init_packed_key(&gvd->root_key_header, + (uint8_t *)(gvd + 1) + ranges_size + sig_size, + root_pubk->key_size); + vb2_copy_packed_key(&gvd->root_key_header, root_pubk); + + /* Copy ranges into the ranges section. */ + gvd->range_count = ranges->range_count; + memcpy(gvd->ranges, ranges->ranges, ranges_size); + + sig = vb2_calculate_signature((uint8_t *)gvd, + sizeof(struct gsc_verification_data) + + ranges_size, privk); + if (!sig) { + ERROR("Failed to calculate signature\n"); + free(gvd); + return NULL; + } + + /* Copy signature body into GVD after some basic checks. */ + if ((sig_size == sig->sig_size) && + (gvd->sig_header.data_size == sig->data_size)) { + vb2_copy_signature(&gvd->sig_header, sig); + } else { + ERROR("Inconsistent signature headers\n"); + free(sig); + free(gvd); + return NULL; + } + + free(sig); + + return gvd; +} + +/** + * Fill RO_GSCVD FMAP area. + * + * All trust chain components have been verified, AP RO sections digest + * calculated, and GVD signature created; put it all together in the dedicated + * FMAP area. + * + * @param ap_firmware_file pointer to the AP firmware file layout descriptor + * @param gvd pointer to the GVD header + * @param keyblock pointer to the keyblock container + * + * @return zero on success, -1 on failure + */ +static int fill_gvd_area(struct file_buf *ap_firmware_file, + struct gsc_verification_data *gvd, + struct vb2_keyblock *keyblock) +{ + size_t total; + uint8_t *cursor; + + /* How much room is needed for the whole thing? */ + total = gvd->size + keyblock->keyblock_size; + + if (total > ap_firmware_file->ro_gscvd->area_size) { + ERROR("GVD section does not fit, %zd > %d\n", + total, ap_firmware_file->ro_gscvd->area_size); + return -1; + } + + cursor = ap_firmware_file->data + + ap_firmware_file->ro_gscvd->area_offset; + + /* Copy GSC verification data */ + memcpy(cursor, gvd, gvd->size); + cursor += gvd->size; + + /* Keyblock, size includes everything. */ + memcpy(cursor, keyblock, keyblock->keyblock_size); + + return 0; +} + +/** + * Initialize a work buffer structure. + * + * Embedded vboot reference code does not use malloc/free, it uses the so + * called work buffer structure to provide a poor man's memory management + * tool. This program uses some of the embedded library functions, let's + * implement work buffer support to keep the embedded code happy. + * + * @param wb pointer to the workubffer structure to initialize + * @param size size of the buffer to allocate + * + * @return pointer to the allocated buffer on success, NULL on failure. + */ +static void *init_wb(struct vb2_workbuf *wb, size_t size) +{ + void *buf = malloc(size); + + if (!buf) + ERROR("Failed to allocate workblock of %zd\n", size); + else + vb2_workbuf_init(wb, buf, size); + + return buf; +} + +/** + * Validate that platform key keyblock was signed by the root key. + * + * This function performs the same step the GSC is supposed to perform: + * validate the platform key keyblock signature using the root public key. + * + * @param root_pubk pointer to the root public key container + * @param kblock pointer to the platform public key keyblock + * + * @return 0 on success, -1 on failure + */ +static int validate_pubk_signature(const struct vb2_packed_key *root_pubk, + struct vb2_keyblock *kblock) +{ + struct vb2_public_key pubk; + struct vb2_workbuf wb; + uint32_t kbsize; + int rv; + void *buf; + + if (vb2_unpack_key(&pubk, root_pubk) != VB2_SUCCESS) { + ERROR("Failed to unpack public key\n"); + return -1; + } + + /* Let's create an ample sized work buffer. */ + buf = init_wb(&wb, 8192); + if (!buf) + return -1; + + rv = -1; + do { + void *work; + + kbsize = kblock->keyblock_size; + work = vb2_workbuf_alloc(&wb, kbsize); + if (!work) { + ERROR("Failed to allocate workblock space %d\n", + kbsize); + break; + } + + memcpy(work, kblock, kbsize); + + if (vb2_verify_keyblock(work, kbsize, &pubk, &wb) != + VB2_SUCCESS) { + ERROR("Root and keyblock mismatch\n"); + break; + } + + rv = 0; + } while (false); + + free(buf); + + return rv; +} + +/** + * Validate that private and public parts of the platform key match. + * + * This is a fairly routine validation, the N components of the private and + * public RSA keys are compared. + * + * @param keyblock pointer to the keyblock containing the public key + * @param plat_privk pointer to the matching private key + * + * @return 0 on success, nonzero on failure + */ +static int validate_privk(struct vb2_keyblock *kblock, + struct vb2_private_key *plat_privk) +{ + const BIGNUM *privn; + BIGNUM *pubn; + struct vb2_public_key pubk; + int rv; + + privn = pubn = NULL; + + RSA_get0_key(plat_privk->rsa_private_key, &privn, NULL, NULL); + + if (vb2_unpack_key(&pubk, &kblock->data_key) != VB2_SUCCESS) { + ERROR("Failed to unpack public key\n"); + return -1; + } + + pubn = BN_new(); + pubn = BN_lebin2bn((uint8_t *)pubk.n, vb2_rsa_sig_size(pubk.sig_alg), + pubn); + rv = BN_cmp(pubn, privn); + if (rv) + ERROR("Public/private key N mismatch!\n"); + + BN_free(pubn); + return rv; +} + +/** + * Copy ranges from AP firmware file into gscvd_ro_ranges container + * + * While copying the ranges verify that they do not overlap. + * + * @param ap_firmware_file pointer to the AP firmware file layout descriptor + * @param gvd pointer to the GVD header followed by the ranges + * @param ranges pointer to the ranges container to copy ranges to + * + * @return 0 on successful copy nonzero on errors. + */ +static int copy_ranges(const struct file_buf *ap_firmware_file, + const struct gsc_verification_data *gvd, + struct gscvd_ro_ranges *ranges) +{ + ranges->range_count = gvd->range_count; + memcpy(ranges->ranges, gvd->ranges, + sizeof(ranges->ranges[0]) * ranges->range_count); + + return verify_ranges(ranges, ap_firmware_file); +} + +/** + * Basic validation of GVD included in a AP firmware file. + * + * This is not a cryptographic verification, just a check that the structure + * makes sense and the expected values are found in certain fields. + * + * @param gvd pointer to the GVD header followed by the ranges + * @param ap_firmware_file pointer to the AP firmware file layout descriptor + * + * @return zero on success, -1 on failure. + */ +static int validate_gvd(const struct gsc_verification_data *gvd, + const struct file_buf *ap_firmware_file) +{ + const FmapHeader *fmh; + + if (gvd->gv_magic != GSC_VD_MAGIC) { + ERROR("Incorrect gscvd magic %x\n", gvd->gv_magic); + return -1; + } + + if (!gvd->range_count || (gvd->range_count > MAX_RANGES)) { + ERROR("Incorrect gscvd range count %d\n", gvd->range_count); + return -1; + } + + /* Guaranteed to succeed. */ + fmh = fmap_find(ap_firmware_file->data, ap_firmware_file->len); + + if (gvd->fmap_location != + ((uintptr_t)fmh - (uintptr_t)ap_firmware_file->data)) { + ERROR("Incorrect gscvd fmap offset %x\n", gvd->fmap_location); + return -1; + } + + /* Make sure signature and root key fit. */ + if (vb2_verify_signature_inside(gvd, gvd->size, &gvd->sig_header) != + VB2_SUCCESS) { + ERROR("Corrupted signature header in GVD\n"); + return -1; + } + + if (vb2_verify_packed_key_inside(gvd, gvd->size, + &gvd->root_key_header) != + VB2_SUCCESS) { + ERROR("Corrupted root key header in GVD\n"); + return -1; + } + + return 0; +} + +/** + * Validate GVD signature. + * + * Given the entire GVD space (header plus ranges array), the signature and + * the public key, verify that the signature matches. + * + * @param gvd pointer to gsc_verification_data followed by the ranges array + * @param gvd_signature pointer to the vb2 signature container + * @param packedk pointer to the keyblock containing the public key + * + * @return zero on success, non-zero on failure + */ +static int validate_gvd_signature(struct gsc_verification_data *gvd, + const struct vb2_packed_key *packedk) +{ + struct vb2_workbuf wb; + void *buf; + int rv; + struct vb2_public_key pubk; + size_t signed_size; + + /* Extract public key from the public key keyblock. */ + if (vb2_unpack_key(&pubk, packedk) != VB2_SUCCESS) { + ERROR("Failed to unpack public key\n"); + return -1; + } + + /* Let's create an ample sized work buffer. */ + buf = init_wb(&wb, 8192); + if (!buf) + return -1; + + signed_size = sizeof(struct gsc_verification_data) + + gvd->range_count * sizeof(gvd->ranges[0]); + + rv = vb2_verify_data((const uint8_t *)gvd, signed_size, + &gvd->sig_header, + &pubk, &wb); + + free(buf); + return rv; +} + +/* + * Validate GVD of the passed in AP firmware file and possibly the root key hash + * + * The input parameters are the subset of the command line, the first argv + * string is the AP firmware file name, the second string, if present, is the + * hash of the root public key included in the RO_GSCVD area of the AP + * firmware file. + * + * @return zero on success, -1 on failure. + */ +static int validate_gscvd(int argc, char *argv[]) +{ + struct file_buf ap_firmware_file; + int rv; + struct gscvd_ro_ranges ranges; + struct gsc_verification_data *gvd; + const char *file_name; + uint8_t digest[sizeof(gvd->ranges_digest)]; + struct vb2_hash root_key_digest = { .algo = VB2_HASH_SHA256 }; + + /* Guaranteed to be available. */ + file_name = argv[0]; + + if (argc > 1) + parse_digest_or_die(root_key_digest.sha256, + sizeof(root_key_digest.sha256), + argv[1]); + + do { + struct vb2_keyblock *kblock; + + rv = -1; /* Speculative, will be cleared on success. */ + + if (load_ap_firmware(file_name, &ap_firmware_file)) + break; + + /* Copy ranges from gscvd to local structure. */ + gvd = (struct gsc_verification_data + *)(ap_firmware_file.data + + ap_firmware_file.ro_gscvd->area_offset); + + if (validate_gvd(gvd, &ap_firmware_file)) + break; + + if (copy_ranges(&ap_firmware_file, gvd, &ranges)) + break; + + if (calculate_ranges_digest(&ap_firmware_file, &ranges, + gvd->hash_alg, digest, + sizeof(digest))) + break; + + if (memcmp(digest, gvd->ranges_digest, sizeof(digest))) { + ERROR("Ranges digest mismatch\n"); + break; + } + + /* Find the keyblock. */ + kblock = (struct vb2_keyblock *)((uintptr_t)gvd + gvd->size); + + if ((argc > 1) && (vb2_hash_verify + (vb2_packed_key_data(&gvd->root_key_header), + gvd->root_key_header.key_size, + &root_key_digest) != VB2_SUCCESS)) { + ERROR("Sha256 mismatch\n"); + break; + } + + if (validate_pubk_signature(&gvd->root_key_header, + kblock)) + break; + + if (validate_gvd_signature(gvd, &kblock->data_key)) + break; + + rv = 0; + } while (false); + + return rv; +} + +/** + * Calculate and report sha256 hash of the public key body. + * + * The hash will be incorporated into GVC firmware to allow it to validate the + * root key. + * + * @param pubk pointer to the public key to process. + */ +static void dump_pubk_hash(const struct vb2_packed_key *pubk) +{ + struct vb2_hash hash; + size_t i; + + vb2_hash_calculate(vb2_packed_key_data(pubk), pubk->key_size, + VB2_HASH_SHA256, &hash); + + printf("Root key body sha256 hash:\n"); + + for (i = 0; i < sizeof(hash.sha256); i++) + printf("%02x", hash.sha256[i]); + + printf("\n"); +} + +/** + * The main function of this futilty option. + * + * See the usage string for input details. + * + * @return zero on success, nonzero on failure. + */ +static int do_gscvd(int argc, char *argv[]) +{ + int i; + int longindex; + char *infile = NULL; + char *outfile = NULL; + char *work_file = NULL; + struct gscvd_ro_ranges ranges; + int errorcount = 0; + struct vb2_packed_key *root_pubk = NULL; + struct vb2_keyblock *kblock = NULL; + struct vb2_private_key *plat_privk = NULL; + struct gsc_verification_data *gvd = NULL; + struct file_buf ap_firmware_file = { .fd = -1 }; + uint32_t board_id = UINT32_MAX; + int rv = 0; + + ranges.range_count = 0; + + while ((i = getopt_long(argc, argv, short_opts, long_opts, + &longindex)) != -1) { + switch (i) { + case OPT_OUTFILE: + outfile = optarg; + break; + case 'R': + if (parse_ranges(optarg, &ranges)) { + ERROR("Could not parse ranges\n"); + /* Error message has been already printed. */ + errorcount++; + } + break; + case 'b': { + char *e; + long long bid; + + bid = strtoull(optarg, &e, 16); + if (*e || (bid >= UINT32_MAX)) { + ERROR("Board ID value '%s' is invalid\n", + optarg); + errorcount++; + } else { + board_id = (uint32_t)bid; + } + break; + } + case 'r': + root_pubk = vb2_read_packed_key(optarg); + if (!root_pubk) { + ERROR("Could not read %s\n", optarg); + errorcount++; + } + break; + case 'k': + kblock = vb2_read_keyblock(optarg); + if (!kblock) { + ERROR("Could not read %s\n", optarg); + errorcount++; + } + break; + case 'p': + plat_privk = vb2_read_private_key(optarg); + if (!plat_privk) { + ERROR("Could not read %s\n", optarg); + errorcount++; + } + break; + case 'h': + printf("%s", usage); + return 0; + case '?': + if (optopt) + ERROR("Unrecognized option: -%c\n", optopt); + else + ERROR("Unrecognized option: %s\n", + argv[optind - 1]); + errorcount++; + break; + case ':': + ERROR("Missing argument to -%c\n", optopt); + errorcount++; + break; + case 0: /* handled option */ + break; + default: + FATAL("Unrecognized getopt output: %d\n", i); + } + } + + if ((optind == 1) && (argc > 1)) + /* This must be a validation request. */ + return validate_gscvd(argc - 1, argv + 1); + + if (optind != (argc - 1)) { + ERROR("Misformatted command line\n%s\n", usage); + return 1; + } + + if (errorcount || !ranges.range_count || !root_pubk || !kblock || + !plat_privk || (board_id == UINT32_MAX)) { + /* Error message(s) should have been printed by now. */ + ERROR("%s\n", usage); + return 1; + } + + infile = argv[optind]; + + if (outfile) { + futil_copy_file_or_die(infile, outfile); + work_file = outfile; + } else { + work_file = infile; + } + + do { + rv = 1; /* Speculative, will be cleared on success. */ + + if (validate_pubk_signature(root_pubk, kblock)) + break; + + if (validate_privk(kblock, plat_privk)) + break; + + if (load_ap_firmware(work_file, &ap_firmware_file)) + break; + + if (verify_ranges(&ranges, &ap_firmware_file)) + break; + + gvd = create_gvd(&ap_firmware_file, &ranges, + root_pubk, plat_privk, board_id); + if (!gvd) + break; + + if (fill_gvd_area(&ap_firmware_file, gvd, kblock)) + break; + + dump_pubk_hash(root_pubk); + + rv = 0; + } while (false); + + free(gvd); + free(root_pubk); + free(kblock); + vb2_private_key_free(plat_privk); + + /* Now flush the file. */ + if (ap_firmware_file.data) { + rv |= futil_unmap_file(ap_firmware_file.fd, true, + ap_firmware_file.data, + ap_firmware_file.len); + } + + if (ap_firmware_file.fd != -1) + close(ap_firmware_file.fd); + + return rv; +} + +DECLARE_FUTIL_COMMAND(gscvd, do_gscvd, VBOOT_VERSION_2_1, + "Create RO verification structure"); diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_pcr.c vboot-utils-0~R99-14469.B/futility/cmd_pcr.c --- vboot-utils-0~R88-13597.B/futility/cmd_pcr.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_pcr.c 2022-02-11 14:46:09.000000000 +0000 @@ -40,57 +40,6 @@ printf(usage, argv[0], argv[0], argv[0]); } -static int parse_hex(uint8_t *val, const char *str) -{ - uint8_t v = 0; - char c; - int digit; - - for (digit = 0; digit < 2; digit++) { - c = *str; - if (!c) - return 0; - if (!isxdigit(c)) - return 0; - c = tolower(c); - if (c >= '0' && c <= '9') - v += c - '0'; - else - v += 10 + c - 'a'; - if (!digit) - v <<= 4; - str++; - } - - *val = v; - return 1; -} - -static void parse_digest_or_die(uint8_t *buf, int len, const char *str) -{ - const char *s = str; - int i; - - for (i = 0; i < len; i++) { - /* skip whitespace */ - while (*s && isspace(*s)) - s++; - if (!*s) - break; - if (!parse_hex(buf, s)) - break; - - /* on to the next byte */ - s += 2; - buf++; - } - - if (i != len) { - fprintf(stderr, "Invalid DIGEST \"%s\"\n", str); - exit(1); - } -} - static void print_digest(const uint8_t *buf, int len) { int i; diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_show.c vboot-utils-0~R99-14469.B/futility/cmd_show.c --- vboot-utils-0~R88-13597.B/futility/cmd_show.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_show.c 2022-02-11 14:46:09.000000000 +0000 @@ -31,7 +31,6 @@ #include "host_key21.h" #include "util_misc.h" #include "vb1_helper.h" -#include "vb2_common.h" /* Options */ struct show_option_s show_option = { @@ -73,6 +72,10 @@ printf(" !REC"); if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1) printf(" REC"); + if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0) + printf(" !MINIOS"); + if (keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1) + printf(" MINIOS"); printf("\n"); struct vb2_packed_key *data_key = &keyblock->data_key; diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_sign.c vboot-utils-0~R99-14469.B/futility/cmd_sign.c --- vboot-utils-0~R88-13597.B/futility/cmd_sign.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_sign.c 2022-02-11 14:46:09.000000000 +0000 @@ -20,7 +20,6 @@ #include "2common.h" #include "file_type.h" #include "file_type_bios.h" -#include "fmap.h" #include "futility.h" #include "futility_options.h" #include "host_common.h" @@ -29,7 +28,6 @@ #include "kernel_blob.h" #include "util_misc.h" #include "vb1_helper.h" -#include "vb2_common.h" /* Options */ struct sign_option_s sign_option = { @@ -722,7 +720,7 @@ break; case OPT_FV: sign_option.fv_specified = 1; - __attribute__ ((fallthrough)); + VBOOT_FALLTHROUGH; case OPT_INFILE: sign_option.inout_file_count++; infile = optarg; diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_update.c vboot-utils-0~R99-14469.B/futility/cmd_update.c --- vboot-utils-0~R88-13597.B/futility/cmd_update.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_update.c 2022-02-11 14:46:09.000000000 +0000 @@ -13,6 +13,8 @@ #include "futility.h" #include "updater.h" +#ifdef USE_FLASHROM + enum { OPT_DUMMY = 0x100, @@ -31,6 +33,7 @@ OPT_QUIRKS_LIST, OPT_REPACK, OPT_SERVO, + OPT_SERVO_NORESET, OPT_SERVO_PORT, OPT_SIGNATURE, OPT_SYS_PROPS, @@ -54,6 +57,7 @@ {"ccd", 0, NULL, OPT_CCD}, {"servo", 0, NULL, OPT_SERVO}, + {"servo_noreset", 0, NULL, OPT_SERVO_NORESET}, {"servo_port", 1, NULL, OPT_SERVO_PORT}, {"emulate", 1, NULL, OPT_EMULATE}, {"factory", 0, NULL, OPT_FACTORY}, @@ -130,6 +134,7 @@ " --gbb_flags=FLAG\tOverride new GBB flags\n" " --ccd \tDo fast,force,wp=0,p=raiden_debug_spi\n" " --servo \tFlash using Servo (v2, v4, micro, ...)\n" + " --servo_noreset \tLike servo but with 'custom_rst=true'\n" " --servo_port=PRT\tOverride servod port, implies --servo\n" " --signature_id=S\tOverride signature ID for key files\n" " --sys_props=LIST\tList of system properties to override\n" @@ -139,12 +144,29 @@ argv[0]); } +static char *add_servo_noreset(char *programmer) +{ + char *ret; + + if (strstr(programmer, "raiden_debug_spi:target=AP") == NULL) { + ERROR("servo_noreset only works for AP flashing over CCD.\n"); + free(programmer); + + return NULL; + } + + ASPRINTF(&ret, "%s,custom_rst=true", programmer); + free(programmer); + + return ret; +} + static int do_update(int argc, char *argv[]) { struct updater_config *cfg; struct updater_config_arguments args = {0}; int i, errorcnt = 0, do_update = 1; - int detect_servo = 0, do_servo_cpu_fw_spi = 0; + int detect_servo = 0, do_servo_cpu_fw_spi = 0, servo_noreset = 0; char *servo_programmer = NULL; char *endptr; @@ -255,6 +277,14 @@ args.host_only = 1; detect_servo = 1; break; + case OPT_SERVO_NORESET: + args.fast_update = 1; + args.force_update = 1; + args.write_protection = "0"; + args.host_only = 1; + detect_servo = 1; + servo_noreset = 1; + break; case OPT_SERVO_PORT: setenv(ENV_SERVOD_PORT, optarg, 1); args.fast_update = 1; @@ -289,6 +319,10 @@ if (!errorcnt && detect_servo) { servo_programmer = host_detect_servo(&do_servo_cpu_fw_spi); + + if (servo_programmer && servo_noreset) + servo_programmer = add_servo_noreset(servo_programmer); + if (!servo_programmer) errorcnt++; else if (!args.programmer) @@ -326,6 +360,17 @@ updater_delete_config(cfg); return !!errorcnt; } +#define CMD_HELP_STR "Update system firmware" + +#else /* USE_FLASHROM */ + +static int do_update(int argc, char *argv[]) +{ + FATAL(MYNAME " was built without flashrom support, `update` command unavailable!\n"); + return -1; +} +#define CMD_HELP_STR "Update system firmware (unavailable in this build)" + +#endif /* !USE_FLASHROM */ -DECLARE_FUTIL_COMMAND(update, do_update, VBOOT_VERSION_ALL, - "Update system firmware"); +DECLARE_FUTIL_COMMAND(update, do_update, VBOOT_VERSION_ALL, CMD_HELP_STR); diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_vbutil_firmware.c vboot-utils-0~R99-14469.B/futility/cmd_vbutil_firmware.c --- vboot-utils-0~R88-13597.B/futility/cmd_vbutil_firmware.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_vbutil_firmware.c 2022-02-11 14:46:09.000000000 +0000 @@ -22,7 +22,6 @@ #include "kernel_blob.h" #include "util_misc.h" #include "vb1_helper.h" -#include "vb2_common.h" /* Command line options */ enum { diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_vbutil_kernel.c vboot-utils-0~R99-14469.B/futility/cmd_vbutil_kernel.c --- vboot-utils-0~R88-13597.B/futility/cmd_vbutil_kernel.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_vbutil_kernel.c 2022-02-11 14:46:09.000000000 +0000 @@ -9,7 +9,7 @@ #include #include #include /* For PRIu64 */ -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #include /* For BLKGETSIZE64 */ #endif #include @@ -26,7 +26,6 @@ #include "host_common.h" #include "kernel_blob.h" #include "vb1_helper.h" -#include "vb2_common.h" /* Global opts */ static int opt_verbose; @@ -173,7 +172,7 @@ FATAL("Unable to stat %s: %s\n", filename, strerror(errno)); if (S_ISBLK(statbuf.st_mode)) { -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) int fd = open(filename, O_RDONLY); if (fd >= 0) { ioctl(fd, BLKGETSIZE64, &file_size); diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_vbutil_keyblock.c vboot-utils-0~R99-14469.B/futility/cmd_vbutil_keyblock.c --- vboot-utils-0~R88-13597.B/futility/cmd_vbutil_keyblock.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_vbutil_keyblock.c 2022-02-11 14:46:09.000000000 +0000 @@ -19,7 +19,6 @@ #include "host_key21.h" #include "util_misc.h" #include "vb1_helper.h" -#include "vb2_common.h" /* Command line options */ enum { @@ -223,6 +222,10 @@ printf(" !REC"); if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1) printf(" REC"); + if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0) + printf(" !MINIOS"); + if (block->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1) + printf(" MINIOS"); printf("\n"); struct vb2_packed_key *data_key = &block->data_key; diff -Nru vboot-utils-0~R88-13597.B/futility/cmd_vbutil_key.c vboot-utils-0~R99-14469.B/futility/cmd_vbutil_key.c --- vboot-utils-0~R88-13597.B/futility/cmd_vbutil_key.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/cmd_vbutil_key.c 2022-02-11 14:46:09.000000000 +0000 @@ -17,7 +17,6 @@ #include "host_key21.h" #include "util_misc.h" #include "vb1_helper.h" -#include "vb2_common.h" /* Command line options */ enum { diff -Nru vboot-utils-0~R88-13597.B/futility/dump_kernel_config_lib.c vboot-utils-0~R99-14469.B/futility/dump_kernel_config_lib.c --- vboot-utils-0~R88-13597.B/futility/dump_kernel_config_lib.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/dump_kernel_config_lib.c 2022-02-11 14:46:09.000000000 +0000 @@ -10,7 +10,7 @@ #include #include #include -#if !defined (__FreeBSD__) +#if !defined (__FreeBSD__) && !defined(__OpenBSD__) #include #endif #include @@ -125,7 +125,7 @@ char *newstr = NULL; int fd = open(infile, O_RDONLY | O_CLOEXEC -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) | O_LARGEFILE #endif ); diff -Nru vboot-utils-0~R88-13597.B/futility/file_type_bios.c vboot-utils-0~R99-14469.B/futility/file_type_bios.c --- vboot-utils-0~R88-13597.B/futility/file_type_bios.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/file_type_bios.c 2022-02-11 14:46:09.000000000 +0000 @@ -16,7 +16,6 @@ #include "futility_options.h" #include "host_common.h" #include "vb1_helper.h" -#include "vb2_common.h" static const char * const fmap_name[] = { "GBB", /* BIOS_FMAP_GBB */ diff -Nru vboot-utils-0~R88-13597.B/futility/flashrom_drv.c vboot-utils-0~R99-14469.B/futility/flashrom_drv.c --- vboot-utils-0~R88-13597.B/futility/flashrom_drv.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/flashrom_drv.c 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,227 @@ +/* Copyright 2021 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. + * + * The utility functions for firmware updater. + */ + +#include + +#include "2common.h" +#include "crossystem.h" +#include "host_misc.h" +#include "util_misc.h" +#include "updater.h" + +#define FLASHROM_OUTPUT_WP_PATTERN "write protect is " + +/* System environment values. */ +static const char * const FLASHROM_OUTPUT_WP_ENABLED = + FLASHROM_OUTPUT_WP_PATTERN "enabled", + * const FLASHROM_OUTPUT_WP_DISABLED = + FLASHROM_OUTPUT_WP_PATTERN "disabled"; + +// global to allow verbosity level to be injected into callback. +static enum flashrom_log_level g_verbose_screen = FLASHROM_MSG_INFO; + +static int flashrom_print_cb(enum flashrom_log_level level, const char *fmt, + va_list ap) +{ + int ret = 0; + FILE *output_type = (level < FLASHROM_MSG_INFO) ? stderr : stdout; + + if (level > g_verbose_screen) + return ret; + + ret = vfprintf(output_type, fmt, ap); + /* msg_*spew often happens inside chip accessors + * in possibly time-critical operations. + * Don't slow them down by flushing. + */ + if (level != FLASHROM_MSG_SPEW) + fflush(output_type); + + return ret; +} + +static char *flashrom_extract_params(const char *str, char **prog, char **params) +{ + char *tmp = strdup(str); + *prog = strtok(tmp, ":"); + *params = strtok(NULL, ""); + return tmp; +} + +int flashrom_read_image(struct firmware_image *image, const char *region, + int verbosity) +{ + int r = 0; + size_t len = 0; + + g_verbose_screen = verbosity; + + char *programmer, *params; + char *tmp = flashrom_extract_params(image->programmer, &programmer, ¶ms); + + struct flashrom_programmer *prog = NULL; + struct flashrom_flashctx *flashctx = NULL; + struct flashrom_layout *layout = NULL; + + flashrom_set_log_callback((flashrom_log_callback *)&flashrom_print_cb); + + r |= flashrom_init(1); + r |= flashrom_programmer_init(&prog, programmer, params); + r |= flashrom_flash_probe(&flashctx, prog, NULL); + + len = flashrom_flash_getsize(flashctx); + + if (region) { + r = flashrom_layout_read_fmap_from_buffer( + &layout, flashctx, (const uint8_t *)image->data, + image->size); + if (r > 0) { + WARN("could not read fmap from image, r=%d, " + "falling back to read from rom\n", r); + r = flashrom_layout_read_fmap_from_rom( + &layout, flashctx, 0, len); + if (r > 0) { + ERROR("could not read fmap from rom, r=%d\n", r); + r = -1; + goto err_cleanup; + } + } + // empty region causes seg fault in API. + r |= flashrom_layout_include_region(layout, region); + if (r > 0) { + ERROR("could not include region = '%s'\n", region); + r = -1; + goto err_cleanup; + } + flashrom_layout_set(flashctx, layout); + } + + image->data = calloc(1, len); + image->size = len; + image->file_name = strdup(""); + + r |= flashrom_image_read(flashctx, image->data, len); + +err_cleanup: + r |= flashrom_programmer_shutdown(prog); + flashrom_layout_release(layout); + flashrom_flash_release(flashctx); + free(tmp); + + return r; +} + +int flashrom_write_image(const struct firmware_image *image, + const char *region, + const struct firmware_image *diff_image, + int verbosity) +{ + int r = 0; + size_t len = 0; + + g_verbose_screen = verbosity; + + char *programmer, *params; + char *tmp = flashrom_extract_params(image->programmer, &programmer, ¶ms); + + struct flashrom_programmer *prog = NULL; + struct flashrom_flashctx *flashctx = NULL; + struct flashrom_layout *layout = NULL; + + flashrom_set_log_callback((flashrom_log_callback *)&flashrom_print_cb); + + r |= flashrom_init(1); + r |= flashrom_programmer_init(&prog, programmer, params); + r |= flashrom_flash_probe(&flashctx, prog, NULL); + + len = flashrom_flash_getsize(flashctx); + if (len == 0) { + ERROR("zero sized flash detected\n"); + r = -1; + goto err_cleanup; + } + + if (diff_image) { + if (diff_image->size != image->size) { + ERROR("diff_image->size != image->size"); + r = -1; + goto err_cleanup; + } + } + + if (region) { + r = flashrom_layout_read_fmap_from_buffer( + &layout, flashctx, (const uint8_t *)image->data, + image->size); + if (r > 0) { + WARN("could not read fmap from image, r=%d, " + "falling back to read from rom\n", r); + r = flashrom_layout_read_fmap_from_rom( + &layout, flashctx, 0, len); + if (r > 0) { + ERROR("could not read fmap from rom, r=%d\n", r); + r = -1; + goto err_cleanup; + } + } + // empty region causes seg fault in API. + r |= flashrom_layout_include_region(layout, region); + if (r > 0) { + ERROR("could not include region = '%s'\n", region); + r = -1; + goto err_cleanup; + } + flashrom_layout_set(flashctx, layout); + } + + flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_WHOLE_CHIP, true); + flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, true); + if (diff_image) /* equiv --noverify --flash-contents=diff_image at cli */ + flashrom_flag_set(flashctx, FLASHROM_FLAG_VERIFY_AFTER_WRITE, false); + + r |= flashrom_image_write(flashctx, image->data, image->size, + diff_image ? diff_image->data : NULL); + +err_cleanup: + r |= flashrom_programmer_shutdown(prog); + flashrom_layout_release(layout); + flashrom_flash_release(flashctx); + free(tmp); + + return r; +} + +/* Helper function to return write protection status via given programmer. */ +enum wp_state flashrom_get_wp(const char *programmer) +{ + char *command, *result; + const char *postfix; + int r; + + /* grep is needed because host_shell only returns 1 line. */ + postfix = " 2>/dev/null | grep \"" FLASHROM_OUTPUT_WP_PATTERN "\""; + + + /* TODO(b/203715651): link with flashrom directly. */ + ASPRINTF(&command, "flashrom --wp-status -p %s %s", programmer, postfix); + + /* invokes flashrom(8) with non-zero result if error. */ + result = host_shell(command); + strip_string(result, NULL); + free(command); + VB2_DEBUG("wp-status: %s\n", result); + + if (strstr(result, FLASHROM_OUTPUT_WP_ENABLED)) + r = WP_ENABLED; + else if (strstr(result, FLASHROM_OUTPUT_WP_DISABLED)) + r = WP_DISABLED; + else + r = WP_ERROR; + free(result); + + return r; +} diff -Nru vboot-utils-0~R88-13597.B/futility/futility.h vboot-utils-0~R99-14469.B/futility/futility.h --- vboot-utils-0~R88-13597.B/futility/futility.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/futility.h 2022-02-11 14:46:09.000000000 +0000 @@ -116,14 +116,6 @@ /* Copies a file or dies with an error message */ void futil_copy_file_or_die(const char *infile, const char *outfile); -/* Update ryu root key header in the image */ -int fill_ryu_root_header(uint8_t *ptr, size_t size, - const struct vb2_gbb_header *gbb); - -/* Verify ryu root key header */ -int verify_ryu_root_header(uint8_t *ptr, size_t size, - const struct vb2_gbb_header *gbb); - /* Possible file operation errors */ enum futil_file_err { FILE_ERR_NONE, @@ -148,6 +140,12 @@ enum futil_file_err futil_unmap_file(int fd, int writeable, uint8_t *buf, uint32_t len); +/* + * Parse input string as a hex representation of size len, exit with error if + * the string is not a valid hex string or is of a wrongs size. + */ +void parse_digest_or_die(uint8_t *buf, int len, const char *str); + /* The CPU architecture is occasionally important */ enum arch_t { ARCH_UNSPECIFIED, diff -Nru vboot-utils-0~R88-13597.B/futility/misc.c vboot-utils-0~R99-14469.B/futility/misc.c --- vboot-utils-0~R88-13597.B/futility/misc.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/misc.c 2022-02-11 14:46:09.000000000 +0000 @@ -5,7 +5,7 @@ #include #include -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) #include /* For BLKGETSIZE64 */ #endif #include @@ -272,7 +272,7 @@ return FILE_ERR_STAT; } -#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) +#if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__) if (S_ISBLK(sb.st_mode)) ioctl(fd, BLKGETSIZE64, &sb.st_size); #endif @@ -352,3 +352,54 @@ return FILE_TYPE_CHROMIUMOS_DISK; } + +static int parse_hex(uint8_t *val, const char *str) +{ + uint8_t v = 0; + char c; + int digit; + + for (digit = 0; digit < 2; digit++) { + c = *str; + if (!c) + return 0; + if (!isxdigit(c)) + return 0; + c = tolower(c); + if (c >= '0' && c <= '9') + v += c - '0'; + else + v += 10 + c - 'a'; + if (!digit) + v <<= 4; + str++; + } + + *val = v; + return 1; +} + +void parse_digest_or_die(uint8_t *buf, int len, const char *str) +{ + const char *s = str; + int i; + + for (i = 0; i < len; i++) { + /* skip whitespace */ + while (*s && isspace(*s)) + s++; + if (!*s) + break; + if (!parse_hex(buf, s)) + break; + + /* on to the next byte */ + s += 2; + buf++; + } + + if ((i != len) || *s) { + fprintf(stderr, "Invalid DIGEST \"%s\"\n", str); + exit(1); + } +} diff -Nru vboot-utils-0~R88-13597.B/futility/ryu_root_header.c vboot-utils-0~R99-14469.B/futility/ryu_root_header.c --- vboot-utils-0~R88-13597.B/futility/ryu_root_header.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/ryu_root_header.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,165 +0,0 @@ -/* Copyright 2015 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "2common.h" -#include "2sha.h" -#include "2sysincludes.h" -#include "futility.h" - -#define SEARCH_STRIDE 4 - -/** - * Check if the pointer contains the magic string. We need to use a - * case-swapped version, so that the actual magic string doesn't appear in the - * code, to avoid falsely finding it when searching for the struct. - */ -static int is_magic(const void *ptr) -{ - const char magic_inv[RYU_ROOT_KEY_HASH_MAGIC_SIZE] = - RYU_ROOT_KEY_HASH_MAGIC_INVCASE; - const char *magic = ptr; - int i; - - for (i = 0; i < RYU_ROOT_KEY_HASH_MAGIC_SIZE; i++) { - if (magic[i] != (magic_inv[i] ^ 0x20)) - return 0; - } - - return 1; -} - -static int valid_ryu_root_header(struct vb2_ryu_root_key_hash *hash, - size_t size) -{ - if (!is_magic(hash->magic)) - return 0; /* Wrong magic */ - - if (hash->header_version_major != RYU_ROOT_KEY_HASH_VERSION_MAJOR) - return 0; /* Version we can't parse */ - - if (hash->struct_size < EXPECTED_VB2_RYU_ROOT_KEY_HASH_SIZE) - return 0; /* Header too small */ - - if (hash->struct_size > size) - return 0; /* Claimed size doesn't fit in buffer */ - - return 1; -} - -/** - * Find the root key hash struct and return it or NULL if error. - */ -static struct vb2_ryu_root_key_hash *find_ryu_root_header(uint8_t *ptr, - size_t size) -{ - size_t i; - struct vb2_ryu_root_key_hash *tmp, *hash = NULL; - int count = 0; - - /* Look for the ryu root key hash header */ - for (i = 0; i <= size - SEARCH_STRIDE; i += SEARCH_STRIDE) { - if (!is_magic(ptr + i)) - continue; - - /* Found something. See if it's any good. */ - tmp = (struct vb2_ryu_root_key_hash *) (ptr + i); - if (valid_ryu_root_header(tmp, size - i)) - if (!count++) - hash = tmp; - } - - switch (count) { - case 0: - return NULL; - case 1: - return hash; - default: - fprintf(stderr, - "WARNING: multiple ryu root hash headers found\n"); - /* But hey, it's only a warning. Use the first one. */ - return hash; - } -} - -static void calculate_root_key_hash(uint8_t *digest, size_t digest_size, - const struct vb2_gbb_header *gbb) -{ - const uint8_t *gbb_base = (const uint8_t *)gbb; - - vb2_digest_buffer(gbb_base + gbb->rootkey_offset, - gbb->rootkey_size, - VB2_HASH_SHA256, - digest, - digest_size); -} - -int fill_ryu_root_header(uint8_t *ptr, size_t size, - const struct vb2_gbb_header *gbb) -{ - struct vb2_ryu_root_key_hash *hash; - - /* - * Find the ryu root header. If not found, nothing we can do, but - * that's ok because most images don't have the header. - */ - hash = find_ryu_root_header(ptr, size); - if (!hash) - return 0; - - /* Update the hash stored in the header based on the root key */ - calculate_root_key_hash(hash->root_key_hash_digest, - sizeof(hash->root_key_hash_digest), - gbb); - - printf(" - calculate ryu root hash: success\n"); - return 0; -} - -int verify_ryu_root_header(uint8_t *ptr, size_t size, - const struct vb2_gbb_header *gbb) -{ - uint8_t digest[VB2_SHA256_DIGEST_SIZE] = {0}; - - struct vb2_ryu_root_key_hash *hash; - - /* - * Find the ryu root header. If not found, nothing we can do, but - * that's ok because most images don't have the header. - */ - hash = find_ryu_root_header(ptr, size); - if (!hash) { - printf(" - ryu root hash not found\n"); - return 0; - } - - /* Check for all 0's, which means hash hasn't been set */ - if (0 == memcmp(digest, hash->root_key_hash_digest, sizeof(digest))) { - printf(" - ryu root hash is unset\n"); - return 0; - } - - /* Update the hash stored in the header based on the root key */ - calculate_root_key_hash(digest, sizeof(digest), gbb); - - if (0 == memcmp(digest, hash->root_key_hash_digest, sizeof(digest))) { - printf(" - ryu root hash verified\n"); - return 0; - } else { - printf(" - ryu root hash does not verify\n"); - return -1; - } -} diff -Nru vboot-utils-0~R88-13597.B/futility/updater_archive.c vboot-utils-0~R99-14469.B/futility/updater_archive.c --- vboot-utils-0~R88-13597.B/futility/updater_archive.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/updater_archive.c 2022-02-11 14:46:09.000000000 +0000 @@ -8,6 +8,9 @@ #include #include #include +#if defined(__OpenBSD__) +#include +#endif #include #include #include @@ -27,10 +30,13 @@ #include #endif +#ifdef HAVE_CROSID +#include +#endif + #include "host_misc.h" #include "updater.h" #include "util_misc.h" -#include "vb2_common.h" /* * A firmware update package (archive) is a file packed by either shar(1) or @@ -813,6 +819,30 @@ return !manifest_add_model(manifest, &model); } +/** + * get_manifest_key() - Wrapper to get the firmware manifest key from crosid + * + * @manifest_key_out - Output parameter of the firmware manifest key. + * + * Returns: + * - <0 if libcrosid is unavailable or there was an error reading + * device data + * - >=0 (the matched device index) success + */ +static int get_manifest_key(char **manifest_key_out) +{ +#ifdef HAVE_CROSID + return crosid_get_firmware_manifest_key(manifest_key_out); +#else + ERROR("This version of futility was compiled without libcrosid " + "(perhaps compiled outside of the Chrome OS build system?) and " + "the update command is not fully supported. Either compile " + "from the Chrome OS build, or pass --model to manually specify " + "the machine model.\n"); + return -1; +#endif +} + /* * Finds the existing model_config from manifest that best matches current * system (as defined by model_name). @@ -821,9 +851,10 @@ const struct model_config *manifest_find_model(const struct manifest *manifest, const char *model_name) { - char *sys_model_name = NULL; + char *manifest_key = NULL; const struct model_config *model = NULL; int i; + int matched_index; /* * For manifest with single model defined, we should just return because @@ -834,9 +865,16 @@ return &manifest->models[0]; if (!model_name) { - sys_model_name = host_shell("mosys platform model"); - VB2_DEBUG("System model name: '%s'\n", sys_model_name); - model_name = sys_model_name; + matched_index = get_manifest_key(&manifest_key); + if (matched_index < 0) { + ERROR("Failed to get device identity. " + "Run \"crosid -v\" for explanation.\n"); + return NULL; + } + + VB2_DEBUG("Matched chromeos-config index: %d\n", matched_index); + VB2_DEBUG("Manifest key (model): '%s'\n", manifest_key); + model_name = manifest_key; } for (i = 0; !model && i < manifest->num; i++) { @@ -844,27 +882,27 @@ model = &manifest->models[i]; } if (!model) { - if (!*model_name) - ERROR("Cannot get model name.\n"); - else - ERROR("Unsupported model: '%s'.\n", model_name); + ERROR("Unsupported model: '%s'.\n", model_name); fprintf(stderr, - "You are probably running an image for wrong board, or " - "a device in early stage that 'mosys' command is not " - "ready, or image from old (or factory) branches that " - "Unified Build config is not updated yet for 'mosys'.\n" - "Please check command 'mosys platform model', " - "which should output one of the supported models below:" - "\n"); + "The firmware manifest key '%s' is not present in this " + "updater archive. The known keys to this updater " + "archive are:\n", model_name); for (i = 0; i < manifest->num; i++) fprintf(stderr, " %s", manifest->models[i].name); - fprintf(stderr, "\n"); + fprintf(stderr, "\n\n"); + fprintf(stderr, + "Perhaps you are trying to use an updater archive for " + "the wrong board, or designed for an older OS version " + "before this model was supported.\n"); + fprintf(stderr, + "Hint: Read the FIRMWARE_MANIFEST_KEY from the output " + "of the crosid command.\n"); } - free(sys_model_name); + free(manifest_key); return model; } @@ -1058,16 +1096,16 @@ return; if (load_firmware_image(&image, fpath, archive)) return; - if (is_host) - gbb = find_gbb(&image); - else + if (!is_host) printf(",\n"); printf("%*s\"%s\": { \"versions\": { \"ro\": \"%s\", \"rw\": \"%s\" },", indent, "", name, image.ro_version, image.rw_version_a); indent += 2; - if (is_host && patch_image_by_model(&image, m, archive) != 0) { + if (!is_host) { + /* No extra information to be printed */ + } else if (patch_image_by_model(&image, m, archive) != 0) { ERROR("Failed to patch images by model: %s\n", m->name); - } else if (gbb) { + } else if (NULL != (gbb = find_gbb(&image))) { printf("\n%*s\"keys\": { \"root\": \"%s\", ", indent, "", get_gbb_key_hash(gbb, gbb->rootkey_offset, diff -Nru vboot-utils-0~R88-13597.B/futility/updater.c vboot-utils-0~R99-14469.B/futility/updater.c --- vboot-utils-0~R88-13597.B/futility/updater.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/updater.c 2022-02-11 14:46:09.000000000 +0000 @@ -14,7 +14,6 @@ #include "host_misc.h" #include "updater.h" #include "util_misc.h" -#include "vb2_common.h" #define REMOVE_WP_URL "https://goo.gl/ces83U" @@ -276,7 +275,7 @@ static int set_try_cookies(struct updater_config *cfg, const char *target, int has_update, int is_vboot2) { - int tries = 6; + int tries = 8; const char *slot; /* EC Software Sync needs few more reboots. */ @@ -459,7 +458,7 @@ */ if (check_programmer_wp && get_system_property(SYS_PROP_WP_HW, cfg) == WP_ENABLED && - host_get_wp(image->programmer) == WP_ENABLED) { + flashrom_get_wp(image->programmer) == WP_ENABLED) { ERROR("Target %s is write protected, skip updating.\n", image->programmer); return 0; @@ -1209,8 +1208,13 @@ image_from->file_name, image_from->ro_version, image_from->rw_version_a, image_from->rw_version_b); - if (cfg->check_platform && check_compatible_platform(cfg)) + try_apply_quirk(QUIRK_NO_CHECK_PLATFORM, cfg); + if (cfg->check_platform && check_compatible_platform(cfg)) { + ERROR("The firmware image is not compatible with your system. " + "If you really want to proceed, please run again with: " + "--quirks=no_check_platform\n"); return UPDATE_ERR_PLATFORM; + } wp_enabled = is_write_protection_enabled(cfg); STATUS("Write protection: %d (%s; HW=%d, SW=%d).\n", wp_enabled, @@ -1372,17 +1376,13 @@ assert(model->is_white_label); if (!signature_id) { - if (cfg->image_current.data) { - tmp_image = get_firmware_image_temp_file( - &cfg->image_current, &cfg->tempfiles); - if (!tmp_image) - return 1; - } else { + if (!cfg->image_current.data) { INFO("Loading system firmware for white label...\n"); load_system_firmware(&cfg->image_current, &cfg->tempfiles, cfg->verbosity); - tmp_image = cfg->image_current.file_name; } + tmp_image = get_firmware_image_temp_file( + &cfg->image_current, &cfg->tempfiles); if (!tmp_image) { ERROR("Failed to get system current firmware\n"); return 1; @@ -1622,7 +1622,7 @@ errorcnt += !!setup_config_quirks(arg->quirks, cfg); /* Additional checks. */ - if (check_single_image && (cfg->ec_image.data || cfg->pd_image.data)) { + if (check_single_image && !do_output && (cfg->ec_image.data || cfg->pd_image.data)) { errorcnt++; ERROR("EC/PD images are not supported in current mode.\n"); } diff -Nru vboot-utils-0~R88-13597.B/futility/updater.h vboot-utils-0~R99-14469.B/futility/updater.h --- vboot-utils-0~R88-13597.B/futility/updater.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/updater.h 2022-02-11 14:46:09.000000000 +0000 @@ -14,6 +14,7 @@ /* FMAP section names. */ static const char * const FMAP_RO_FRID = "RO_FRID", * const FMAP_RO_SECTION = "RO_SECTION", + * const FMAP_RO_CBFS = "COREBOOT", * const FMAP_RO_GBB = "GBB", * const FMAP_RW_VBLOCK_A = "VBLOCK_A", * const FMAP_RW_VBLOCK_B = "VBLOCK_B", @@ -45,6 +46,7 @@ QUIRK_EC_PARTIAL_RECOVERY, QUIRK_OVERRIDE_SIGNATURE_ID, QUIRK_PRESERVE_ME, + QUIRK_NO_CHECK_PLATFORM, QUIRK_MAX, }; diff -Nru vboot-utils-0~R88-13597.B/futility/updater_quirks.c vboot-utils-0~R99-14469.B/futility/updater_quirks.c --- vboot-utils-0~R88-13597.B/futility/updater_quirks.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/updater_quirks.c 2022-02-11 14:46:09.000000000 +0000 @@ -46,7 +46,7 @@ { .match = "Google_Poppy.", .quirks = "min_platform_version=6" }, { .match = "Google_Scarlet.", .quirks = "min_platform_version=1" }, - { .match = "Google_Trogdor.", .quirks = "min_platform_version=1" }, + { .match = "Google_Trogdor.", .quirks = "min_platform_version=2" }, /* Legacy white label units. */ { .match = "Google_Enguarde.", .quirks = "allow_empty_wltag" }, @@ -116,10 +116,10 @@ ERROR("EC image has invalid section '%s'.\n", "EC_RO"); return 1; } - ec_ro_path = cbfs_extract_file(tmp_path, FMAP_RO_SECTION, "ecro", + ec_ro_path = cbfs_extract_file(tmp_path, FMAP_RO_CBFS, "ecro", &cfg->tempfiles); if (!ec_ro_path || - !cbfs_file_exists(tmp_path, FMAP_RO_SECTION, "ecro.hash")) { + !cbfs_file_exists(tmp_path, FMAP_RO_CBFS, "ecro.hash")) { INFO("No valid EC RO for software sync in AP firmware.\n"); return 1; } @@ -415,6 +415,16 @@ } /* + * Disable checking platform compatibility. + */ +static int quirk_no_check_platform(struct updater_config *cfg) +{ + WARN("Disabled checking platform. You are on your own.\n"); + cfg->check_platform = 0; + return 0; +} + +/* * Registers known quirks to a updater_config object. */ void updater_register_quirks(struct updater_config *cfg) @@ -473,6 +483,11 @@ quirks->help = "b/165590952; Preserve ME during firmware update except " "for factory update or developer images."; quirks->apply = quirk_preserve_me; + + quirks = &cfg->quirks[QUIRK_NO_CHECK_PLATFORM]; + quirks->name = "no_check_platform"; + quirks->help = "Do not check platform name."; + quirks->apply = quirk_no_check_platform; } /* diff -Nru vboot-utils-0~R88-13597.B/futility/updater_utils.c vboot-utils-0~R99-14469.B/futility/updater_utils.c --- vboot-utils-0~R88-13597.B/futility/updater_utils.c 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/updater_utils.c 2022-02-11 14:46:09.000000000 +0000 @@ -9,8 +9,9 @@ #include #include #include +#include #include -#if defined (__FreeBSD__) +#if defined (__FreeBSD__) || defined(__OpenBSD__) #include #endif @@ -21,20 +22,9 @@ #include "updater.h" #define COMMAND_BUFFER_SIZE 256 -#define FLASHROM_OUTPUT_WP_PATTERN "write protect is " - -enum flashrom_ops { - FLASHROM_READ, - FLASHROM_WRITE, - FLASHROM_WP_STATUS, -}; /* System environment values. */ -static const char * const STR_REV = "rev", - * const FLASHROM_OUTPUT_WP_ENABLED = - FLASHROM_OUTPUT_WP_PATTERN "enabled", - * const FLASHROM_OUTPUT_WP_DISABLED = - FLASHROM_OUTPUT_WP_PATTERN "disabled"; +static const char * const STR_REV = "rev"; /* * Strips a string (usually from shell execution output) by removing all the @@ -172,43 +162,18 @@ return 0; } -/* - * Loads a firmware image from file. - * If archive is provided and file_name is a relative path, read the file from - * archive. - * Returns IMAGE_LOAD_SUCCESS on success, IMAGE_READ_FAILURE on file I/O - * failure, or IMAGE_PARSE_FAILURE for non-vboot images. - */ -int load_firmware_image(struct firmware_image *image, const char *file_name, - struct archive *archive) +static int parse_firmware_image(struct firmware_image *image) { int ret = IMAGE_LOAD_SUCCESS; const char *section_a = NULL, *section_b = NULL; - if (!file_name) { - ERROR("No file name given\n"); - return IMAGE_READ_FAILURE; - } - - VB2_DEBUG("Load image file from %s...\n", file_name); - - if (!archive_has_entry(archive, file_name)) { - ERROR("Does not exist: %s\n", file_name); - return IMAGE_READ_FAILURE; - } - if (archive_read_file(archive, file_name, &image->data, &image->size, - NULL) != VB2_SUCCESS) { - ERROR("Failed to load %s\n", file_name); - return IMAGE_READ_FAILURE; - } - VB2_DEBUG("Image size: %d\n", image->size); assert(image->data); - image->file_name = strdup(file_name); + image->fmap_header = fmap_find(image->data, image->size); if (!image->fmap_header) { - ERROR("Invalid image file (missing FMAP): %s\n", file_name); + ERROR("Invalid image file (missing FMAP): %s\n", image->file_name); ret = IMAGE_PARSE_FAILURE; } @@ -222,7 +187,7 @@ section_a = FMAP_RW_FWID; section_b = FMAP_RW_FWID; } else if (!ret) { - ERROR("Unsupported VBoot firmware (no RW ID): %s\n", file_name); + ERROR("Unsupported VBoot firmware (no RW ID): %s\n", image->file_name); ret = IMAGE_PARSE_FAILURE; } @@ -237,6 +202,38 @@ } /* + * Loads a firmware image from file. + * If archive is provided and file_name is a relative path, read the file from + * archive. + * Returns IMAGE_LOAD_SUCCESS on success, IMAGE_READ_FAILURE on file I/O + * failure, or IMAGE_PARSE_FAILURE for non-vboot images. + */ +int load_firmware_image(struct firmware_image *image, const char *file_name, + struct archive *archive) +{ + if (!file_name) { + ERROR("No file name given\n"); + return IMAGE_READ_FAILURE; + } + + VB2_DEBUG("Load image file from %s...\n", file_name); + + if (!archive_has_entry(archive, file_name)) { + ERROR("Does not exist: %s\n", file_name); + return IMAGE_READ_FAILURE; + } + if (archive_read_file(archive, file_name, &image->data, &image->size, + NULL) != VB2_SUCCESS) { + ERROR("Failed to load %s\n", file_name); + return IMAGE_READ_FAILURE; + } + + image->file_name = strdup(file_name); + + return parse_firmware_image(image); +} + +/* * Generates a temporary file for snapshot of firmware image contents. * * Returns a file path if success, otherwise NULL. @@ -462,6 +459,7 @@ char *host_detect_servo(int *need_prepare_ptr) { const char *servo_port = getenv(ENV_SERVOD_PORT); + const char *servo_name = getenv(ENV_SERVOD_NAME); char *servo_type = host_shell("dut-control -o servo_type 2>/dev/null"); const char *programmer = NULL; char *ret = NULL; @@ -469,10 +467,11 @@ char *servo_serial = NULL; /* Get serial name if servo port is provided. */ - if (servo_port && *servo_port) { + if ((servo_port && *servo_port) || (servo_name && *servo_name)) { const char *cmd = "dut-control -o serialname 2>/dev/null"; - VB2_DEBUG("Select servod using port: %s\n", servo_port); + VB2_DEBUG("Select servod using port: %s or name: %s\n", + servo_port, servo_name); if (strstr(servo_type, "with_servo_micro")) cmd = ("dut-control -o servo_micro_serialname" " 2>/dev/null"); @@ -491,8 +490,9 @@ VB2_DEBUG("Selected Servo Micro.\n"); programmer = "raiden_debug_spi"; need_prepare = 1; - } else if (strstr(servo_type, "ccd_cr50")) { - VB2_DEBUG("Selected CCD CR50.\n"); + } else if (strstr(servo_type, "ccd_cr50") || + strstr(servo_type, "ccd_gsc")) { + VB2_DEBUG("Selected CCD.\n"); programmer = "raiden_debug_spi:target=AP"; } else { VB2_DEBUG("Selected Servo V2.\n"); @@ -519,112 +519,6 @@ } /* - * A helper function to invoke flashrom(8) command. - * Returns 0 if success, non-zero if error. - */ -static int host_flashrom(enum flashrom_ops op, const char *image_path, - const char *programmer, int verbose, - const char *section_name, const char *extra) -{ - char *command, *result; - const char *op_cmd, *dash_i = "-i", *postfix = ""; - int r; - - switch (verbose) { - case 0: - postfix = " >/dev/null 2>&1"; - break; - case 1: - break; - case 2: - postfix = "-V"; - break; - case 3: - postfix = "-V -V"; - break; - default: - postfix = "-V -V -V"; - break; - } - - if (!section_name || !*section_name) { - dash_i = ""; - section_name = ""; - } - - switch (op) { - case FLASHROM_READ: - op_cmd = "-r"; - assert(image_path); - break; - - case FLASHROM_WRITE: - op_cmd = "-w"; - assert(image_path); - break; - - case FLASHROM_WP_STATUS: - op_cmd = "--wp-status"; - assert(image_path == NULL); - image_path = ""; - /* grep is needed because host_shell only returns 1 line. */ - postfix = " 2>/dev/null | grep \"" \ - FLASHROM_OUTPUT_WP_PATTERN "\""; - break; - - default: - assert(0); - return -1; - } - - if (!extra) - extra = ""; - - /* TODO(hungte) In future we should link with flashrom directly. */ - ASPRINTF(&command, "flashrom %s %s -p %s %s %s %s %s", op_cmd, - image_path, programmer, dash_i, section_name, extra, - postfix); - - if (verbose) - INFO("Executing: %s\n", command); - - if (op != FLASHROM_WP_STATUS) { - r = system(command); - free(command); - if (r) - ERROR("Error code: %d\n", r); - return r; - } - - result = host_shell(command); - strip_string(result, NULL); - free(command); - VB2_DEBUG("wp-status: %s\n", result); - - if (strstr(result, FLASHROM_OUTPUT_WP_ENABLED)) - r = WP_ENABLED; - else if (strstr(result, FLASHROM_OUTPUT_WP_DISABLED)) - r = WP_DISABLED; - else - r = WP_ERROR; - free(result); - return r; -} - -/* Helper function to return write protection status via given programmer. */ -enum wp_state host_get_wp(const char *programmer) -{ - return host_flashrom(FLASHROM_WP_STATUS, NULL, programmer, 0, NULL, - NULL); -} - -/* Helper function to return host software write protection status. */ -static int host_get_wp_sw(void) -{ - return host_get_wp(PROG_HOST); -} - -/* * Loads the active system firmware image (usually from SPI flash chip). * Returns 0 if success, non-zero if error. */ @@ -632,26 +526,10 @@ struct tempfile *tempfiles, int verbosity) { int r; - const char *tmp_path = create_temp_file(tempfiles); - if (!tmp_path) - return -1; - - r = host_flashrom(FLASHROM_READ, tmp_path, image->programmer, - verbosity, NULL, NULL); - /* - * The verbosity for host_flashrom will be translated to - * (verbosity-1)*'-V', and usually 3*'-V' is enough for debugging. - */ - const int debug_verbosity = 4; - if (r && verbosity < debug_verbosity) { - /* Read again, with verbose messages for debugging. */ - WARN("Failed reading system firmware (%d), try again...\n", r); - r = host_flashrom(FLASHROM_READ, tmp_path, image->programmer, - debug_verbosity, NULL, NULL); - } + r = flashrom_read_image(image, NULL, (verbosity + 1)); if (!r) - r = load_firmware_image(image, tmp_path, NULL); + r = parse_firmware_image(image); return r; } @@ -666,28 +544,13 @@ struct tempfile *tempfiles, int verbosity) { - const char *tmp_path = get_firmware_image_temp_file(image, tempfiles); - const char *tmp_diff = NULL; - - const char *programmer = image->programmer; - char *extra = NULL; - int r; - - if (!tmp_path) - return -1; - - if (diff_image) { - tmp_diff = get_firmware_image_temp_file( - diff_image, tempfiles); - if (!tmp_diff) - return -1; - ASPRINTF(&extra, "--noverify --diff=%s", tmp_diff); - } + return flashrom_write_image(image, section_name, diff_image, (verbosity + 1)); +} - r = host_flashrom(FLASHROM_WRITE, tmp_path, programmer, verbosity, - section_name, extra); - free(extra); - return r; +/* Helper function to return host software write protection status. */ +static int host_get_wp_sw(void) +{ + return flashrom_get_wp(PROG_HOST); } /* Helper function to configure all properties. */ diff -Nru vboot-utils-0~R88-13597.B/futility/updater_utils.h vboot-utils-0~R99-14469.B/futility/updater_utils.h --- vboot-utils-0~R88-13597.B/futility/updater_utils.h 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/updater_utils.h 2022-02-11 14:46:09.000000000 +0000 @@ -175,11 +175,14 @@ }; /* Helper function to return write protection status via given programmer. */ -enum wp_state host_get_wp(const char *programmer); +enum wp_state flashrom_get_wp(const char *programmer); /* The environment variable name for setting servod port. */ #define ENV_SERVOD_PORT "SERVOD_PORT" +/* The environment variable name for setting servod name. */ +#define ENV_SERVOD_NAME "SERVOD_NAME" + /* * Helper function to detect type of Servo board attached to host. * Returns a string as programmer parameter on success, otherwise NULL. @@ -228,4 +231,11 @@ */ const char *get_firmware_rootkey_hash(const struct firmware_image *image); +int flashrom_read_image(struct firmware_image *image, const char *region, + int verbosity); +int flashrom_write_image(const struct firmware_image *image, + const char *region, + const struct firmware_image *diff_image, + int verbosity); + #endif /* VBOOT_REFERENCE_FUTILITY_UPDATER_UTILS_H_ */ diff -Nru vboot-utils-0~R88-13597.B/futility/vb1_helper.c vboot-utils-0~R99-14469.B/futility/vb1_helper.c --- vboot-utils-0~R88-13597.B/futility/vb1_helper.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/futility/vb1_helper.c 2022-02-11 14:46:09.000000000 +0000 @@ -21,7 +21,6 @@ #include "kernel_blob.h" #include "util_misc.h" #include "vb1_helper.h" -#include "vb2_common.h" /****************************************************************************/ /* Here are globals containing all the bits & pieces I'm working on. @@ -549,6 +548,10 @@ printf(" !REC"); if (g_keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_RECOVERY_1) printf(" REC"); + if (g_keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_0) + printf(" !MINIOS"); + if (g_keyblock->keyblock_flags & VB2_KEYBLOCK_FLAG_MINIOS_1) + printf(" MINIOS"); printf("\n"); printf(" Data key algorithm: %u %s\n", data_key->algorithm, vb2_get_crypto_algorithm_name(data_key->algorithm)); diff -Nru vboot-utils-0~R88-13597.B/.gitignore vboot-utils-0~R99-14469.B/.gitignore --- vboot-utils-0~R88-13597.B/.gitignore 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/.gitignore 2022-02-11 14:46:09.000000000 +0000 @@ -1,6 +1,7 @@ /build /build-au /build-main +Cargo.lock ID scripts/newbitmaps/default_source/*.bmp scripts/newbitmaps/images/out_* @@ -8,3 +9,5 @@ scripts/newbitmaps/strings/font scripts/newbitmaps/strings/*.png scripts/newbitmaps/strings/localized_text/*/*.png +target +.idea diff -Nru vboot-utils-0~R88-13597.B/host/arch/arm/lib/crossystem_arch.c vboot-utils-0~R99-14469.B/host/arch/arm/lib/crossystem_arch.c --- vboot-utils-0~R88-13597.B/host/arch/arm/lib/crossystem_arch.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/arch/arm/lib/crossystem_arch.c 2022-02-11 14:46:09.000000000 +0000 @@ -35,7 +35,9 @@ #define PLATFORM_DEV_PATH "/sys/devices/platform/chromeos_arm" /* These should match the Linux GPIO name (i.e., 'gpio-line-names'). */ #define GPIO_NAME_RECOVERY_SW_L "RECOVERY_SW_L" +#define GPIO_NAME_RECOVERY_SW "RECOVERY_SW" #define GPIO_NAME_WP_L "AP_FLASH_WP_L" +#define GPIO_NAME_WP "AP_FLASH_WP" /* Device for NVCTX write */ #define NVCTX_PATH "/dev/mmcblk%d" /* Base name for GPIO files */ @@ -481,6 +483,9 @@ value = gpiod_read(GPIO_NAME_RECOVERY_SW_L, true); if (value != -1) return value; + value = gpiod_read(GPIO_NAME_RECOVERY_SW, false); + if (value != -1) + return value; /* Try the deprecated chromeos_arm platform device next. */ return VbGetPlatformGpioStatus("recovery"); } else if (!strcasecmp(name, "wpsw_cur")) { @@ -489,6 +494,9 @@ value = gpiod_read(GPIO_NAME_WP_L, true); if (value != -1) return value; + value = gpiod_read(GPIO_NAME_WP, false); + if (value != -1) + return value; /* Try the deprecated chromeos_arm platform device next. */ return VbGetPlatformGpioStatus("write-protect"); } else if (!strcasecmp(name, "recoverysw_ec_boot")) { diff -Nru vboot-utils-0~R88-13597.B/host/arch/x86/lib/crossystem_arch.c vboot-utils-0~R99-14469.B/host/arch/x86/lib/crossystem_arch.c --- vboot-utils-0~R88-13597.B/host/arch/x86/lib/crossystem_arch.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/arch/x86/lib/crossystem_arch.c 2022-02-11 14:46:09.000000000 +0000 @@ -7,7 +7,7 @@ #include #include #include -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) #include #include #endif @@ -100,7 +100,7 @@ static void VbFixCmosChecksum(FILE* file) { -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) int fd = fileno(file); ioctl(fd, NVRAM_SETCKS); #endif @@ -666,7 +666,7 @@ if (uname(&host) == 0) { if (sscanf(host.release, "%u.%u.", &maj, &min) == 2) { -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) if (KERNEL_VERSION(maj, min, 0) >= KERNEL_VERSION(4, 16, 0) && *offset > 11) *offset += 3; diff -Nru vboot-utils-0~R88-13597.B/host/arch/x86_64/lib/crossystem_arch.c vboot-utils-0~R99-14469.B/host/arch/x86_64/lib/crossystem_arch.c --- vboot-utils-0~R88-13597.B/host/arch/x86_64/lib/crossystem_arch.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/arch/x86_64/lib/crossystem_arch.c 2022-02-11 14:46:09.000000000 +0000 @@ -7,7 +7,7 @@ #include #include #include -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) #include #include #endif @@ -100,7 +100,7 @@ static void VbFixCmosChecksum(FILE* file) { -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) int fd = fileno(file); ioctl(fd, NVRAM_SETCKS); #endif @@ -666,7 +666,7 @@ if (uname(&host) == 0) { if (sscanf(host.release, "%u.%u.", &maj, &min) == 2) { -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) if (KERNEL_VERSION(maj, min, 0) >= KERNEL_VERSION(4, 16, 0) && *offset > 11) *offset += 3; diff -Nru vboot-utils-0~R88-13597.B/host/lib/crossystem.c vboot-utils-0~R99-14469.B/host/lib/crossystem.c --- vboot-utils-0~R88-13597.B/host/lib/crossystem.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/crossystem.c 2022-02-11 14:46:09.000000000 +0000 @@ -4,15 +4,18 @@ */ #include +#include #include #include #include +#include #include #include "2api.h" #include "2common.h" #include "2nvstorage.h" #include "2sysincludes.h" +#include "chromeos_config.h" #include "crossystem_arch.h" #include "crossystem.h" #include "crossystem_vbnv.h" @@ -21,11 +24,15 @@ #include "subprocess.h" #include "vboot_struct.h" +/* Filename for crossystem lock */ +#define CROSSYSTEM_LOCK_PATH "/run/lock/crossystem.lock" + /* Filename for kernel command line */ #define KERNEL_CMDLINE_PATH "/proc/cmdline" -/* Filename for the mount-encrypted key */ -#define MOUNT_ENCRYPTED_KEY_PATH "/mnt/stateful_partition/encrypted.key" +/* Filename for the TPM simulator NV data */ +#define TPM_SIMULATOR_NVCHIP_PATH \ + "/mnt/stateful_partition/unencrypted/tpm2-simulator/NVChip" /* Fields that GetVdatString() can get */ typedef enum VdatStringField { @@ -63,7 +70,7 @@ } VbBuildOption; static const char *fw_results[] = {"unknown", "trying", "success", "failure"}; -static const char *default_boot[] = {"disk", "usb", "legacy"}; +static const char *default_boot[] = {"disk", "usb", "altfw"}; /* Masks for kern_nv usage by kernel. */ #define KERN_NV_FWUPDATE_TRIES_MASK 0x000F @@ -85,6 +92,32 @@ return 0 == strncmp(fwid, start, strlen(start)); } +/* Acquire the lock for crossystem SetSystemProperty call. */ +static int AcquireCrossystemLock(void) +{ + int lock_fd; + + lock_fd = open(CROSSYSTEM_LOCK_PATH, O_RDWR | O_CREAT, 0600); + if (lock_fd < 0) + return -1; + + if (flock(lock_fd, LOCK_EX) < 0) + return -1; + + return lock_fd; +} + +/* Release the lock for crossystem SetSystemProperty call. */ +static int ReleaseCrossystemLock(int lock_fd) +{ + if (flock(lock_fd, F_UNLCK) < 0) + return -1; + + close(lock_fd); + + return 0; +} + static struct vb2_context *get_fake_context(void) { static uint8_t fake_workbuf[sizeof(struct vb2_shared_data) + 16] @@ -313,7 +346,7 @@ break; case VDAT_INT_FW_BOOT2: value = (sh->flags & VBSD_BOOT_FIRMWARE_VBOOT2 ? 1 : 0); - __attribute__ ((fallthrough)); + VBOOT_FALLTHROUGH; default: break; } @@ -375,8 +408,8 @@ value = vb2_get_nv_storage(VB2_NV_DISABLE_DEV_REQUEST); } else if (!strcasecmp(name,"clear_tpm_owner_request")) { if (TPM2_SIMULATOR) - /* Check mount-encrypted key status */ - value = access(MOUNT_ENCRYPTED_KEY_PATH, F_OK) != 0; + /* Check TPM simulator NVChip status */ + value = access(TPM_SIMULATOR_NVCHIP_PATH, F_OK) != 0; else value = vb2_get_nv_storage( VB2_NV_CLEAR_TPM_OWNER_REQUEST); @@ -411,8 +444,9 @@ value = vb2_get_nv_storage(VB2_NV_BACKUP_NVRAM_REQUEST); } else if (!strcasecmp(name,"dev_boot_usb")) { value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_EXTERNAL); - } else if (!strcasecmp(name,"dev_boot_legacy")) { - value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_LEGACY); + } else if (!strcasecmp(name,"dev_boot_altfw") || + !strcasecmp(name,"dev_boot_legacy")) { + value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_ALTFW); } else if (!strcasecmp(name,"dev_boot_signed_only")) { value = vb2_get_nv_storage(VB2_NV_DEV_BOOT_SIGNED_ONLY); } else if (!strcasecmp(name,"dev_enable_udc")) { @@ -477,10 +511,21 @@ return value; } -const char *VbGetSystemPropertyString(const char *name, char *dest, - size_t size) +const char *VbGetSystemPropertyString(const char *name, char *dest, size_t size) { - /* Check architecture-dependent properties first */ + /* Check for HWID override via cros_config */ + if (!strcasecmp(name, "hwid")) { + char *hwid_override; + + if (chromeos_config_get_string("/", "hwid-override", + &hwid_override) == VB2_SUCCESS) { + StrCopy(dest, hwid_override, size); + free(hwid_override); + return dest; + } + } + + /* Check architecture-dependent properties */ if (VbGetArchPropertyString(name, dest, size)) return dest; @@ -522,13 +567,14 @@ return default_boot[v]; else return "unknown"; + } else if (!strcasecmp(name, "minios_priority")) { + return vb2_get_nv_storage(VB2_NV_MINIOS_PRIORITY) ? "B" : "A"; } return NULL; } - -int VbSetSystemPropertyInt(const char *name, int value) +static int VbSetSystemPropertyIntInternal(const char *name, int value) { /* Check architecture-dependent properties first */ @@ -556,12 +602,10 @@ * on simulator */ if (value == 0) return -1; - /* Check mount-encrypted key status */ - if (!access(MOUNT_ENCRYPTED_KEY_PATH, F_OK)) { - /* Remove the mount_encrypted key, and it would - * also clear the TPM2.0 simulator NV space on - * it. */ - return remove(MOUNT_ENCRYPTED_KEY_PATH); + /* Check TPM simulator data status */ + if (!access(TPM_SIMULATOR_NVCHIP_PATH, F_OK)) { + /* Remove the TPM2.0 simulator data */ + return remove(TPM_SIMULATOR_NVCHIP_PATH); } else { /* Return success when the file is already * removed */ @@ -620,9 +664,10 @@ } else if (!strcasecmp(name,"dev_boot_usb")) { return vb2_set_nv_storage_with_backup( VB2_NV_DEV_BOOT_EXTERNAL, value); - } else if (!strcasecmp(name,"dev_boot_legacy")) { + } else if (!strcasecmp(name,"dev_boot_altfw") || + !strcasecmp(name,"dev_boot_legacy")) { return vb2_set_nv_storage_with_backup( - VB2_NV_DEV_BOOT_LEGACY, value); + VB2_NV_DEV_BOOT_ALTFW, value); } else if (!strcasecmp(name,"dev_boot_signed_only")) { return vb2_set_nv_storage_with_backup( VB2_NV_DEV_BOOT_SIGNED_ONLY, value); @@ -646,7 +691,25 @@ return -1; } -int VbSetSystemPropertyString(const char* name, const char* value) +int VbSetSystemPropertyInt(const char *name, int value) +{ + int result = -1; + int lock_fd; + + lock_fd = AcquireCrossystemLock(); + if (lock_fd < 0) + return -1; + + result = VbSetSystemPropertyIntInternal(name, value); + + if (ReleaseCrossystemLock(lock_fd) < 0) + return -1; + + return result; +} + +static int VbSetSystemPropertyStringInternal(const char *name, + const char *value) { /* Chain to architecture-dependent properties */ if (0 == VbSetArchPropertyString(name, value)) @@ -659,7 +722,13 @@ return vb2_set_nv_storage(VB2_NV_TRY_NEXT, 1); else return -1; - + } else if (!strcasecmp(name, "minios_priority")) { + if (!strcasecmp(value, "A")) + return vb2_set_nv_storage(VB2_NV_MINIOS_PRIORITY, 0); + else if (!strcasecmp(value, "B")) + return vb2_set_nv_storage(VB2_NV_MINIOS_PRIORITY, 1); + else + return -1; } else if (!strcasecmp(name, "fw_result")) { int i; @@ -671,6 +740,16 @@ } else if (!strcasecmp(name, "dev_default_boot")) { int i; + /* "legacy" term deprecated in favour of "altfw" + (see: b/179458327) */ + if (!strcasecmp(value, "legacy")) { + fprintf(stderr, + "!!!\n" + "!!! PLEASE USE 'altfw' INSTEAD OF 'legacy'\n" + "!!!\n"); + value = "altfw"; + } + for (i = 0; i < ARRAY_SIZE(default_boot); i++) { if (!strcasecmp(value, default_boot[i])) return vb2_set_nv_storage( @@ -682,6 +761,23 @@ return -1; } +int VbSetSystemPropertyString(const char *name, const char *value) +{ + int result = -1; + int lock_fd; + + lock_fd = AcquireCrossystemLock(); + if (lock_fd < 0) + return -1; + + result = VbSetSystemPropertyStringInternal(name, value); + + if (ReleaseCrossystemLock(lock_fd) < 0) + return -1; + + return result; +} + /** * Get index of the last valid VBNV entry in an EEPROM. * diff -Nru vboot-utils-0~R88-13597.B/host/lib/flashrom.c vboot-utils-0~R99-14469.B/host/lib/flashrom.c --- vboot-utils-0~R88-13597.B/host/lib/flashrom.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/flashrom.c 2022-02-11 14:46:09.000000000 +0000 @@ -155,7 +155,7 @@ FLASHROM_EXEC_NAME, "-p", programmer, - "--fast-verify", + "--noverify-all", "-w", region ? "-i" : tmpfile, region ? region_param : NULL, diff -Nru vboot-utils-0~R88-13597.B/host/lib/host_common.c vboot-utils-0~R99-14469.B/host/lib/host_common.c --- vboot-utils-0~R88-13597.B/host/lib/host_common.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/host_common.c 2022-02-11 14:46:09.000000000 +0000 @@ -12,7 +12,6 @@ #include "2sysincludes.h" #include "host_common.h" #include "host_key21.h" -#include "vb2_common.h" struct vb2_fw_preamble *vb2_create_fw_preamble( uint32_t firmware_version, @@ -134,3 +133,22 @@ /* Return the header */ return h; } + +void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble, + uint64_t *vmlinuz_header_address, + uint32_t *vmlinuz_header_size) +{ + if (preamble->header_version_minor < 1) { + *vmlinuz_header_address = 0; + *vmlinuz_header_size = 0; + } else { + /* + * Set header and size only if the preamble header version is > + * 2.1 as they don't exist in version 2.0 (Note that we don't + * need to check header_version_major; if that's not 2 then + * vb2_verify_kernel_preamble() would have already failed. + */ + *vmlinuz_header_address = preamble->vmlinuz_header_address; + *vmlinuz_header_size = preamble->vmlinuz_header_size; + } +} diff -Nru vboot-utils-0~R88-13597.B/host/lib/host_key2.c vboot-utils-0~R99-14469.B/host/lib/host_key2.c --- vboot-utils-0~R88-13597.B/host/lib/host_key2.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/host_key2.c 2022-02-11 14:46:09.000000000 +0000 @@ -19,7 +19,6 @@ #include "host_key21.h" #include "host_key.h" #include "host_misc.h" -#include "vb2_common.h" enum vb2_crypto_algorithm vb2_get_crypto_algorithm( enum vb2_hash_algorithm hash_alg, diff -Nru vboot-utils-0~R88-13597.B/host/lib/host_keyblock.c vboot-utils-0~R99-14469.B/host/lib/host_keyblock.c --- vboot-utils-0~R88-13597.B/host/lib/host_keyblock.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/host_keyblock.c 2022-02-11 14:46:09.000000000 +0000 @@ -17,7 +17,6 @@ #include "host_key21.h" #include "host_keyblock.h" #include "host_key.h" -#include "vb2_common.h" struct vb2_keyblock *vb2_create_keyblock( const struct vb2_packed_key *data_key, diff -Nru vboot-utils-0~R88-13597.B/host/lib/host_signature2.c vboot-utils-0~R99-14469.B/host/lib/host_signature2.c --- vboot-utils-0~R88-13597.B/host/lib/host_signature2.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/host_signature2.c 2022-02-11 14:46:09.000000000 +0000 @@ -22,7 +22,6 @@ #include "host_common.h" #include "host_key21.h" #include "host_signature21.h" -#include "vb2_common.h" struct vb2_signature *vb2_alloc_signature(uint32_t sig_size, uint32_t data_size) diff -Nru vboot-utils-0~R88-13597.B/host/lib/host_signature.c vboot-utils-0~R99-14469.B/host/lib/host_signature.c --- vboot-utils-0~R88-13597.B/host/lib/host_signature.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/host_signature.c 2022-02-11 14:46:09.000000000 +0000 @@ -21,7 +21,6 @@ #include "2sysincludes.h" #include "host_common.h" #include "host_signature21.h" -#include "vb2_common.h" /* Invoke [external_signer] command with [pem_file] as an argument, contents of * [inbuf] passed redirected to stdin, and the stdout of the command is put diff -Nru vboot-utils-0~R88-13597.B/host/lib/include/gsc_ro.h vboot-utils-0~R99-14469.B/host/lib/include/gsc_ro.h --- vboot-utils-0~R88-13597.B/host/lib/include/gsc_ro.h 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/include/gsc_ro.h 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,59 @@ +/* + * Copyright 2021 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_HOST_LIB_INCLUDE_GSC_RO_H +#define __VBOOT_REFERENCE_HOST_LIB_INCLUDE_GSC_RO_H + +#include +#include + +#include "2sha.h" + +struct gscvd_ro_range { + uint32_t offset; + uint32_t size; /* Use uint32_t as opposed to size_to be portable. */ +}; + +#define GSC_VD_MAGIC 0x65666135 /* Little endian '5 a f e' */ +#define GSC_VD_ROLLBACK_COUNTER 1 + +struct gsc_verification_data { + uint32_t gv_magic; + /* + * Size of this structure in bytes, including the ranges array, + * signature and root key bodies. + */ + uint16_t size; + uint16_t major_version; /* Version of this struct layout. Starts at 0 */ + uint16_t minor_version; + /* + * GSC will cache the counter value and will not accept verification + * data blobs with a lower value. + */ + uint16_t rollback_counter; + uint32_t gsc_board_id; /* Locks blob to certain platform. */ + uint32_t gsc_flags; /* A field for future enhancements. */ + /* + * The location of fmap that points to this blob. This location must + * also be in one of the verified sections, expressed as offset in + * flash + */ + uint32_t fmap_location; + uint32_t hash_alg; /* one of enum vb2_hash_algorithm alg. */ + struct vb2_signature sig_header; + struct vb2_packed_key root_key_header; + /* + * SHAxxx(ranges[0].offset..ranges[0].size || ... || + * ranges[n].offset..ranges[n].size) + * + * Let the digest space allow to accommodate the largest possible one. + */ + uint8_t ranges_digest[VB2_SHA512_DIGEST_SIZE]; + uint32_t range_count; /* Number of gscvd_ro_range entries. */ + struct gscvd_ro_range ranges[0]; +}; + +#endif /* ! __VBOOT_REFERENCE_HOST_LIB_INCLUDE_GSC_RO_H */ diff -Nru vboot-utils-0~R88-13597.B/host/lib/include/host_common.h vboot-utils-0~R99-14469.B/host/lib/include/host_common.h --- vboot-utils-0~R88-13597.B/host/lib/include/host_common.h 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/include/host_common.h 2022-02-11 14:46:09.000000000 +0000 @@ -64,4 +64,18 @@ uint32_t desired_size, const struct vb2_private_key *signing_key); +/** + * Retrieve the 16-bit vmlinuz header address and size from the preamble. + * + * Size 0 means there is no 16-bit vmlinuz header present. Old preamble + * versions (<2.1) return 0 for both fields. + * + * @param preamble Preamble to check + * @param vmlinuz_header_address Destination for header address + * @param vmlinuz_header_size Destination for header size + */ +void vb2_kernel_get_vmlinuz_header(const struct vb2_kernel_preamble *preamble, + uint64_t *vmlinuz_header_address, + uint32_t *vmlinuz_header_size); + #endif /* VBOOT_REFERENCE_HOST_COMMON_H_ */ diff -Nru vboot-utils-0~R88-13597.B/host/lib/include/host_misc.h vboot-utils-0~R99-14469.B/host/lib/include/host_misc.h --- vboot-utils-0~R88-13597.B/host/lib/include/host_misc.h 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/include/host_misc.h 2022-02-11 14:46:09.000000000 +0000 @@ -9,6 +9,7 @@ #define VBOOT_REFERENCE_HOST_MISC_H_ #include "vboot_struct.h" +#include "vboot_api.h" /* Copy up to dest_size-1 characters from src to dest, ensuring null * termination (which strncpy() doesn't do). Returns the destination diff -Nru vboot-utils-0~R88-13597.B/host/lib/util_misc.c vboot-utils-0~R99-14469.B/host/lib/util_misc.c --- vboot-utils-0~R88-13597.B/host/lib/util_misc.c 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/host/lib/util_misc.c 2022-02-11 14:46:09.000000000 +0000 @@ -20,7 +20,6 @@ #include "host_key21.h" #include "openssl_compat.h" #include "util_misc.h" -#include "vb2_common.h" const char *packed_key_sha1_string(const struct vb2_packed_key *key) { diff -Nru vboot-utils-0~R88-13597.B/Makefile vboot-utils-0~R99-14469.B/Makefile --- vboot-utils-0~R88-13597.B/Makefile 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/Makefile 2022-02-11 14:46:09.000000000 +0000 @@ -56,6 +56,7 @@ # US_DIR = shared data directory (for static content like devkeys) # DF_DIR = utility defaults directory # VB_DIR = vboot binary directory for dev-mode-only scripts +# DUT_TEST_DIR = vboot dut tests binary directory UB_DIR=${DESTDIR}/usr/bin UL_DIR=${DESTDIR}/usr/${LIBDIR} ULP_DIR=${UL_DIR}/pkgconfig @@ -63,6 +64,7 @@ US_DIR=${DESTDIR}/usr/share/vboot DF_DIR=${DESTDIR}/etc/default VB_DIR=${US_DIR}/bin +DUT_TEST_DIR=${US_DIR}/tests # Where to install the (exportable) executables for testing? TEST_INSTALL_DIR = ${BUILD}/install_for_test @@ -71,12 +73,12 @@ SDK_BUILD ?= # Verbose? Use V=1 -ifeq (${V},) +ifeq ($(filter-out 0,${V}),) Q := @ endif # Quiet? Use QUIET=1 -ifeq (${QUIET},) +ifeq ($(filter-out 0,${QUIET}),) PRINTF := printf else PRINTF := : @@ -123,14 +125,14 @@ # Provide default CC and CFLAGS for firmware builds; if you have any -D flags, # please add them after this point (e.g., -DVBOOT_DEBUG). -DEBUG_FLAGS := $(if ${DEBUG},-g -O0,-g -Os) +DEBUG_FLAGS := $(if $(filter-out 0,${DEBUG}),-g -Og,-g -Os) WERROR := -Werror FIRMWARE_FLAGS := -nostdinc -ffreestanding -fno-builtin -fno-stack-protector COMMON_FLAGS := -pipe ${WERROR} -Wall -Wstrict-prototypes -Wtype-limits \ -Wundef -Wmissing-prototypes -Wno-trigraphs -Wredundant-decls -Wshadow \ - -Wwrite-strings -Wstrict-aliasing -Wdate-time -Wno-unknown-warning \ - -Wno-address-of-packed-member -ffunction-sections -fdata-sections \ - -Wimplicit-fallthrough -Wformat -Wno-format-security ${DEBUG_FLAGS} + -Wwrite-strings -Wstrict-aliasing -Wdate-time \ + -ffunction-sections -fdata-sections \ + -Wformat -Wno-format-security ${DEBUG_FLAGS} # FIRMWARE_ARCH is defined if compiling for a firmware target # (coreboot or depthcharge). @@ -153,30 +155,44 @@ CFLAGS += -DCHROMEOS_ENVIRONMENT ${COMMON_FLAGS} endif +CFLAGS += -std=gnu11 + +# test_ccflag +# $(1): compiler flags to test +# $(2): code to insert into test snippet +# returns: $(1) if compiler was successful, empty string otherwise +test_ccflag = $(shell \ + printf "$(2)\nvoid _start(void) {}\n" | \ + $(CC) -nostdlib -Werror $(1) -xc -c - -o /dev/null \ + >/dev/null 2>&1 && echo "$(1)") + +COMMON_FLAGS += $(call test_ccflag,-Wimplicit-fallthrough) +COMMON_FLAGS += $(call test_ccflag,-Wno-address-of-packed-member) +COMMON_FLAGS += $(call test_ccflag,-Wno-unknown-warning) + # Needs -Wl because LD is actually set to CC by default. LDFLAGS += -Wl,--gc-sections -ifneq (${DEBUG},) +ifneq ($(filter-out 0,${DEBUG})$(filter-out 0,${TEST_PRINT}),) CFLAGS += -DVBOOT_DEBUG endif -ifeq (${DISABLE_NDEBUG},) +ifeq ($(filter-out 0,${DISABLE_NDEBUG}),) CFLAGS += -DNDEBUG endif -ifneq (${FORCE_LOGGING_ON},) +ifneq ($(filter-out 0,${FORCE_LOGGING_ON}),) CFLAGS += -DFORCE_LOGGING_ON=${FORCE_LOGGING_ON} endif -ifneq (${TPM2_MODE},) +ifneq ($(filter-out 0,${TPM2_MODE}),) CFLAGS += -DTPM2_MODE endif -# Enable boot from external disk when switching to dev mode -ifneq ($(filter-out 0,${BOOT_EXTERNAL_ON_DEV}),) -CFLAGS += -DBOOT_EXTERNAL_ON_DEV=1 -else -CFLAGS += -DBOOT_EXTERNAL_ON_DEV=0 +# Support devices with GPT in SPI-NOR (for nand device) +# TODO(b:184812319): Consider removing this code if nobody uses it. +ifneq ($(filter-out 0,${GPT_SPI_NOR}),) +CFLAGS += -DGPT_SPI_NOR endif # Enable EC early firmware selection. @@ -187,7 +203,7 @@ endif # Some tests need to be disabled when using mocked_secdata_tpm. -ifneq (${MOCK_TPM},) +ifneq ($(filter-out 0,${MOCK_TPM}),) CFLAGS += -DMOCK_TPM endif @@ -198,43 +214,6 @@ CFLAGS += -DTPM2_SIMULATOR=0 endif -# DETACHABLE indicates whether the device is a detachable or not. -ifneq ($(filter-out 0,${DETACHABLE}),) -CFLAGS += -DDETACHABLE=1 -else -CFLAGS += -DDETACHABLE=0 -endif - -# Enable the menu-based user interface. -ifneq ($(filter-out 0,${MENU_UI}),) -CFLAGS += -DMENU_UI=1 -else -CFLAGS += -DMENU_UI=0 -endif - -# LEGACY_MENU_UI controls whether to enable legacy menu UI, which is used with -# devices that don't have a keyboard (detachables). -# Pass LEGACY_MENU_UI= (or =0) to make to disable feature. -ifneq ($(filter-out 0,${LEGACY_MENU_UI}),) -CFLAGS += -DLEGACY_MENU_UI=1 -else -CFLAGS += -DLEGACY_MENU_UI=0 -endif - -# pass DIAGNOSTIC_UI= (or =0) to make to disable feature -ifneq ($(filter-out 0,${DIAGNOSTIC_UI}),) -CFLAGS += -DDIAGNOSTIC_UI=1 -else -CFLAGS += -DDIAGNOSTIC_UI=0 -endif - -# Confirm physical presence using keyboard -ifneq ($(filter-out 0,${PHYSICAL_PRESENCE_KEYBOARD}),) -CFLAGS += -DPHYSICAL_PRESENCE_KEYBOARD=1 -else -CFLAGS += -DPHYSICAL_PRESENCE_KEYBOARD=0 -endif - # NOTE: We don't use these files but they are useful for other packages to # query about required compiling/linking flags. PC_IN_FILES = vboot_host.pc.in @@ -244,14 +223,20 @@ ifeq (${FIRMWARE_ARCH},) # Creates position independent code for non firmware target. -CFLAGS += -fPIE +CFLAGS += -fPIC endif -# These are required to access large disks and files on 32-bit systems. -CFLAGS += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 +CFLAGS += -D_GNU_SOURCE + +# This is required to access large disks and files on 32-bit systems, +# but if the environment doesn't support it, at least compile support +# for what is possible. +# Pass through cflags_use_64bits to evaluate it only once, here. +cflags_use_64bits := $(call test_ccflag,-D_FILE_OFFSET_BITS=64,\#include ) +CFLAGS += $(cflags_use_64bits) # Code coverage -ifneq (${COV},) +ifneq ($(filter-out 0,${COV}),) COV_FLAGS = -O0 --coverage -DCOVERAGE CFLAGS += ${COV_FLAGS} LDFLAGS += ${COV_FLAGS} @@ -273,7 +258,7 @@ PKG_CONFIG ?= pkg-config # Static? -ifneq (${STATIC},) +ifneq ($(filter-out 0,${STATIC}),) LDFLAGS += -static PKG_CONFIG += --static endif @@ -285,11 +270,17 @@ # Optional Libraries LIBZIP_VERSION := $(shell ${PKG_CONFIG} --modversion libzip 2>/dev/null) HAVE_LIBZIP := $(if ${LIBZIP_VERSION},1) -ifneq (${HAVE_LIBZIP},) +ifneq ($(filter-out 0,${HAVE_LIBZIP}),) CFLAGS += -DHAVE_LIBZIP $(shell ${PKG_CONFIG} --cflags libzip) LIBZIP_LIBS := $(shell ${PKG_CONFIG} --libs libzip) endif +HAVE_CROSID := $(shell ${PKG_CONFIG} --exists crosid && echo 1) +ifeq ($(HAVE_CROSID),1) + CFLAGS += -DHAVE_CROSID $(shell ${PKG_CONFIG} --cflags crosid) + CROSID_LIBS := $(shell ${PKG_CONFIG} --libs crosid) +endif + # Determine QEMU architecture needed, if any ifeq (${ARCH},${HOST_ARCH}) # Same architecture; no need for QEMU @@ -331,9 +322,9 @@ # Default target. .PHONY: all all: fwlib futil utillib hostlib cgpt tlcl \ - $(if ${SDK_BUILD},utils_sdk,utils_board) \ + $(if ${SDK_BUILD},${UTIL_FILES_SDK},${UTIL_FILES_BOARD}) \ $(if $(filter x86_64,${ARCH}),$(if $(filter clang,${CC}),fuzzers)) \ - $(if ${COV},coverage) + $(if $(filter-out 0,${COV}),coverage) ############################################################################## # Now we need to describe everything we might want or need to build @@ -353,6 +344,9 @@ ifeq (${FIRMWARE_ARCH},) INCLUDES += -Ihost/include -Ihost/lib/include INCLUDES += -Ihost/lib21/include +ifeq ($(shell uname -s), OpenBSD) +INCLUDES += -I/usr/local/include +endif endif # Firmware library, used by the other firmware components (depthcharge, @@ -371,11 +365,13 @@ firmware/2lib/2crc8.c \ firmware/2lib/2crypto.c \ firmware/2lib/2ec_sync.c \ + firmware/2lib/2firmware.c \ firmware/2lib/2gbb.c \ firmware/2lib/2hmac.c \ firmware/2lib/2kernel.c \ firmware/2lib/2misc.c \ firmware/2lib/2nvstorage.c \ + firmware/2lib/2packed_key.c \ firmware/2lib/2recovery_reasons.c \ firmware/2lib/2rsa.c \ firmware/2lib/2secdata_firmware.c \ @@ -385,28 +381,20 @@ firmware/2lib/2sha256.c \ firmware/2lib/2sha512.c \ firmware/2lib/2sha_utility.c \ + firmware/2lib/2struct.c \ firmware/2lib/2stub_hwcrypto.c \ firmware/2lib/2tpm_bootmode.c \ - firmware/2lib/2ui.c \ - firmware/2lib/2ui_screens.c \ firmware/lib/cgptlib/cgptlib.c \ firmware/lib/cgptlib/cgptlib_internal.c \ firmware/lib/cgptlib/crc32.c \ firmware/lib/gpt_misc.c \ firmware/lib/vboot_api_kernel.c \ - firmware/lib/vboot_audio.c \ firmware/lib/vboot_kernel.c \ - firmware/lib/vboot_ui_legacy.c \ - firmware/lib/vboot_ui_legacy_clamshell.c \ - firmware/lib/vboot_ui_legacy_menu.c \ - firmware/lib/vboot_ui_legacy_wilco.c \ firmware/lib20/api_kernel.c \ - firmware/lib20/kernel.c \ - firmware/lib20/misc.c \ - firmware/lib20/packed_key.c + firmware/lib20/kernel.c # TPM lightweight command library -ifeq (${TPM2_MODE},) +ifeq ($(filter-out 0,${TPM2_MODE}),) TLCL_SRCS = \ firmware/lib/tpm_lite/tlcl.c else @@ -417,18 +405,18 @@ endif # Support real TPM unless MOCK_TPM is set -ifneq (${MOCK_TPM},) +ifneq ($(filter-out 0,${MOCK_TPM}),) FWLIB_SRCS += \ firmware/lib/tpm_lite/mocked_tlcl.c endif -ifneq (${VENDOR_DATA_LENGTH},) -CFLAGS += -DVENDOR_DATA_LENGTH=${VENDOR_DATA_LENGTH} -else ifeq (${FIRMWARE_ARCH},) -CFLAGS += -DVENDOR_DATA_LENGTH=4 -else -CFLAGS += -DVENDOR_DATA_LENGTH=0 +ifneq ($(filter-out 0,${X86_SHA_EXT}),) +CFLAGS += -DX86_SHA_EXT +FWLIB_SRCS += \ + firmware/2lib/2sha256_x86.c endif +# Even if X86_SHA_EXT is 0 we need cflags since this will be compiled for tests +${BUILD}/firmware/2lib/2sha256_x86.o: CFLAGS += -mssse3 -mno-avx -msha ifeq (${FIRMWARE_ARCH},) # Include BIOS stubs in the firmware library when compiling for host @@ -437,7 +425,6 @@ firmware/stub/tpm_lite_stub.c \ firmware/stub/vboot_api_stub.c \ firmware/stub/vboot_api_stub_disk.c \ - firmware/stub/vboot_api_stub_init.c \ firmware/stub/vboot_api_stub_stream.c \ firmware/2lib/2stub.c endif @@ -446,6 +433,11 @@ TLCL_OBJS = ${TLCL_SRCS:%.c=${BUILD}/%.o} ALL_OBJS += ${FWLIB_OBJS} ${TLCL_OBJS} +COMMONLIB_SRCS = \ + host/lib/fmap.c \ + host/lib/flashrom.c \ + host/lib/subprocess.c + # Intermediate library for the vboot_reference utilities to link against. UTILLIB = ${BUILD}/libvboot_util.a @@ -464,8 +456,7 @@ host/lib/crossystem.c \ host/lib/crypto.c \ host/lib/file_keys.c \ - host/lib/flashrom.c \ - host/lib/fmap.c \ + $(COMMONLIB_SRCS) \ host/lib/host_common.c \ host/lib/host_key2.c \ host/lib/host_keyblock.c \ @@ -473,7 +464,6 @@ host/lib/host_signature.c \ host/lib/host_signature2.c \ host/lib/signature_digest.c \ - host/lib/subprocess.c \ host/lib/util_misc.c \ host/lib21/host_common.c \ host/lib21/host_key.c \ @@ -494,7 +484,6 @@ cgpt/cgpt_create.c \ cgpt/cgpt_edit.c \ cgpt/cgpt_find.c \ - cgpt/cgpt_nor.c \ cgpt/cgpt_prioritize.c \ cgpt/cgpt_show.c \ firmware/2lib/2common.c \ @@ -510,6 +499,7 @@ firmware/2lib/2sha256.c \ firmware/2lib/2sha512.c \ firmware/2lib/2sha_utility.c \ + firmware/2lib/2struct.c \ firmware/2lib/2stub.c \ firmware/2lib/2stub_hwcrypto.c \ firmware/lib/cgptlib/cgptlib_internal.c \ @@ -518,20 +508,21 @@ firmware/stub/tpm_lite_stub.c \ firmware/stub/vboot_api_stub.c \ firmware/stub/vboot_api_stub_disk.c \ - firmware/stub/vboot_api_stub_init.c \ futility/dump_kernel_config_lib.c \ $(CROSSYSTEM_ARCH_C) \ host/lib/chromeos_config.c \ host/lib/crossystem.c \ host/lib/crypto.c \ host/lib/extract_vmlinuz.c \ - host/lib/flashrom.c \ - host/lib/fmap.c \ + $(COMMONLIB_SRCS) \ host/lib/host_misc.c \ - host/lib/subprocess.c \ host/lib21/host_misc.c \ ${TLCL_SRCS} +ifneq ($(filter-out 0,${GPT_SPI_NOR}),) +HOSTLIB_SRCS += cgpt/cgpt_nor.c +endif + HOSTLIB_OBJS = ${HOSTLIB_SRCS:%.c=${BUILD}/%.o} ALL_OBJS += ${HOSTLIB_OBJS} @@ -549,7 +540,6 @@ cgpt/cgpt_edit.c \ cgpt/cgpt_find.c \ cgpt/cgpt_legacy.c \ - cgpt/cgpt_nor.c \ cgpt/cgpt_prioritize.c \ cgpt/cgpt_repair.c \ cgpt/cgpt_show.c \ @@ -563,6 +553,10 @@ cgpt/cmd_repair.c \ cgpt/cmd_show.c +ifneq ($(filter-out 0,${GPT_SPI_NOR}),) +CGPT_SRCS += cgpt/cgpt_nor.c +endif + CGPT_OBJS = ${CGPT_SRCS:%.c=${BUILD}/%.o} ALL_OBJS += ${CGPT_OBJS} @@ -581,27 +575,32 @@ UTIL_DEFAULTS = ${BUILD}/default/vboot_reference # Scripts to install directly (not compiled) -UTIL_SCRIPTS_SDK = \ +UTIL_SCRIPT_NAMES_SDK = \ utility/dev_make_keypair \ utility/vbutil_what_keys -UTIL_SCRIPTS_BOARD = \ +UTIL_SCRIPT_NAMES_BOARD = \ utility/chromeos-tpm-recovery \ utility/dev_debug_vboot \ utility/enable_dev_usb_boot \ utility/tpm-nvsize -UTIL_NAMES_SDK = \ +UTIL_BIN_NAMES_SDK = \ + utility/dumpRSAPublicKey \ utility/load_kernel_test \ utility/pad_digest_utility \ utility/signature_digest_utility \ utility/verify_data -UTIL_NAMES_BOARD = \ +UTIL_BIN_NAMES_BOARD = \ utility/crossystem \ utility/dumpRSAPublicKey \ utility/tpmc -UTIL_BINS_SDK = $(addprefix ${BUILD}/,${UTIL_NAMES_SDK}) -UTIL_BINS_BOARD = $(addprefix ${BUILD}/,${UTIL_NAMES_BOARD}) +UTIL_SCRIPTS_SDK = $(addprefix ${BUILD}/,${UTIL_SCRIPT_NAMES_SDK}) +UTIL_SCRIPTS_BOARD = $(addprefix ${BUILD}/,${UTIL_SCRIPT_NAMES_BOARD}) +UTIL_BINS_SDK = $(addprefix ${BUILD}/,${UTIL_BIN_NAMES_SDK}) +UTIL_BINS_BOARD = $(addprefix ${BUILD}/,${UTIL_BIN_NAMES_BOARD}) +UTIL_FILES_SDK = ${UTIL_BINS_SDK} ${UTIL_SCRIPTS_SDK} +UTIL_FILES_BOARD = ${UTIL_BINS_BOARD} ${UTIL_SCRIPTS_BOARD} ALL_OBJS += $(addsuffix .o,${UTIL_BINS_SDK}) ALL_OBJS += $(addsuffix .o,${UTIL_BINS_BOARD}) @@ -639,6 +638,7 @@ futility/cmd_dump_fmap.c \ futility/cmd_dump_kernel_config.c \ futility/cmd_gbb_utility.c \ + futility/cmd_gscvd.c \ futility/cmd_load_fmap.c \ futility/cmd_pcr.c \ futility/cmd_show.c \ @@ -648,21 +648,29 @@ futility/cmd_vbutil_firmware.c \ futility/cmd_vbutil_firmware.c \ futility/cmd_vbutil_kernel.c \ - futility/cmd_vbutil_keyblock.c \ - futility/cmd_vbutil_key.c \ futility/cmd_vbutil_key.c \ + futility/cmd_vbutil_keyblock.c \ futility/file_type_bios.c \ futility/file_type.c \ futility/file_type_rwsig.c \ futility/file_type_usbpd1.c \ futility/misc.c \ - futility/ryu_root_header.c \ - futility/updater.c \ + futility/vb1_helper.c \ + futility/vb2_helper.c + +# Maintain behaviour of default on. +USE_FLASHROM ?= 1 + +ifneq ($(filter-out 0,${USE_FLASHROM}),) +$(info building with libflashrom support) +FLASHROM_LIBS := $(shell ${PKG_CONFIG} --libs flashrom) +FUTIL_SRCS += futility/flashrom_drv.c \ futility/updater_archive.c \ futility/updater_quirks.c \ futility/updater_utils.c \ - futility/vb1_helper.c \ - futility/vb2_helper.c + futility/updater.c +CFLAGS += -DUSE_FLASHROM +endif # List of commands built in futility. FUTIL_CMD_LIST = ${BUILD}/gen/futility_cmds.c @@ -677,7 +685,7 @@ # Library of handy test functions. TESTLIB = ${BUILD}/tests/test.a -TESTLIB_SRCS = \ +TESTLIB_SRCS += \ tests/test_common.c \ tests/timer_utils.c \ tests/crc32_test.c @@ -690,18 +698,16 @@ TEST_NAMES = \ tests/cgptlib_test \ tests/chromeos_config_tests \ + tests/gpt_misc_tests \ tests/sha_benchmark \ tests/subprocess_tests \ tests/vboot_api_kernel4_tests \ tests/vboot_api_kernel_tests \ tests/vboot_kernel_tests \ - tests/vboot_ui_legacy_clamshell_beep_tests \ - tests/vboot_ui_legacy_clamshell_tests \ - tests/vboot_ui_legacy_menu_tests \ - tests/vboot_ui_legacy_tests \ + tests/vboot_kernel2_tests \ tests/verify_kernel -ifeq (${MOCK_TPM}${TPM2_MODE},) +ifeq ($(filter-out 0,${MOCK_TPM})$(filter-out 0,${TPM2_MODE}),) # tlcl_tests only works when MOCK_TPM is disabled # TODO(apronin): tests for TPM2 case? TEST_NAMES += \ @@ -723,6 +729,7 @@ tests/vb2_common3_tests \ tests/vb2_crypto_tests \ tests/vb2_ec_sync_tests \ + tests/vb2_firmware_tests \ tests/vb2_gbb_tests \ tests/vb2_host_flashrom_tests \ tests/vb2_host_key_tests \ @@ -737,16 +744,12 @@ tests/vb2_secdata_kernel_tests \ tests/vb2_sha_api_tests \ tests/vb2_sha_tests \ - tests/vb2_ui_tests \ - tests/vb2_ui_action_tests \ - tests/vb2_ui_utility_tests \ tests/hmac_test TEST20_NAMES = \ tests/vb20_api_kernel_tests \ tests/vb20_verify_fw.c \ tests/vb20_kernel_tests \ - tests/vb20_misc_tests \ tests/vb20_rsa_padding_tests \ tests/vb20_verify_fw @@ -759,8 +762,15 @@ TEST_NAMES += ${TEST2X_NAMES} ${TEST20_NAMES} ${TEST21_NAMES} +# Tests which should be run on dut +ifeq (${ARCH}, x86_64) +DUT_TEST_NAMES += tests/vb2_sha256_x86_tests +endif + +TEST_NAMES += ${DUT_TEST_NAMES} + # And a few more... -ifeq (${TPM2_MODE},) +ifeq ($(filter-out 0,${TPM2_MODE}),) TLCL_TEST_NAMES = \ tests/tpm_lite/tpmtest_earlyextend \ tests/tpm_lite/tpmtest_earlynvram \ @@ -818,7 +828,9 @@ .PHONY: install install: cgpt_install signing_install futil_install pc_files_install \ - lib_install $(if ${SDK_BUILD},utils_install_sdk,utils_install_board) + lib_install $(if ${SDK_BUILD},,util_install_defaults) \ + $(foreach f,$(if ${SDK_BUILD},${UTIL_FILES_SDK},${UTIL_FILES_BOARD}), \ + util_install-$(patsubst ${BUILD}/%,%,${f})) .PHONY: install_dev install_dev: devkeys_install headers_install @@ -828,8 +840,9 @@ .PHONY: install_for_test install_for_test: override DESTDIR = ${TEST_INSTALL_DIR} -install_for_test: test_setup -install_for_test: install utils_install_sdk utils_install_board +install_for_test: test_setup install \ + $(foreach f,${UTIL_FILES_SDK} ${UTIL_FILES_BOARD}, \ + util_install-$(patsubst ${BUILD}/%,%,${f})) # Don't delete intermediate object files .SECONDARY: @@ -949,10 +962,12 @@ ${Q}${LD} -o ${CGPT_WRAPPER} ${LDFLAGS} $^ ${LDLIBS} .PHONY: cgpt -cgpt: ${CGPT} ${CGPT_WRAPPER} +cgpt: ${CGPT} $(if $(filter-out 0,${GPT_SPI_NOR}),cgpt_wrapper) # on FreeBSD: install misc/e2fsprogs-libuuid from ports, # or e2fsprogs-libuuid from its binary package system. +# on OpenBSD: install sysutils/e2fsprogs from ports, +# or e2fsprogs from its binary package system, to install uuid/uid.h ${CGPT}: LDLIBS += -luuid ${CGPT}: ${CGPT_OBJS} ${UTILLIB} @@ -985,27 +1000,23 @@ ${UTIL_BINS_BOARD}: ${UTILLIB} ${UTIL_BINS_BOARD}: LIBS = ${UTILLIB} -.PHONY: utils_sdk -utils_sdk: ${UTIL_BINS_SDK} ${UTIL_SCRIPTS_SDK} - ${Q}cp -f ${UTIL_SCRIPTS_SDK} ${BUILD}/utility - ${Q}chmod a+rx $(patsubst %,${BUILD}/%,${UTIL_SCRIPTS_SDK}) - -.PHONY: utils_board -utils_board: ${UTIL_BINS_BOARD} ${UTIL_SCRIPTS_BOARD} - ${Q}cp -f ${UTIL_SCRIPTS_BOARD} ${BUILD}/utility - ${Q}chmod a+rx $(patsubst %,${BUILD}/%,${UTIL_SCRIPTS_BOARD}) - -.PHONY: utils_install_sdk -utils_install_sdk: utils_sdk - @${PRINTF} " INSTALL UTILS\n" - ${Q}mkdir -p ${UB_DIR} - ${Q}${INSTALL} -t ${UB_DIR} ${UTIL_BINS_SDK} ${UTIL_SCRIPTS_SDK} +${UTIL_SCRIPTS_SDK} ${UTIL_SCRIPTS_BOARD}: ${BUILD}/%: % + ${Q}cp -f $< $@ + ${Q}chmod a+rx $@ + +define UTIL_INSTALL_template +.PHONY: util_install-$(1) +util_install-$(1): $$(addprefix $${BUILD}/,$(1)) + @${PRINTF} " INSTALL $(1)\n" + ${Q}mkdir -p $${UB_DIR} + ${Q}${INSTALL} -t $${UB_DIR} $$< +endef -.PHONY: utils_install_board -utils_install_board: utils_board ${UTIL_DEFAULTS} - @${PRINTF} " INSTALL UTILS\n" - ${Q}mkdir -p ${UB_DIR} - ${Q}${INSTALL} -t ${UB_DIR} ${UTIL_BINS_BOARD} ${UTIL_SCRIPTS_BOARD} +$(foreach f, $(sort ${UTIL_FILES_SDK} ${UTIL_FILES_BOARD}), \ + $(eval $(call UTIL_INSTALL_template,$(patsubst ${BUILD}/%,%,${f})))) + +.PHONY: util_install_defaults +util_install_defaults: ${UTIL_DEFAULTS} ${Q}mkdir -p ${DF_DIR} ${Q}${INSTALL} -t ${DF_DIR} -m 'u=rw,go=r,a-s' ${UTIL_DEFAULTS} @@ -1024,7 +1035,7 @@ futil: ${FUTIL_BIN} # FUTIL_LIBS is shared by FUTIL_BIN and TEST_FUTIL_BINS. -FUTIL_LIBS = ${CRYPTO_LIBS} ${LIBZIP_LIBS} +FUTIL_LIBS = ${CROSID_LIBS} ${CRYPTO_LIBS} ${LIBZIP_LIBS} ${FLASHROM_LIBS} ${FUTIL_BIN}: LDLIBS += ${FUTIL_LIBS} ${FUTIL_BIN}: ${FUTIL_OBJS} ${UTILLIB} ${FWLIB} @@ -1084,6 +1095,22 @@ @${PRINTF} " AR $(subst ${BUILD}/,,$@)\n" ${Q}ar qc $@ $^ +DUT_TEST_BINS = $(addprefix ${BUILD}/,${DUT_TEST_NAMES}) + +# Special build for sha256_x86 test +${BUILD}/tests/vb2_sha256_x86_tests: \ + ${BUILD}/firmware/2lib/2sha256_x86.o +${BUILD}/tests/vb2_sha256_x86_tests: \ + LIBS += ${BUILD}/firmware/2lib/2sha256_x86.o + +.PHONY: install_dut_test +install_dut_test: ${DUT_TEST_BINS} +ifneq ($(strip ${DUT_TEST_BINS}),) + @${PRINTF} " INSTALL DUT TESTS\n" + ${Q}mkdir -p ${DUT_TEST_DIR} + ${Q}${INSTALL} -t ${DUT_TEST_DIR} $^ +endif + # ---------------------------------------------------------------------------- # Fuzzers @@ -1128,6 +1155,9 @@ ifeq ($(shell uname -s), FreeBSD) CRYPTO_LIBS += -lcrypto endif +ifeq ($(shell uname -s), OpenBSD) +LDFLAGS += -Wl,-z,notext +endif ${BUILD}/utility/dumpRSAPublicKey: LDLIBS += ${CRYPTO_LIBS} ${BUILD}/utility/pad_digest_utility: LDLIBS += ${CRYPTO_LIBS} @@ -1147,7 +1177,7 @@ ${BUILD}/tests/%: LDLIBS += -lrt -luuid ${BUILD}/tests/%: LIBS += ${TESTLIB} -ifeq (${TPM2_MODE},) +ifeq ($(filter-out 0,${TPM2_MODE}),) # TODO(apronin): tests for TPM2 case? TLCL_TEST_BINS = $(addprefix ${BUILD}/,${TLCL_TEST_NAMES}) ${TLCL_TEST_BINS}: OBJS += ${BUILD}/tests/tpm_lite/tlcl_tests.o @@ -1184,7 +1214,7 @@ # Targets that exist just to run tests .PHONY: test_setup -test_setup:: cgpt utils_sdk utils_board futil tests +test_setup:: cgpt ${UTIL_FILES_SDK} ${UTIL_FILES_BOARD} futil tests # Qemu setup for cross-compiled tests. Need to copy qemu binary into the # sysroot. @@ -1235,18 +1265,16 @@ .PHONY: runmisctests runmisctests: install_for_test + ${RUNTEST} ${BUILD_RUN}/tests/gpt_misc_tests ${RUNTEST} ${BUILD_RUN}/tests/subprocess_tests -ifeq (${MOCK_TPM}${TPM2_MODE},) +ifeq ($(filter-out 0,${MOCK_TPM})$(filter-out 0,${TPM2_MODE}),) # tlcl_tests only works when MOCK_TPM is disabled ${RUNTEST} ${BUILD_RUN}/tests/tlcl_tests endif ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel4_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_api_kernel_tests ${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel_tests - ${RUNTEST} ${BUILD_RUN}/tests/vboot_ui_legacy_clamshell_beep_tests - ${RUNTEST} ${BUILD_RUN}/tests/vboot_ui_legacy_clamshell_tests - ${RUNTEST} ${BUILD_RUN}/tests/vboot_ui_legacy_menu_tests - ${RUNTEST} ${BUILD_RUN}/tests/vboot_ui_legacy_tests + ${RUNTEST} ${BUILD_RUN}/tests/vboot_kernel2_tests .PHONY: run2tests run2tests: install_for_test @@ -1257,6 +1285,7 @@ ${RUNTEST} ${BUILD_RUN}/tests/vb2_common3_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb2_crypto_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_ec_sync_tests + ${RUNTEST} ${BUILD_RUN}/tests/vb2_firmware_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_gbb_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_host_key_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_kernel_tests @@ -1268,12 +1297,8 @@ ${RUNTEST} ${BUILD_RUN}/tests/vb2_secdata_kernel_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_sha_api_tests ${RUNTEST} ${BUILD_RUN}/tests/vb2_sha_tests - ${RUNTEST} ${BUILD_RUN}/tests/vb2_ui_tests - ${RUNTEST} ${BUILD_RUN}/tests/vb2_ui_action_tests - ${RUNTEST} ${BUILD_RUN}/tests/vb2_ui_utility_tests ${RUNTEST} ${BUILD_RUN}/tests/vb20_api_kernel_tests ${RUNTEST} ${BUILD_RUN}/tests/vb20_kernel_tests - ${RUNTEST} ${BUILD_RUN}/tests/vb20_misc_tests ${RUNTEST} ${BUILD_RUN}/tests/vb21_host_common_tests ${RUNTEST} ${BUILD_RUN}/tests/vb21_host_common2_tests ${TEST_KEYS} ${RUNTEST} ${BUILD_RUN}/tests/vb21_host_key_tests ${TEST_KEYS} ${BUILD} @@ -1326,7 +1351,7 @@ -o ${COV_INFO}.firmware .PHONY: coverage -ifeq (${COV},) +ifeq ($(filter-out 0,${COV}),) coverage: $(error Build coverage like this: make clean && COV=1 make coverage) else diff -Nru vboot-utils-0~R88-13597.B/OWNERS vboot-utils-0~R99-14469.B/OWNERS --- vboot-utils-0~R88-13597.B/OWNERS 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/OWNERS 2022-02-11 14:46:09.000000000 +0000 @@ -1,4 +1,5 @@ -kitching@chromium.org jwerner@chromium.org -rspangler@chromium.org +yupingso@chromium.org +twawrzynczak@chromium.org +hungte@chromium.org * diff -Nru vboot-utils-0~R88-13597.B/PRESUBMIT.cfg vboot-utils-0~R99-14469.B/PRESUBMIT.cfg --- vboot-utils-0~R88-13597.B/PRESUBMIT.cfg 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/PRESUBMIT.cfg 2022-02-11 14:46:09.000000000 +0000 @@ -1,8 +1,16 @@ [Hook Overrides] branch_check: true +cargo_clippy_check: true +checkpatch_check: true +long_line_check: false signoff_check: true # We are using Linux style indentation with tabs # The indentation is checked by checkpatch not the python script tab_check: false +[Hook Overrides Options] +cros_license_check: --exclude_regex=^\.checkpatch\.conf$ + +cargo_clippy_check: + --project=rust/vboot_reference-sys diff -Nru vboot-utils-0~R88-13597.B/README vboot-utils-0~R99-14469.B/README --- vboot-utils-0~R88-13597.B/README 2020-12-01 09:49:26.000000000 +0000 +++ vboot-utils-0~R99-14469.B/README 2022-02-11 14:46:09.000000000 +0000 @@ -48,6 +48,9 @@ Tools and scripts used to generate and use new signing keypairs. These are typically used only on a secure machine. +rust/ + + Rust bindings for vboot_reference. See rust/README.md for more details. -------------------- Building and testing diff -Nru vboot-utils-0~R88-13597.B/rust/OWNERS vboot-utils-0~R99-14469.B/rust/OWNERS --- vboot-utils-0~R88-13597.B/rust/OWNERS 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/rust/OWNERS 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1 @@ +allenwebb@chromium.org diff -Nru vboot-utils-0~R88-13597.B/rust/README.md vboot-utils-0~R99-14469.B/rust/README.md --- vboot-utils-0~R88-13597.B/rust/README.md 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/rust/README.md 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,18 @@ +# Rust bindings for vboot_reference + +This path contains the vboot_reference-sys crate which uses bindgen to generate +Rust bindings for the vboot_reference C library. + +Each header is included as its own submodule. To use these bindings: + * Add `vboot_reference-sys` to your `Cargo.toml` for example: +```toml +[dependencies] +vboot_reference-sys = { path = "../../vboot_reference/rust/vboot_reference-sys" } +``` + * Include the symbols you need for example: +```rust +use vboot_reference_sys::crossystem::*; +``` + +The `build.rs` in `vboot_reference-sys` takes care of adding the necessary +includes and linker flags for `vboot_host` through the `pkg-config` crate. diff -Nru vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/build.rs vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/build.rs --- vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/build.rs 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/build.rs 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,54 @@ +// Copyright 2019 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. + +/// Minijail's build script invoked by cargo. +/// +/// This script prefers linking against a pkg-config provided libminijail, but will fall back to +/// building libminijail statically. +use std::env; +use std::fs::remove_file; +use std::io; +use std::path::Path; +use std::process::Command; + +fn bindings_generation() -> io::Result<()> { + let bindgen = which::which("bindgen").unwrap(); + + let out_dir = env::var("OUT_DIR").unwrap(); + let gen_file = Path::new(&out_dir).join("./crossystem.rs"); + if gen_file.exists() { + remove_file(&gen_file).expect("Failed to remove generated file."); + } + let header_dir = Path::new("."); + let header_path = header_dir.join("crossystem.h"); + println!("cargo:rerun-if-changed={}", header_path.display()); + let status = Command::new(&bindgen) + .args(&["--default-enum-style", "rust"]) + .args(&["--blacklist-type", "__rlim64_t"]) + .args(&["--raw-line", "pub type __rlim64_t = u64;"]) + .args(&["--blacklist-type", "__u\\d{1,2}"]) + .args(&["--raw-line", "pub type __u8 = u8;"]) + .args(&["--raw-line", "pub type __u16 = u16;"]) + .args(&["--raw-line", "pub type __u32 = u32;"]) + .args(&["--blacklist-type", "__uint64_t"]) + .arg("--no-layout-tests") + .arg("--disable-header-comment") + .args(&["--output", gen_file.to_str().unwrap()]) + .arg(header_path.to_str().unwrap()) + .args(&[ + "--", + "-DUSE_BINDGEN", + "-D_FILE_OFFSET_BITS=64", + "-D_LARGEFILE_SOURCE", + "-D_LARGEFILE64_SOURCE", + ]) + .status()?; + assert!(status.success()); + Ok(()) +} + +fn main() -> io::Result<()> { + pkg_config::Config::new().probe("vboot_host").unwrap(); + bindings_generation() +} diff -Nru vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/Cargo.toml vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/Cargo.toml --- vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/Cargo.toml 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/Cargo.toml 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,17 @@ +[package] +name = "vboot_reference-sys" +version = "1.0.0" +description = "Provides raw (unsafe) bindings to the vboot_reference C library." +authors = ["The Chromium OS Authors"] +edition = "2018" +build = "build.rs" + +[lib] +path = "lib.rs" + +[dependencies] +libc = "0.2.44" + +[build-dependencies] +pkg-config = "0.3" +which = "4.0.0" diff -Nru vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/crossystem.h vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/crossystem.h --- vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/crossystem.h 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/crossystem.h 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,52 @@ +/* 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. + */ + +#ifndef VBOOT_REFERENCE_CROSSYSTEM_H_ +#define VBOOT_REFERENCE_CROSSYSTEM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Recommended size for string property buffers used with + * VbGetSystemPropertyString(). */ +#define VB_MAX_STRING_PROPERTY ((size_t) 8192) + +/* Reads a system property integer. + * + * Returns the property value, or -1 if error. */ +int VbGetSystemPropertyInt(const char* name); + +/* Read a system property string into a destination buffer of the + * specified size. Returned string will be null-terminated. If the + * buffer is too small, the returned string will be truncated. + * + * The caller can expect an un-truncated value if the size provided is + * at least VB_MAX_STRING_PROPERTY. + * + * Returns the passed buffer, or NULL if error. */ +const char* VbGetSystemPropertyString(const char* name, char* dest, + size_t size); + +/* Sets a system property integer. + * + * Returns 0 if success, -1 if error. */ +int VbSetSystemPropertyInt(const char* name, int value); + +/* Set a system property string. + * + * The maximum length of the value accepted depends on the specific + * property, not on VB_MAX_STRING_PROPERTY. + * + * Returns 0 if success, -1 if error. */ +int VbSetSystemPropertyString(const char* name, const char* value); + +#ifdef __cplusplus +} +#endif + +#endif /* VBOOT_REFERENCE_CROSSYSTEM_H_ */ diff -Nru vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/lib.rs vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/lib.rs --- vboot-utils-0~R88-13597.B/rust/vboot_reference-sys/lib.rs 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/rust/vboot_reference-sys/lib.rs 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,15 @@ +// Copyright 2022 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. + +/// vboot_reference bindings for Rust. + +#[allow( + clippy::all, + non_camel_case_types, + non_snake_case, + non_upper_case_globals +)] +pub mod crossystem { + include!(concat!(env!("OUT_DIR"), "/crossystem.rs")); +} diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/common.sh vboot-utils-0~R99-14469.B/scripts/image_signing/common.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/common.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/common.sh 2022-02-11 14:46:09.000000000 +0000 @@ -10,25 +10,6 @@ . "$(dirname "$0")/common_minimal.sh" CROS_LOG_PREFIX="${PROG}: " -# Array of actions that are executed during the clean up process. -declare -a cleanup_actions - -# Adds an action to be executed during the clean up process. -# Actions are executed in the reverse order of when they were added. -# ARGS: ACTION -add_cleanup_action() { - cleanup_actions[${#cleanup_actions[*]}]=$1 -} - -# Performs the latest clean up action and removes it from the list. -perform_latest_cleanup_action() { - local num_actions=${#cleanup_actions[*]} - if [ "${num_actions}" -gt 0 ]; then - eval "${cleanup_actions[$num_actions-1]} || true" > /dev/null 2>&1 - unset "cleanup_actions[$num_actions-1]" - fi -} - # Performs clean up by executing actions in the cleanup_actions array in # reversed order. cleanup() { @@ -36,9 +17,8 @@ rv=$? set +e - while [ ${#cleanup_actions[*]} -gt 0 ]; do - perform_latest_cleanup_action - done + cleanup_temps_and_mounts + cleanup_loopbacks set -e return $rv @@ -158,6 +138,3 @@ # This will override the trap set in common_minmal.sh trap "cleanup" INT TERM EXIT - -add_cleanup_action "cleanup_temps_and_mounts" -add_cleanup_action "cleanup_loopbacks" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_no_nonrelease_files.sh vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_no_nonrelease_files.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_no_nonrelease_files.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_no_nonrelease_files.sh 2022-02-11 14:46:09.000000000 +0000 @@ -37,9 +37,14 @@ # Either way, load test-expectations data from config. . "${configfile}" || return 1 - local loopdev=$(loopback_partscan "${image}") - local rootfs=$(make_temp_dir) - mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" + local loopdev rootfs + if [[ -d "${image}" ]]; then + rootfs="${image}" + else + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") + mount_loop_image_partition "${loopdev}" 3 "${rootfs}" + fi # Pick the right set of test-expectation data to use. local brdvar=$(get_boardvar_from_lsb_release "${rootfs}") eval "release_file_blocklist=(\"\${RELEASE_FILE_BLOCKLIST_${brdvar}[@]}\")" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_not_ASAN.sh vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_not_ASAN.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_not_ASAN.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_not_ASAN.sh 2022-02-11 14:46:09.000000000 +0000 @@ -11,26 +11,31 @@ . "$(dirname "$0")/common.sh" usage() { - echo "Usage $PROG image" + echo "Usage $PROG image" } main() { - if [ $# -ne 1 ]; then - usage - exit 1 - fi + if [[ $# -ne 1 ]]; then + usage + exit 1 + fi - local image="$1" + local image="$1" - local loopdev=$(loopback_partscan "${image}") - local rootfs=$(make_temp_dir) + local loopdev rootfs + if [[ -d "${image}" ]]; then + rootfs="${image}" + else + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" + fi - # This mirrors the check performed in the platform_ToolchainOptions - # autotest. - if readelf -s "$rootfs/opt/google/chrome/chrome" | \ - grep -q __asan_init; then - exit 1 - fi + # This mirrors the check performed in the platform_ToolchainOptions + # autotest. + if readelf -s "$rootfs/opt/google/chrome/chrome" | \ + grep -q __asan_init; then + exit 1 + fi } main "$@" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_not_tainted_license.sh vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_not_tainted_license.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_not_tainted_license.sh 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_not_tainted_license.sh 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,71 @@ +#!/bin/bash +# +# Copyright 2020 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 script ensures absence of a tag in image's license. + +# Abort on error. +set -e + +# Load common constants and variables. +. "$(dirname "$0")/common.sh" + +usage() { + echo "Usage ${PROG} image" +} + +main() { + if [[ $# -ne 1 ]]; then + usage + exit 1 + fi + + local image="$1" + + local loopdev rootfs + if [[ -d "${image}" ]]; then + rootfs="${image}" + else + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") + mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" + fi + + local license_dir license tainted_tag tainted_status + license_dir="${rootfs}/opt/google/chrome/" + if [[ ! -d "${license_dir}" ]]; then + echo "Directory ${license_dir} does not exist. Skipping the tainted check." + exit 0 + fi + + license=$(find "${license_dir}" -name about_os_credits.html 2>/dev/null) + if [[ -z "${license}" ]]; then + echo "License file about_os_credits.html not found in ${license_dir}." + echo "Skipping the check of tainted license." + exit 0 + fi + + tainted_tag="" + # Add "|| :" to the grep command to prevent it from returning error code 1 if + # no match is found, which would cause the script to exit immediately with + # error code 1 due to set -e. + tainted_status=$(grep "${tainted_tag}" "${license}") || : + if [[ -n "${tainted_status}" ]]; then + echo "${license}:" + echo "License file contains packages with LICENSE=TAINTED." + echo "Remove those packages or modify their license to allow signing." + # Print the list of tainted packages. + sed -n '/Image is TAINTED/,/<\/ul>/{ + # Strip out HTML tags. + s/<[^>]*>//g + # Delete any empty lines. + /^[[:space:]]*$/d + p + }' "${license}" + exit 1 + fi + exit 0 +} +main "$@" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_secure_kernelparams.sh vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_secure_kernelparams.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_secure_kernelparams.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_secure_kernelparams.sh 2022-02-11 14:46:09.000000000 +0000 @@ -100,9 +100,8 @@ # which is the install kernel on the recovery image. # crosbug.com/24274 local loop_kern="${loopdev}p4" - local loop_rootfs="${loopdev}p3" local rootfs=$(make_temp_dir) - sudo mount -o ro "${loop_rootfs}" "${rootfs}" + mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" # Pick the right set of test-expectation data to use. local boardvar=$(get_boardvar_from_lsb_release "${rootfs}") diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_update_verification.sh vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_update_verification.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/ensure_update_verification.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/ensure_update_verification.sh 2022-02-11 14:46:09.000000000 +0000 @@ -23,10 +23,16 @@ fi local image=$1 - local loopdev=$(loopback_partscan "${image}") - local rootfs=$(make_temp_dir) + + local loopdev rootfs + if [[ -d "${image}" ]]; then + rootfs="${image}" + else + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") + mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" + fi local key_location="/usr/share/update_engine/update-payload-key.pub.pem" - mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" if [ ! -e "$rootfs/$key_location" ]; then die "Update payload verification key not found at $key_location" fi diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/gbb_flags_common.sh vboot-utils-0~R99-14469.B/scripts/image_signing/gbb_flags_common.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/gbb_flags_common.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/gbb_flags_common.sh 2022-02-11 14:46:09.000000000 +0000 @@ -26,10 +26,10 @@ VB2_GBB_FLAG_FORCE_DEV_BOOT_USB 0x00000010 VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK 0x00000020 VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM 0x00000040 - VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY 0x00000080 + VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW 0x00000080 VB2_GBB_FLAG_RUNNING_FAFT 0x00000100 VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC 0x00000200 - VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY 0x00000400 + VB2_GBB_FLAG_DEFAULT_DEV_BOOT_ALTFW 0x00000400 VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC 0x00000800 VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN 0x00001000 VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY 0x00004000 @@ -55,5 +55,5 @@ } flashrom_write() { - flashrom -p host -i GBB --fast-verify -w "$@" + flashrom -p host -i GBB --noverify-all -w "$@" } diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/insert_au_publickey.sh vboot-utils-0~R99-14469.B/scripts/image_signing/insert_au_publickey.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/insert_au_publickey.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/insert_au_publickey.sh 2022-02-11 14:46:09.000000000 +0000 @@ -21,10 +21,17 @@ EOF exit 1 fi - local loopdev=$(loopback_partscan "${image}") - local rootfs=$(make_temp_dir) + + local loopdev rootfs + if [[ -d "${image}" ]]; then + rootfs="${image}" + else + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") + mount_loop_image_partition "${loopdev}" 3 "${rootfs}" + fi + local key_location="/usr/share/update_engine/" - mount_loop_image_partition "${loopdev}" 3 "${rootfs}" sudo mkdir -p "$rootfs/$key_location" sudo cp "$pub_key" "$rootfs/$key_location/update-payload-key.pub.pem" sudo chown root:root "$rootfs/$key_location/update-payload-key.pub.pem" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/make_dev_ssd.sh vboot-utils-0~R99-14469.B/scripts/image_signing/make_dev_ssd.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/make_dev_ssd.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/make_dev_ssd.sh 2022-02-11 14:46:09.000000000 +0000 @@ -35,7 +35,15 @@ DEFINE_string image "$ROOTDEV_DISK" "Path to device or image file" "i" DEFINE_string keys "$DEFAULT_KEYS_FOLDER" "Path to folder of dev keys" "k" DEFINE_boolean remove_rootfs_verification \ - $FLAGS_FALSE "Modify kernel boot config to disable rootfs verification" "" + "${FLAGS_FALSE}" "Modify kernel boot config to disable rootfs verification" "" +DEFINE_boolean enable_earlycon "${FLAGS_FALSE}" \ + "Enable earlycon from stdout-path (ARM/ARM64) or SPCR (x86)." "" +DEFINE_boolean disable_earlycon "${FLAGS_FALSE}" \ + "Disable earlycon." "" +DEFINE_boolean enable_console "${FLAGS_FALSE}" \ + "Enable serial console." "" +DEFINE_boolean disable_console "${FLAGS_FALSE}" \ + "Disable serial console." "" DEFINE_string backup_dir \ "$DEFAULT_BACKUP_FOLDER" "Path of directory to store kernel backups" "" DEFINE_string save_config "" \ @@ -106,6 +114,28 @@ sudo umount "$mount_point" } +# Enable/Disable earlycon or serial console +insert_parameter() { + local cmdline="$1" + local param="$2" + + if [ -n "${cmdline##*${param}*}" ]; then + cmdline="${param} ${cmdline}" + fi + + echo "${cmdline}" +} + +remove_parameter() { + local cmdline="$1" + local param="$2" + + cmdline=$(echo "${cmdline}" | sed ' + s/'"${param} "'//g') + + echo "${cmdline}" +} + # Wrapped version of dd mydd() { # oflag=sync is safer, but since we need bs=512, syncing every block would be @@ -244,6 +274,26 @@ remove_legacy_boot_rootfs_verification "$ssd_device" fi + if [ "${FLAGS_enable_earlycon}" = "${FLAGS_TRUE}" ]; then + debug_msg "Enabling earlycon" + kernel_config="$(insert_parameter "${kernel_config}" "earlycon")" + debug_msg "New kernel config: ${kernel_config}" + elif [ "${FLAGS_disable_earlycon}" = "${FLAGS_TRUE}" ]; then + debug_msg "Disabling earlycon" + kernel_config="$(remove_parameter "${kernel_config}" "earlycon")" + debug_msg "New kernel config: ${kernel_config}" + fi + + if [ "${FLAGS_enable_console}" = "${FLAGS_TRUE}" ]; then + debug_msg "Enabling serial console" + kernel_config="$(remove_parameter "${kernel_config}" "console=")" + debug_msg "New kernel config: ${kernel_config}" + elif [ "${FLAGS_disable_console}" = "${FLAGS_TRUE}" ]; then + debug_msg "Disabling serial console" + kernel_config="$(insert_parameter "${kernel_config}" "console=")" + debug_msg "New kernel config: ${kernel_config}" + fi + local new_kernel_config_file="$(make_temp_file)" echo -n "$kernel_config" >"$new_kernel_config_file" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/set_channel.sh vboot-utils-0~R99-14469.B/scripts/image_signing/set_channel.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/set_channel.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/set_channel.sh 2022-02-11 14:46:09.000000000 +0000 @@ -26,10 +26,14 @@ local to=$2 local loopdev rootfs lsb - loopdev=$(loopback_partscan "${image}") - rootfs=$(make_temp_dir) + if [[ -d "${image}" ]]; then + rootfs="${image}" + else + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") + mount_loop_image_partition "${loopdev}" 3 "${rootfs}" + fi lsb="${rootfs}/etc/lsb-release" - mount_loop_image_partition "${loopdev}" 3 "${rootfs}" # Get the current channel on the image. local from=$(lsbval "${lsb}" 'CHROMEOS_RELEASE_TRACK') from=${from%"-channel"} diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/set_lsb_release.sh vboot-utils-0~R99-14469.B/scripts/image_signing/set_lsb_release.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/set_lsb_release.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/set_lsb_release.sh 2022-02-11 14:46:09.000000000 +0000 @@ -11,15 +11,17 @@ set_lsb_release_keyval() { local rootfs=$1 + local lsb="${rootfs}/etc/lsb-release" local key=$2 local value=$3 - local temp_lsb_release="$rootfs/etc/temp-lsb-release" - echo "$key=$value" | sudo tee "$temp_lsb_release" > /dev/null - grep -Ev "^$key=" "$rootfs/etc/lsb-release" \ - | sudo tee -a "$temp_lsb_release" > /dev/null - sudo sort -o "$rootfs/etc/lsb-release" "$temp_lsb_release" - sudo rm -f "$temp_lsb_release" - restore_lsb_selinux "$rootfs/etc/lsb-release" + local data + data=$( + ( + grep -Ev "^${key}=" "${lsb}" + echo "${key}=${value}" + ) | sort + ) + sudo tee "${lsb}" <<<"${data}" >/dev/null } main() { @@ -45,17 +47,25 @@ exit 1 fi + # If there are no key/value pairs to process, we don't need write access. + local ro=$([[ $# -eq 0 ]] && echo true || echo false) + local image=$1 shift - local loopdev=$(loopback_partscan "${image}") - local rootfs=$(make_temp_dir) + local loopdev rootfs - # If there are no key/value pairs to process, we don't need write access. - if [[ $# -eq 0 ]]; then - mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" + if [[ -d "${image}" ]]; then + rootfs="${image}" else - mount_loop_image_partition "${loopdev}" 3 "${rootfs}" - touch "${image}" # Updates the image modification time. + rootfs=$(make_temp_dir) + loopdev=$(loopback_partscan "${image}") + + if ${ro}; then + mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" + else + mount_loop_image_partition "${loopdev}" 3 "${rootfs}" + touch "${image}" # Updates the image modification time. + fi fi # Process all the key/value pairs. @@ -65,6 +75,9 @@ shift 2 set_lsb_release_keyval "${rootfs}" "${key}" "${value}" done + if ! ${ro}; then + restore_lsb_selinux "${rootfs}/etc/lsb-release" + fi # Dump the final state. cat "${rootfs}/etc/lsb-release" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/sign_android_image.sh vboot-utils-0~R99-14469.B/scripts/image_signing/sign_android_image.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/sign_android_image.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/sign_android_image.sh 2022-02-11 14:46:09.000000000 +0000 @@ -37,6 +37,7 @@ sign_framework_apks() { local system_mnt="$1" local key_dir="$2" + local working_dir="$3" local flavor_prop="" local keyset="" @@ -53,6 +54,11 @@ info "Start signing framework apks" + if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \ + "Prepare apks signing"; then + return 1 + fi + # Counters for validity check. local counter_platform=0 local counter_media=0 @@ -116,6 +122,10 @@ --in "${temp_apk}" --out "${signed_apk}" \ ${extra_flags} fi + if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \ + "sign apk ${signed_apk}"; then + return 1 + fi # Copy the content instead of mv to avoid owner/mode changes. sudo cp "${signed_apk}" "${apk}" && rm -f "${signed_apk}" @@ -127,6 +137,10 @@ : $(( counter_${keyname} += 1 )) : $(( counter_total += 1 )) + if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \ + "update re-signed apk ${apk}"; then + return 1 + fi done < <(find "${system_mnt}/system" -type f -name '*.apk' -print0) info "Found ${counter_platform} platform APKs." @@ -141,6 +155,8 @@ ${counter_total} -lt 25 ]]; then die "Number of re-signed package seems to be wrong" fi + + return 0 } # Extracts certificate from the provided public key. @@ -234,7 +250,22 @@ sudo find "${dir}" -exec stat -c '%n:%u:%g:%a' {} + | sort } -main() { +# Integrity check that image content is unchanged. +image_content_integrity_check() { + local system_mnt=$1 + local working_dir=$2 + local reason=$3 + snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.new" + local d + if ! d=$(diff "${working_dir}"/properties.{orig,new}); then + error "Unexpected change of file property, diff due to ${reason}\n${d}" + return 1 + fi + + return 0 +} + +sign_android_internal() { local root_fs_dir=$1 local key_dir=$2 @@ -242,7 +273,6 @@ # Keep this aligned with # src/private-overlays/project-cheets-private/scripts/board_specific_setup.sh local system_image="" - local compression_flags="" local selinux_dir="${root_fs_dir}/etc/selinux" local file_contexts="" local vm_candidate="${root_fs_dir}/opt/google/vms/android/system.raw.img" @@ -250,11 +280,9 @@ "${root_fs_dir}/opt/google/containers/android/system.raw.img") if [[ -f "${vm_candidate}" ]]; then system_image="${vm_candidate}" - compression_flags="-comp lz4 -Xhc -b 256K" file_contexts="${selinux_dir}/arc/contexts/files/android_file_contexts_vm" elif [[ -f "${container_candidate}" ]]; then system_image="${container_candidate}" - compression_flags="-comp gzip" file_contexts="${selinux_dir}/arc/contexts/files/android_file_contexts" else die "System image does not exist" @@ -277,6 +305,21 @@ die "System image does not exist: ${system_img}" fi + # NOTE: Keep compression_flags aligned with + # src/private-overlays/project-cheets-private/scripts/board_specific_setup.sh + local compression_flags="" + local compression=$(sudo "${unsquashfs}" -s "${system_img}" \ + | grep -e ^"Compression\s") + if [[ "${compression}" == "Compression gzip" ]]; then + compression_flags="-comp gzip" + elif [[ "${compression}" == "Compression lz4" ]]; then + compression_flags="-comp lz4 -Xhc -b 256K" + elif [[ "${compression}" == "Compression zstd" ]]; then + compression_flags="-comp zstd -b 256K" + else + die "Unexpected compression type: ${compression}" + fi + if ! type -P zipalign &>/dev/null || ! type -P signapk &>/dev/null \ || ! type -P apksigner &>/dev/null; then # TODO(victorhsieh): Make this an error. This is not treating as error @@ -293,15 +336,25 @@ snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.orig" - sign_framework_apks "${system_mnt}" "${key_dir}" + if ! sign_framework_apks "${system_mnt}" "${key_dir}" "${working_dir}"; then + return 1 + fi + + if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \ + "sign_framework_apks"; then + return 1 + fi + update_sepolicy "${system_mnt}" "${key_dir}" - replace_ota_cert "${system_mnt}" "${key_dir}/releasekey.x509.pem" + if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \ + "update_sepolicy"; then + return 1 + fi - # Validity check. - snapshot_file_properties "${system_mnt}" > "${working_dir}/properties.new" - local d - if ! d=$(diff "${working_dir}"/properties.{orig,new}); then - die "Unexpected change of file property, diff\n${d}" + replace_ota_cert "${system_mnt}" "${key_dir}/releasekey.x509.pem" + if ! image_content_integrity_check "${system_mnt}" "${working_dir}" \ + "replace_ota_cert"; then + return 1 fi # Packages cache needs to be regenerated when the key and timestamp are @@ -346,17 +399,33 @@ info "Packages cache ${packages_cache} does not exist. Skip regeneration." fi - info "Repacking squashfs image" + info "Repacking squashfs image with compression flags '${compression_flags}'" local old_size=$(stat -c '%s' "${system_img}") # Remove old system image to prevent mksquashfs tries to merge both images. sudo rm -rf "${system_img}" - # Note, compression_flags is a combination of flags. Keep this aligned with - # src/private-overlays/project-cheets-private/scripts/board_specific_setup.sh sudo mksquashfs "${system_mnt}" "${system_img}" \ ${compression_flags} -context-file "${file_contexts}" -mount-point "/" \ -no-progress local new_size=$(stat -c '%s' "${system_img}") info "Android system image size change: ${old_size} -> ${new_size}" + return 0 +} + +main() { + # TODO(b/175081695): Remove retries once root problem is fixed. + local attempts + for (( attempts = 1; attempts <= 3; ++attempts )); do + if sign_android_internal "$@"; then + exit 0 + fi + warn "Could not sign android image due to recoverable error, will retry," \ + "attempt # ${attempts}." + warn "@@@ALERT@@@" + lsof -n + dmesg + mount + done + die "Unable to sign Android image; giving up." } main "$@" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/sign_cr50_firmware.sh vboot-utils-0~R99-14469.B/scripts/image_signing/sign_cr50_firmware.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/sign_cr50_firmware.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/sign_cr50_firmware.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,460 +0,0 @@ -#!/bin/bash -# Copyright 2018 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -. "$(dirname "$0")/common.sh" - -load_shflags || exit 1 - -DEFINE_boolean override_keyid "${FLAGS_TRUE}" \ - "Override keyid from manifest." "" - -FLAGS_HELP="Usage: ${PROG} [options] - -Signs with keys in . -" - -# Parse command line. -FLAGS "$@" || exit 1 -eval set -- "${FLAGS_ARGV}" - -# Abort on error and uninitialized variables. -set -e -set -u - -PRE_PVT_BID_FLAG=0x10 -MP_BID_FLAG=0x10000 -CR50_FACTORY_VERSION="0.3.22" - -# Convert unsigned 32 bit value into a signed one. -to_int32() { - local inp="$1" - python -c \ - "import struct; \ - d=struct.pack('I', $inp); \ - print (struct.unpack('i', d)[0])" -} - -# This function accepts one argument, the name of the Cr50 manifest file which -# needs to be verified and in certain cases altered. -# -# The function verifies that the input manifest is a proper json file, and -# that the manifest conforms to Cr50 version numbering and board ID flags -# conventions for various build images: -# -# - only factory version binaries can be converted to node locked images, -# board IDs for node locked images come from signing instructions, and the -# config1 manifest field value must have the 0x80000000 bit set. -# -# - when signing pre-pvt binaries (major version number is even) the 0x10 -# flags bit must be set. -# -# - when signing mp images (major version number is odd), the 0x10000 flags -# bit must be set (this can be overridden by signing instructions). -verify_and_prepare_cr50_manifest() { - if [[ $# -ne 1 ]]; then - die "Usage: verify_and_prepare_cr50_manifest " - fi - - local manifest_json="$1" - - local bid_flags - local config1 - local epoch - local major - local minor - local values - - values=( $(jq '.config1,.epoch,.major,.minor,.board_id_flags' \ - "${manifest_json}") ) - - config1="${values[0]}" - epoch="${values[1]}" - major="${values[2]}" - minor="${values[3]}" - bid_flags="${values[4]}" - - if [[ ${major} == null ]]; then - die "Major version number not found in ${manifest_json}" - fi - - if [[ ${bid_flags} == null ]]; then - die "bid_flags not found in ${manifest_json}" - fi - - case "${INSN_TARGET:-}" in - - (NodeLocked) - if [[ -z ${INSN_DEVICE_ID:-} ]]; then - die "Node locked target without Device ID value" - fi - # Case of a node locked image, it must have the fixed factory version. - if [[ $epoch.$major.$minor != $CR50_FACTORY_VERSION ]];then - die "Won't create node locked images for version $epoch.$major.$minor" - fi - - local sub - local devid0 - local devid1 - - devid0="$(to_int32 "0x${INSN_DEVICE_ID/-*}")" - devid1="$(to_int32 "0x${INSN_DEVICE_ID/*-}")" - cf1="$(to_int32 $(( 0x80000000 + ${config1} )))" - sub="$(printf " \"DEV_ID0\": %s,\\\n \"DEV_ID1\": %s," \ - "${devid0}" "${devid1}")" - - # Manifest fields must be modified as follows: - # - # - board_id related fields removed - # - 'config1' field bit 0x80000000 set - # - least significant bit of the 'tag' field originally set to all zeros - # changed from zero to one - # - DEV_ID values spliced in into the 'fuses' section - sed -i "/board_id/d;\ - s/\"config1\":.*/\"config1\": ${cf1},/;\ - s/\(tag.*0\+\)0/\11/;\ - /\"fuses\":/ a\ - $sub" "${manifest_json}" || die "Failed to edit the manifest" - return 0 - ;; - - (PrePVT) - # All we care about for pre pvt images is that major version number is - # even and the 0x10 Board ID flag is set. - if (( !(major & 1 ) && (bid_flags & PRE_PVT_BID_FLAG) )); then - return 0 - fi - ;; - - (ReleaseCandidate|GeneralRelease) - if (( (bid_flags & MP_BID_FLAG) && (major & 1) )); then - if [[ ${INSN_TARGET} == GeneralRelease ]]; then - # Strip Board ID information for approved for release MP images. - sed -i "/board_id/d" "${manifest_json}" - fi - return 0 - fi - ;; - - (*) - die "Unsupported target '${INSN_TARGET:-}'" - esac - - die "Inconsistent manifest ${manifest_json}: major = '${major}'," \ - "board_id_flags = '${bid_flags}' target = '${INSN_TARGET}'" -} - -# This function accepts two arguments, names of two binary files. -# -# It searches the first passed-in file for the first 8 bytes of the second -# passed in file. The od utility is used to generate full hex dump of the -# first file (16 bytes per line) and the first 8 bytes of the second file. -# grep is used to check if the pattern is present in the full dump. -find_blob_in_blob() { - if [[ $# -ne 2 ]]; then - die "Usage: find_blob_in_blob " - fi - - local main_blob="$1" - local pattern_blob="$2" - local pattern - # Show without offsets, single byte hex, no compression of zero runs. - local od_options=("-An" "-tx1" "-v") - - # Get the first 8 bytes of the pattern blob. - pattern="$(od "${od_options[@]}" -N8 "${pattern_blob}")" - - # Eliminate all newlines to be able to search the entire body as one unit. - if od "${od_options[@]}" "${main_blob}" | \ - tr -d '\n' | - grep -q -F "${pattern}"; then - return 0 - fi - - return 1 -} - -# This function accepts two arguments, names of the two ELF files. -# -# The files are searched for test RMA public key patterns - x25519 or p256, -# both files are supposed to have pattern of one of these keys and not the -# other. If this holds true the function prints the public key base name. If -# not both files include the same key, or include more than one key, the -# function reports failure and exits the script. -determine_rma_key_base() { - if [[ $# -ne 3 ]]; then - die "Usage: determine_rma_key_base " - fi - - local rma_key_dir="$1" - local elfs=( "$2" "$3" ) - local base_name="${rma_key_dir}/rma_key_blob" - local curve - local curves=( "x25519" "p256" ) - local elf - local key_file - local mask=1 - local result=0 - local rma_key_base - - for curve in "${curves[@]}"; do - key_file="${base_name}.${curve}.test" - for elf in "${elfs[@]}"; do - if find_blob_in_blob "${elf}" "${key_file}"; then - : $(( result |= mask )) - fi - : $(( mask <<= 1 )) - done - done - - case "${result}" in - (3) curve="x25519";; - (12) curve="p256";; - (*) die "could not determine key type in the ELF files";; - esac - - echo "${base_name}.${curve}" -} - -# Sign cr50 RW firmware ELF images into a combined cr50 firmware image -# using the provided production keys and manifests. -sign_rw() { - if [[ $# -ne 7 ]]; then - die "Usage: sign_rw " \ - " " - fi - - local key_file="$1" - local manifest_file="$2" - local fuses_file="$3" - local rma_key_dir="$4" - local elfs=( "$5" "$6" ) - local result_file="$7" - local temp_dir="$(make_temp_dir)" - local rma_key_base - - if [[ ! -f "${result_file}" ]]; then - die "${result_file} not found." - fi - - # If signing a chip factory image (version 0.0.22) do not try figuring out the - # RMA keys. - local cr50_version="$(jq '.epoch * 10000 + .major * 100 + .minor' \ - "${manifest_file}")" - - if [[ "${cr50_version}" != "22" ]]; then - rma_key_base="$(determine_rma_key_base "${rma_key_dir}" "${elfs[@]}")" - else - echo "Ignoring RMA keys for factory branch ${cr50_version}" - fi - - local signer_command_params=(--b -x "${fuses_file}" --key "${key_file}") - - # Swap test public RMA server key with the prod version. - if [[ -n "${rma_key_base}" ]]; then - signer_command_params+=( - --swap "${rma_key_base}.test","${rma_key_base}.prod" - ) - fi - signer_command_params+=(--json "${manifest_file}") - - signer_command_params+=(--format=bin) - dst_suffix='flat' - - if [[ "${FLAGS_override_keyid}" == "${FLAGS_TRUE}" ]]; then - signer_command_params+=(--override-keyid) - fi - - local count=0 - for elf in "${elfs[@]}"; do - if strings "${elf}" | grep -q "DBG/cr50"; then - die "Will not sign debug image with prod keys" - fi - signed_file="${temp_dir}/${count}.${dst_suffix}" - - # Make sure output file is not owned by root. - touch "${signed_file}" - if ! cr50-codesigner "${signer_command_params[@]}" \ - -i "${elf}" -o "${signed_file}"; then - die "cr50-codesigner ${signer_command_params[@]}" \ - "-i ${elf} -o ${signed_file} failed" - fi - - if [[ -n "${rma_key_base}" ]]; then - if find_blob_in_blob "${signed_file}" "${rma_key_base}.test"; then - die "test RMA key in the signed image!" - fi - - if ! find_blob_in_blob "${signed_file}" "${rma_key_base}.prod"; then - die "prod RMA key not in the signed image!" - fi - fi - : $(( count++ )) - done - - # Full binary image is required, paste the newly signed blobs into the - # output image. - dd if="${temp_dir}/0.${dst_suffix}" of="${result_file}" \ - seek=16384 bs=1 conv=notrunc - dd if="${temp_dir}/1.${dst_suffix}" of="${result_file}" \ - seek=278528 bs=1 conv=notrunc -} - -# A very crude RO verification function. The key signature found at a fixed -# offset into the RO blob must match the RO type. Prod keys have bit D2 set to -# one, dev keys have this bit set to zero. -# -# The check is bypassed if the key file directory name includes string 'test'. -verify_ro() { - if [[ $# -ne 2 ]]; then - die "Usage: verify_ro " - fi - - local ro_bin="$1" - local key_file="$2" - local key_byte - local key_path - - if [[ ! -f "${ro_bin}" ]]; then - die "${ro_bin} not a file!" - fi - - key_path="$(dirname "${key_file}")" - if [[ ${key_path##*/} == *"test"* ]]; then - info "Test run, ignoring key type verification" - return 0 - fi - - # Key signature's lowest byte is byte #5 in the line at offset 0001a0. - key_byte="$(od -Ax -t x1 -v "${ro_bin}" | awk '/0001a0/ {print $6}')" - case "${key_byte}" in - (?[4567cdef]) - return 0 - ;; - esac - - die "RO key (${key_byte}) in ${ro_bin} does not match type prod" -} - -# This function prepares a full CR50 image, consisting of two ROs and two RWs -# placed at their respective offsets into the resulting blob. It invokes the -# bs (binary signer) script to actually convert ELF versions of RWs into -# binaries and sign them. -# -# The signed image is placed in the directory named as concatenation of RO and -# RW version numbers and board ID fields, if set to non-default. The ebuild -# downloading the tarball from the BCS expects the image to be in that -# directory. -sign_cr50_firmware() { - if [[ $# -ne 9 ]]; then - die "Usage: sign_cr50_firmware " \ - " " - fi - - local key_file="$1" - local manifest_source="$2" - local fuses_file="$3" - local rma_key_dir="$4" - local ro_a_hex="$5" - local ro_b_hex="$6" - local rw_a="$7" - local rw_b="$8" - local output_file="$9" - - local manifest_file="${manifest_source}.updated" - local temp_dir="$(make_temp_dir)" - - # The H1 chip where Cr50 firmware runs has 512K of flash, the generated - # image must match the flash size. - IMAGE_SIZE="$(( 512 * 1024 ))" - - # Prepare file for inline editing. - jq . < "${manifest_source}" > "${manifest_file}" || \ - die "basic validation of ${manifest_json} failed" - - verify_and_prepare_cr50_manifest "${manifest_file}" - - dd if=/dev/zero bs="${IMAGE_SIZE}" count=1 status=none | - tr '\000' '\377' > "${output_file}" - if [[ "$(stat -c '%s' "${output_file}")" != "${IMAGE_SIZE}" ]]; then - die "Failed creating ${output_file}" - fi - - local f - local count=0 - for f in "${ro_a_hex}" "${ro_b_hex}"; do - if ! objcopy -I ihex "${f}" -O binary "${temp_dir}/${count}.bin"; then - die "Failed to convert ${f} from hex to bin" - fi - verify_ro "${temp_dir}/${count}.bin" "${key_file}" - : $(( count++ )) - done - - if ! sign_rw "${key_file}" "${manifest_file}" "${fuses_file}" \ - "${rma_key_dir}" "${rw_a}" "${rw_b}" "${output_file}"; then - die "Failed invoking sign_rw for ELF files ${rw_a} ${rw_b}" - fi - - dd if="${temp_dir}/0.bin" of="${output_file}" conv=notrunc - dd if="${temp_dir}/1.bin" of="${output_file}" seek=262144 bs=1 conv=notrunc - - echo "Image successfully signed to ${output_file}" -} - -# Sign the directory holding cr50 firmware. -sign_cr50_firmware_dir() { - if [[ $# -ne 3 ]]; then - die "Usage: sign_cr50_firmware_dir " - fi - - local input="${1%/}" - local key_file="$2" - local output="$3" - - if [[ -d "${output}" ]]; then - output="${output}/cr50.bin.prod" - fi - - sign_cr50_firmware \ - "${key_file}" \ - "${input}/prod.json" \ - "${input}/fuses.xml" \ - "${input}" \ - "${input}/prod.ro.A" \ - "${input}/prod.ro.B" \ - "${input}/ec.RW.elf" \ - "${input}/ec.RW_B.elf" \ - "${output}" -} - -main() { - if [[ $# -ne 3 ]]; then - flags_help - exit 1 - fi - - local input="${1%/}" - local key_dir="$2" - local output="$3" - - local key_file="${key_dir}/cr50.pem" - local signing_instructions="${input}/signing_instructions.sh" - - if [[ -f ${signing_instructions} ]]; then - . "${signing_instructions}" - else - die "${signing_instructions} not found" - fi - - if [[ ! -e "${key_file}" ]]; then - die "Missing key file: ${key_file}" - fi - - if [[ ! -d "${input}" ]]; then - die "Missing input directory: ${input}" - fi - - sign_cr50_firmware_dir "${input}" "${key_file}" "${output}" -} -main "$@" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/sign_gsc_firmware.sh vboot-utils-0~R99-14469.B/scripts/image_signing/sign_gsc_firmware.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/sign_gsc_firmware.sh 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/sign_gsc_firmware.sh 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,648 @@ +#!/bin/bash +# Copyright 2018 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +. "$(dirname "$0")/common.sh" + +load_shflags || exit 1 + +DEFINE_boolean override_keyid "${FLAGS_TRUE}" \ + "Override keyid from manifest." "" + +FLAGS_HELP="Usage: ${PROG} [options] + +Signs with keys in . +" + +# Parse command line. +FLAGS "$@" || exit 1 +eval set -- "${FLAGS_ARGV}" + +# Abort on error and uninitialized variables. +set -e +set -u + +PRE_PVT_BID_FLAG=0x10 +MP_BID_FLAG=0x10000 +CR50_NODE_LOCKED_VERSION="0.5.12" + +# Convert unsigned 32 bit value into a signed one. +to_int32() { + local inp="$1" + python -c \ + "import struct; \ + d=struct.pack('I', $inp); \ + print (struct.unpack('i', d)[0])" +} + +# Functions allowing to determine the base address of a binary blob in ihex +# format. Invoked in a subprocess through () to be able to use stdout as the +# return values. + +# In ihex format binary data is represented as a set of records. Each record +# is a text string of hex values in ASCII. All records start with a header +# which determines the record contents. +# +# The most common record type is the data record, its header includes the 16 +# bit address of where the record data will have to be placed in the physical +# address space. Naturally 16 bits is not enough as of last thirty years, some +# special types of record are used to specify the segment base of there the +# 16 bit address is used as the offset. +# +# The segment base is still represented as a 16 bit value, depending on the +# record type the base is shifted right ether 4 (record type 02) or 16 (record +# type 04) bits. +# +# The first two records of the ihex binary blob are a segment record and a +# data record. Combining the segment value from the first record and the +# address value from the second record one can determine the base address +# where the blob is supposed to be placed. +# +# See https://en.wikipedia.org/wiki/Intel_HEX for further details. +parse_segment() { + local string="$1" + + if [[ "${string}" =~ ^:020000 && "${#string}" -eq 15 ]]; then + local type="${string:7:2}" + local value="0x${string:9:4}" + local segment + + case "${type}" in + (02) + segment=$(( value << 4 )) + ;; + (04) + segment=$(( value << 16 )) + ;; + (*) + error "unknown segment record type ${type}" + ;; + esac + printf "0x%x" "${segment}" + else + error "unexpected segment record: ${string}" + fi +} + +# The second record in the ihex binary blob is mapped to the lowest 16 bit +# address in the segment. +parse_data() { + local string="$1" + + if [[ "${string}" =~ ^:10 && "${#string}" -eq 43 ]]; then + echo "0x${string:3:4}" + else + error "unexpected data record: ${string}" + fi +} + +# Given an ihex binary blob determine its base address as a sum of the segment +# address and the offset of the first record into the segment. +get_hex_base() { + local hexf="$1" + local strings + local segment + local base_offset + + # Some ihex blobs include , drop to allow for fixed size check. + mapfile -t strings < <(head -2 "${hexf}" | sed 's/\x0d//') + + if [[ ${#strings[@]} != 2 ]]; then + error "input file ${hexf} too short" + return + fi + segment="$(parse_segment "${strings[0]}")" + base_offset="$(parse_data "${strings[1]}")" + + if [[ -n "${segment}" && -n "${base_offset}" ]]; then + printf "%d\n" $(( segment + base_offset )) + else + error "${hexf} does not seem to be a valid ihex module." + fi +} + +# Paste a binary blob into a larger binary file at a given offset. +paste_bin() { + local file="${1}" + local blob="${2}" + local image_base="${3}" + local hex_base="${4}" + local file_size + local blob_size + local offset + + + file_size="$(stat -c '%s' "${file}")" + blob_size="$(stat -c '%s' "${blob}")" + offset="$(( hex_base - image_base ))" + + if [[ $(( blob_size + offset )) -ge ${file_size} ]];then + die \ + "Can't fit ${blob_size} bytes at offset ${offset} into ${file_size} bytes" + fi + dd if="${blob}" of="${file}" seek="${offset}" bs=1 conv=notrunc +} + +# This function accepts one argument, the name of the GSC manifest file which +# needs to be verified and in certain cases altered. +# +# The function verifies that the input manifest is a proper json file, and +# that the manifest conforms to GSC version numbering and board ID flags +# conventions for various build images: +# +# - only binaries where version is set to CR50_NODE_LOCKED_VERSION can be +# converted to node locked images. Board IDs for node locked images come +# from signing instructions, and the config1 manifest field value must have +# the 0x80000000 bit set. +# +# - when signing pre-pvt binaries (major version number is even) the 0x10 +# flags bit must be set. +# +# - when signing mp images (major version number is odd), the 0x10000 flags +# bit must be set (this can be overridden by signing instructions). +verify_and_prepare_gsc_manifest() { + if [[ $# -ne 1 ]]; then + die "Usage: verify_and_prepare_gsc_manifest " + fi + + local manifest_json="$1" + + local bid_flags + local config1 + local epoch + local major + local minor + local values + + mapfile -t values < <(jq '.config1,.epoch,.major,.minor,.board_id_flags' \ + "${manifest_json}") + + config1="${values[0]}" + epoch="${values[1]}" + major="${values[2]}" + minor="${values[3]}" + bid_flags="${values[4]}" + + if [[ ${major} == null ]]; then + die "Major version number not found in ${manifest_json}" + fi + + if [[ ${bid_flags} == null ]]; then + die "bid_flags not found in ${manifest_json}" + fi + + case "${INSN_TARGET:-}" in + + (NodeLocked) + if [[ -z ${INSN_DEVICE_ID:-} ]]; then + die "Node locked target without Device ID value" + fi + # Case of a node locked image, it must have the fixed version. + if [[ "${epoch}.${major}.${minor}" != "${CR50_NODE_LOCKED_VERSION}" ]] + then + die "Won't create node locked images for version $epoch.$major.$minor" + fi + + local sub + local devid0 + local devid1 + + devid0="$(to_int32 "0x${INSN_DEVICE_ID/-*}")" + devid1="$(to_int32 "0x${INSN_DEVICE_ID/*-}")" + cf1="$(to_int32 $(( 0x80000000 + config1 )))" + sub="$(printf " \"DEV_ID0\": %s,\\\n \"DEV_ID1\": %s," \ + "${devid0}" "${devid1}")" + + # Manifest fields must be modified as follows: + # + # - board_id related fields removed + # - 'config1' field bit 0x80000000 set + # - least significant bit of the 'tag' field originally set to all zeros + # changed from zero to one + # - DEV_ID values spliced in into the 'fuses' section + sed -i "/board_id/d;\ + s/\"config1\":.*/\"config1\": ${cf1},/;\ + s/\(tag.*0\+\)0/\11/;\ + /\"fuses\":/ a\ + $sub" "${manifest_json}" || die "Failed to edit the manifest" + return 0 + ;; + + (PrePVT) + # All we care about for pre pvt images is that major version number is + # even and the 0x10 Board ID flag is set. + if (( !(major & 1 ) && (bid_flags & PRE_PVT_BID_FLAG) )); then + return 0 + fi + ;; + + (ReleaseCandidate|GeneralRelease) + if (( (bid_flags & MP_BID_FLAG) && (major & 1) )); then + if [[ ${INSN_TARGET} == GeneralRelease ]]; then + # Strip Board ID information for approved for release MP images. + sed -i "/board_id/d" "${manifest_json}" + fi + return 0 + fi + ;; + + (*) + die "Unsupported target '${INSN_TARGET:-}'" + esac + + die "Inconsistent manifest ${manifest_json}: major = '${major}'," \ + "board_id_flags = '${bid_flags}' target = '${INSN_TARGET}'" +} + +# This function accepts two arguments, names of two binary files. +# +# It searches the first passed-in file for the first 8 bytes of the second +# passed in file. The od utility is used to generate full hex dump of the +# first file (16 bytes per line) and the first 8 bytes of the second file. +# grep is used to check if the pattern is present in the full dump. +find_blob_in_blob() { + if [[ $# -ne 2 ]]; then + die "Usage: find_blob_in_blob " + fi + + local main_blob="$1" + local pattern_blob="$2" + local pattern + # Show without offsets, single byte hex, no compression of zero runs. + local od_options=("-An" "-tx1" "-v") + + # Get the first 8 bytes of the pattern blob. + pattern="$(od "${od_options[@]}" -N8 "${pattern_blob}")" + + # Eliminate all newlines to be able to search the entire body as one unit. + if od "${od_options[@]}" "${main_blob}" | \ + tr -d '\n' | + grep -q -F "${pattern}"; then + return 0 + fi + + return 1 +} + +# This function accepts two arguments, names of the two ELF files. +# +# The files are searched for test RMA public key patterns - x25519 or p256, +# both files are supposed to have pattern of one of these keys and not the +# other. If this holds true the function prints the public key base name. If +# not both files include the same key, or include more than one key, the +# function reports failure and exits the script. +determine_rma_key_base() { + if [[ $# -ne 3 ]]; then + die "Usage: determine_rma_key_base " + fi + + local rma_key_dir="$1" + local elfs=( "$2" "$3" ) + local base_name="${rma_key_dir}/rma_key_blob" + local curve + local curves=( "x25519" "p256" ) + local elf + local key_file + local mask=1 + local result=0 + local rma_key_base + + for curve in "${curves[@]}"; do + key_file="${base_name}.${curve}.test" + for elf in "${elfs[@]}"; do + if find_blob_in_blob "${elf}" "${key_file}"; then + : $(( result |= mask )) + fi + : $(( mask <<= 1 )) + done + done + + case "${result}" in + (3) curve="x25519";; + (12) curve="p256";; + (*) die "could not determine key type in the ELF files";; + esac + + echo "${base_name}.${curve}" +} + +# Sign GSC RW firmware ELF images into a combined GSC firmware image +# using the provided production keys and manifests. +sign_rw() { + if [[ $# -ne 9 ]]; then + die "Usage: sign_rw " \ + " " + fi + + local key_file="$1" + local manifest_file="$2" + local fuses_file="$3" + local rma_key_dir="$4" + local rws=( "$5" "$6" ) + local result_file="$7" + local generation="$8" + local image_base="$9" + local base_name + local rma_key_base="" + local signer_command_params + local temp_dir + + temp_dir="$(make_temp_dir)" + signer_command_params=(-x "${fuses_file}" --key "${key_file}") + + case "${generation}" in + (h) + # H1 image might require some tweaking. + # If signing a chip factory image (version 0.0.22) do not try figuring + # out the RMA keys. + local gsc_version + + gsc_version="$(jq '.epoch * 10000 + .major * 100 + .minor' \ + "${manifest_file}")" + + if [[ "${gsc_version}" != "22" ]]; then + rma_key_base="$(determine_rma_key_base "${rma_key_dir}" "${rws[@]}")" + else + warn "Ignoring RMA keys for factory branch ${gsc_version}" + fi + + # Swap test public RMA server key with the prod version. + if [[ -n "${rma_key_base}" ]]; then + signer_command_params+=( + --swap "${rma_key_base}.test,${rma_key_base}.prod" + ) + fi + + # Indicate H1 signing. + signer_command_params+=( "--b" ) + base_name="cr50" + ;; + (d) + # Indicate D1 signing. + signer_command_params+=( "--dauntless" "--ihex" ) + base_name="ti50" + ;; + (*) + die "Unknown generation value \"${generation}\"" + ;; + esac + + signer_command_params+=(--json "${manifest_file}") + + + if [[ "${FLAGS_override_keyid}" == "${FLAGS_TRUE}" ]]; then + signer_command_params+=(--override-keyid) + fi + + for rw in "${rws[@]}"; do + local hex_signed="${temp_dir}/hex_signed" + local bin_signed="${temp_dir}/bin_signed" + local hex_base + + # Make sure output files are not owned by root. + touch "${bin_signed}" "${hex_signed}" + if ! gsc-codesigner "${signer_command_params[@]}" \ + -i "${rw}" -o "${hex_signed}"; then + die "gsc-codesigner ${signer_command_params[*]}" \ + "-i ${rw} -o ${hex_signed} failed" + fi + + if ! objcopy -I ihex "${hex_signed}" -O binary "${bin_signed}"; then + die "Failed to convert ${rw} from hex to bin" + fi + + if [[ -n "${rma_key_base}" ]]; then + if find_blob_in_blob "${bin_signed}" "${rma_key_base}.test"; then + die "test RMA key in the signed image!" + fi + + if ! find_blob_in_blob "${bin_signed}" "${rma_key_base}.prod"; then + die "prod RMA key not in the signed image!" + fi + fi + + hex_base="$(get_hex_base "${hex_signed}")" + paste_bin "${result_file}" "${bin_signed}" "${image_base}" "${hex_base}" + done + + if strings "${rw}" | grep -q "DBG/${base_name}"; then + die "Will not sign debug image with prod keys" + fi + +} + +# A very crude RO verification function. The key signature found at a fixed +# offset into the RO blob must match the RO type. Prod keys have bit D2 set to +# one, dev keys have this bit set to zero. +# +# The check is bypassed if the key file directory name includes string 'test'. +verify_ro() { + if [[ $# -ne 2 ]]; then + die "Usage: verify_ro " + fi + + local ro_bin="$1" + local key_file="$2" + local key_byte + local key_path + + if [[ ! -f "${ro_bin}" ]]; then + die "${ro_bin} not a file!" + fi + + key_path="$(dirname "${key_file}")" + if [[ ${key_path##*/} == *"test"* ]]; then + info "Test run, ignoring key type verification" + return 0 + fi + + # Key signature's lowest byte is byte #5 in the line at offset 0001a0. + key_byte="$(od -Ax -t x1 -v "${ro_bin}" | awk '/0001a0/ {print $6}')" + case "${key_byte}" in + (?[4567cdef]) + return 0 + ;; + esac + + die "RO key (${key_byte}) in ${ro_bin} does not match type prod" +} + +# This function prepares a full GSC image, consisting of two ROs and two RWs +# placed at their respective offsets into the resulting blob. It invokes the +# bs (binary signer) script to actually convert ELF versions of RWs into +# binaries and sign them. +# +# The signed image is placed in the directory named as concatenation of RO and +# RW version numbers and board ID fields, if set to non-default. The ebuild +# downloading the tarball from the BCS expects the image to be in that +# directory. +sign_gsc_firmware() { + if [[ $# -ne 10 ]]; then + die "Usage: sign_gsc_firmware " \ + " " + fi + + local key_file="$1" + local manifest_file="$2" + local fuses_file="$3" + local rma_key_dir="$4" + local ro_a_hex="$5" + local ro_b_hex="$6" + local rw_a="$7" + local rw_b="$8" + local output_file="$9" + local generation="${10}" + local temp_dir + local chip_name + + temp_dir="$(make_temp_dir)" + + case "${generation}" in + (h) + # H1 flash size, image size must match. + IMAGE_SIZE="$(( 512 * 1024 ))" + IMAGE_BASE="0x40000" + chip_name="cr50" + ;; + (d) + # D2 flash size, image size must match. + IMAGE_SIZE="$(( 1024 * 1024 ))" + IMAGE_BASE="0x80000" + chip_name="ti50" + ;; + esac + + verify_and_prepare_gsc_manifest "${manifest_file}" + + dd if=/dev/zero bs="${IMAGE_SIZE}" count=1 status=none | + tr '\000' '\377' > "${output_file}" + if [[ "$(stat -c '%s' "${output_file}")" != "${IMAGE_SIZE}" ]]; then + die "Failed creating ${output_file}" + fi + + if ! sign_rw "${key_file}" "${manifest_file}" "${fuses_file}" \ + "${rma_key_dir}" "${rw_a}" "${rw_b}" \ + "${output_file}" "${generation}" "${IMAGE_BASE}"; then + die "Failed invoking sign_rw for ${rw_a} and ${rw_b}" + fi + + local f + for f in "${ro_a_hex}" "${ro_b_hex}"; do + local hex_base + local bin + + hex_base="$(get_hex_base "${f}")" + bin="${temp_dir}/bin" + + if [[ -z ${hex_base} ]]; then + die "Failed retrieving base address from ${f}" + fi + + if ! objcopy -I ihex "${f}" -O binary "${bin}"; then + die "Failed to convert ${f} from hex to bin" + fi + if [[ "${generation}" == "h" ]]; then + verify_ro "${bin}" "${key_file}" + fi + + paste_bin "${output_file}" "${bin}" "${IMAGE_BASE}" "${hex_base}" + done + + # Tell the signer how to rename the @CHIP@ portion of the output. + echo "${chip_name}" > "${output_file}.rename" + + info "Image successfully signed to ${output_file}" +} + +# Sign the directory holding GSC firmware. +sign_gsc_firmware_dir() { + if [[ $# -ne 3 ]]; then + die "Usage: sign_gsc_firmware_dir " + fi + + local input="${1%/}" + local key_dir="$2" + local output="$3" + local generation + local rw_a + local rw_b + local manifest_source + local manifest_file + local key_file + local base_name + + manifest_source="${input}/prod.json" + manifest_file="${manifest_source}.updated" + + # Verify signing manifest. + jq . < "${manifest_source}" > "${manifest_file}" || \ + die "basic validation of ${manifest_source} failed" + + + # Retrieve chip type from the manifest, if present, otherwise use h1. + generation="$(jq ".generation" "${input}/prod.json" | sed 's/"//g')" + case "${generation}" in + (h|null) + generation="h" + base_name="cr50" + rw_a="${input}/ec.RW.elf" + rw_b="${input}/ec.RW_B.elf" + ;; + (d) + base_name="ti50" + rw_a="${input}/rw_A.hex" + rw_b="${input}/rw_B.hex" + ;; + (*) + die "Unknown generation value \"${generation}\" in signing manifest" + ;; + esac + + key_file="${key_dir}/${base_name}.pem" + if [[ ! -e "${key_file}" ]]; then + die "Missing key file: ${key_file}" + fi + + if [[ -d "${output}" ]]; then + output="${output}/${base_name}.bin.prod" + fi + + sign_gsc_firmware \ + "${key_file}" \ + "${manifest_file}" \ + "${input}/fuses.xml" \ + "${input}" \ + "${input}/prod.ro.A" \ + "${input}/prod.ro.B" \ + "${rw_a}" \ + "${rw_b}" \ + "${output}" \ + "${generation}" +} + +main() { + if [[ $# -ne 3 ]]; then + flags_help + exit 1 + fi + + local input="${1%/}" + local key_dir="$2" + local output="$3" + + local signing_instructions="${input}/signing_instructions.sh" + + if [[ -f ${signing_instructions} ]]; then + . "${signing_instructions}" + else + die "${signing_instructions} not found" + fi + + if [[ ! -d "${input}" ]]; then + die "Missing input directory: ${input}" + fi + + sign_gsc_firmware_dir "${input}" "${key_dir}" "${output}" +} +main "$@" diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/sign_official_build.sh vboot-utils-0~R99-14469.B/scripts/image_signing/sign_official_build.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/sign_official_build.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/sign_official_build.sh 2022-02-11 14:46:09.000000000 +0000 @@ -9,15 +9,13 @@ # Prerequisite tools needed in the system path: # # futility (from src/platform/vboot_reference) -# vbutil_kernel (from src/platform/vboot_reference) -# vbutil_key (from src/platform/vboot_reference) -# cgpt (from src/platform/vboot_reference) -# dump_kernel_config (from src/platform/vboot_reference) -# verity (from src/platform/verity) +# verity (from src/platform2/verity) # load_kernel_test (from src/platform/vboot_reference) # dumpe2fs +# e2fsck # sha1sum -# cbfstool (from src/third_party/coreboot) + +MINIOS_KERNEL_GUID="09845860-705f-4bb5-b16c-8a8a099caf52" # Load common constants and variables. . "$(dirname "$0")/common.sh" @@ -27,19 +25,15 @@ cat < input_image /path/to/keys/dir [output_image] [version_file] where is one of: - ssd (sign an SSD image) - base (sign a base image, similar to an SSD image) + base (sign a base image) recovery (sign a USB recovery image) factory (sign a factory install image) update_payload (sign a delta update hash) - kernel (sign a kernel image) - recovery_kernel (sign a recovery_kernel image) firmware (sign a firmware image) - usb (sign an image to boot directly from USB) verify (verify an image including rootfs hashes) accessory_usbpd (sign USB-PD accessory firmware) accessory_rwsig (sign accessory RW firmware) - cr50_firmware (sign a cr50 firmware image) + gsc_firmware (sign a GSC firmware image) output_image: File name of the signed output image version_file: File name of where to read the kernel and firmware versions. @@ -84,8 +78,7 @@ PATH=$PATH:/usr/sbin:/sbin # Make sure the tools we need are available. -for prereqs in ${FUTILITY} vbutil_kernel cgpt dump_kernel_config verity \ - cbfstool load_kernel_test dumpe2fs sha1sum e2fsck; do +for prereqs in ${FUTILITY} verity load_kernel_test dumpe2fs e2fsck sha1sum; do type -P "${prereqs}" &>/dev/null || \ die "${prereqs} tool not found." done @@ -117,28 +110,30 @@ get_hash_from_config() { local kernel_config=$1 local dm_config=$(get_dmparams_from_config "${kernel_config}") - local vroot_dev=$(get_dm_slave "${dm_config}" vroot) + local vroot_dev=$(get_dm_device "${dm_config}" vroot) echo $(get_verity_arg "${vroot_dev}" root_hexdigest) } -# Get the slave device and its args -# get_dm_ags $dm_config [vboot|vroot] -# Assumes we have only one slave device per device -get_dm_slave() { +# Get the mapped device and its args. +# Usage: +# get_dm_device $dm_config [vboot|vroot] +# Assumes we have only one mapped device per device. +get_dm_device() { local dm=$1 local device=$2 echo $(echo "${dm}" | sed -nre "s/.*${device}[^,]*,([^,]*).*/\1/p") } -# Set the slave device and its args for a device -# get_dm_ags $dm_config [vboot|vroot] args -# Assumes we have only one slave device per device -set_dm_slave() { +# Set the mapped device and its args for a device. +# Usage: +# set_dm_device $dm_config [vboot|vroot] args +# Assumes we have only one mapped device per device. +set_dm_device() { local dm=$1 local device=$2 - local slave=$3 + local args=$3 echo $(echo "${dm}" | - sed -nre "s#(.*${device}[^,]*,)([^,]*)(.*)#\1${slave}\3#p") + sed -nre "s#(.*${device}[^,]*,)([^,]*)(.*)#\1${args}\3#p") } CALCULATED_KERNEL_CONFIG= @@ -161,7 +156,7 @@ warn "Couldn't grab dm_config. Aborting rootfs hash calculation." return 1 fi - local vroot_dev=$(get_dm_slave "${dm_config}" vroot) + local vroot_dev=$(get_dm_device "${dm_config}" vroot) # Extract the key-value parameters from the kernel command line. local rootfs_sectors=$(get_verity_arg "${vroot_dev}" hashstart) @@ -176,15 +171,15 @@ fi # Run the verity tool on the rootfs partition. - local slave=$(sudo verity mode=create \ + local table=$(sudo verity mode=create \ alg=${verity_algorithm} \ payload="${rootfs_image}" \ payload_blocks=$((rootfs_sectors / 8)) \ hashtree="${hash_image}" ${salt_arg}) # Reconstruct new kernel config command line and replace placeholders. - slave="$(echo "${slave}" | + table="$(echo "${table}" | sed -s "s|ROOT_DEV|${root_dev}|g;s|HASH_DEV|${hash_dev}|")" - CALCULATED_DM_ARGS="$(set_dm_slave "${dm_config}" vroot "${slave}")" + CALCULATED_DM_ARGS="$(set_dm_device "${dm_config}" vroot "${table}")" CALCULATED_KERNEL_CONFIG="$(echo "${kernel_config}" | sed -e 's#\(.*dm="\)\([^"]*\)\(".*\)'"#\1${CALCULATED_DM_ARGS}\3#g")" } @@ -214,7 +209,7 @@ info "Updating rootfs hash and updating config for Kernel partitions" # If we can't find dm parameters in the kernel config, bail out now. - local kernel_config=$(sudo dump_kernel_config "${loop_kern}") + local kernel_config=$(sudo ${FUTILITY} dump_kernel_config "${loop_kern}") local dm_config=$(get_dmparams_from_config "${kernel_config}") if [ -z "${dm_config}" ]; then error "Couldn't grab dm_config from kernel ${loop_kern}" @@ -265,7 +260,7 @@ for kernelpart in 2 4; do loop_kern="${loopdev}p${kernelpart}" if ! new_kernel_config="$( - sudo dump_kernel_config "${loop_kern}" 2>/dev/null)" && + sudo ${FUTILITY} dump_kernel_config "${loop_kern}" 2>/dev/null)" && [[ "${kernelpart}" == 4 ]]; then # Legacy images don't have partition 4. info "Skipping empty kernel partition 4 (legacy images)." @@ -283,7 +278,7 @@ keyblock="${kern_b_keyblock}" priv_key="${kern_b_privkey}" fi - sudo vbutil_kernel --repack "${loop_kern}" \ + sudo ${FUTILITY} vbutil_kernel --repack "${loop_kern}" \ --keyblock ${keyblock} \ --signprivate ${priv_key} \ --version "${KERNEL_VERSION}" \ @@ -302,13 +297,13 @@ local temp_out_vb="$(make_temp_file)" local loop_kern="${loopdev}p4" - if [[ -z "$(sudo dump_kernel_config "${loop_kern}" 2>/dev/null)" ]]; then + if [[ -z "$(sudo ${FUTILITY} dump_kernel_config "${loop_kern}" 2>/dev/null)" ]]; then info "Building vmlinuz_hd.vblock from legacy image partition 2." loop_kern="${loopdev}p2" fi # vblock should always use kernel keyblock. - sudo vbutil_kernel --repack "${temp_out_vb}" \ + sudo ${FUTILITY} vbutil_kernel --repack "${temp_out_vb}" \ --keyblock "${KEY_DIR}/kernel.keyblock" \ --signprivate "${KEY_DIR}/kernel_data_key.vbprivk" \ --oldblob "${loop_kern}" \ @@ -402,52 +397,6 @@ info "Signed firmware image output to ${image}" } -# Sign a kernel in-place with the given keys. -# Args: KERNEL_IMAGE KEY_DIR KERNEL_VERSION -sign_kernel() { - local image=$1 - local key_dir=$2 - local kernel_version=$3 - - # Note: Although vbutil_kernel may correctly handle specifying the same - # output file as the input file, we do not want to rely on it correctly - # handing that. Hence, the use of a temporary file. - local temp_kernel=$(make_temp_file) - - # Resign the kernel with new keys. - vbutil_kernel --repack "${temp_kernel}" \ - --keyblock "${key_dir}/kernel.keyblock" \ - --signprivate "${key_dir}/kernel_data_key.vbprivk" \ - --version "${kernel_version}" \ - --oldblob "${image}" - - mv "${temp_kernel}" "${image}" - info "Signed kernel image output to ${image}" -} - -# Sign a recovery kernel in-place with the given keys. -# Args: KERNEL_IMAGE KEY_DIR KERNEL_VERSION -sign_recovery_kernel() { - local image=$1 - local key_dir=$2 - local kernel_version=$3 - - # Note: Although vbutil_kernel may correctly handle specifying the same - # output file as the input file, we do not want to rely on it correctly - # handing that. Hence, the use of a temporary file. - local temp_kernel=$(make_temp_file) - - # Resign the kernel with new recovery keys. - vbutil_kernel --repack "${temp_kernel}" \ - --keyblock "${key_dir}/recovery_kernel.keyblock" \ - --signprivate "${key_dir}/recovery_kernel_data_key.vbprivk" \ - --version "${kernel_version}" \ - --oldblob "${image}" - - mv "${temp_kernel}" "${image}" - info "Signed recovery_kernel image output to ${image}" -} - # Sign a delta update payload (usually created by paygen). # Args: INPUT_IMAGE KEY_DIR OUTPUT_IMAGE sign_update_payload() { @@ -464,7 +413,7 @@ [8192]=10 ) - key_output=$(futility show "${key_file}") + key_output=$(${FUTILITY} show "${key_file}") key_size=$(echo "${key_output}" | sed -n '/Key length/s/[^0-9]*//p') algo=${algos[${key_size}]} if [[ -z ${algo} ]]; then @@ -681,20 +630,23 @@ echo "Signed with keyset in $(readlink -f "${KEY_DIR}") ." >>"${signer_notes}" # record recovery_key key="${KEY_DIR}/recovery_key.vbpubk" - sha1=$(vbutil_key --unpack "${key}" | grep sha1sum | cut -d" " -f9) + sha1=$(${FUTILITY} vbutil_key --unpack "${key}" \ + | grep sha1sum | cut -d" " -f9) echo "recovery: ${sha1}" >>"${signer_notes}" # record root_key(s) if [[ -d "${shellball_keyset_dir}" ]]; then echo "List sha1sum of all loem/model's signatures:" >>"${signer_notes}" for key in "${shellball_keyset_dir}"/rootkey.*; do model="${key##*.}" - sha1=$(vbutil_key --unpack "${key}" | grep sha1sum | cut -d" " -f9) + sha1=$(${FUTILITY} vbutil_key --unpack "${key}" \ + | grep sha1sum | cut -d" " -f9) echo " ${model}: ${sha1}" >>"${signer_notes}" done else echo "List sha1sum of single key's signature:" >>"${signer_notes}" key="${KEY_DIR}/root_key.vbpubk" - sha1=$(vbutil_key --unpack "${key}" | grep sha1sum | cut -d" " -f9) + sha1=$(${FUTILITY} vbutil_key --unpack "${key}" \ + | grep sha1sum | cut -d" " -f9) echo " root: ${sha1}" >>"${signer_notes}" fi @@ -759,6 +711,7 @@ # Args: LOOPDEV sign_uefi_binaries() { local loopdev="$1" + local efi_glob="*.efi" if [[ ! -d "${KEY_DIR}/uefi" ]]; then return 0 @@ -771,13 +724,22 @@ elif [[ -z "${esp_dir}" ]]; then return 0 fi - "${SCRIPT_DIR}/install_gsetup_certs.sh" "${esp_dir}" "${KEY_DIR}/uefi" - "${SCRIPT_DIR}/sign_uefi.sh" "${esp_dir}" "${KEY_DIR}/uefi" + # TODO(b/199136347): First class this as an arg and pass from config + # in the signing repo. This is a temporary fix to unblock reven-release. + if [[ "${KEY_DIR}" != *"Reven"* ]]; then + "${SCRIPT_DIR}/install_gsetup_certs.sh" "${esp_dir}" "${KEY_DIR}/uefi" + else + # b/205145491: the reven board's boot*.efi files are already signed, + # change the glob so that they don't get resigned. + efi_glob="grub*.efi" + fi + "${SCRIPT_DIR}/sign_uefi.sh" "${esp_dir}" "${KEY_DIR}/uefi" "${efi_glob}" sudo umount "${esp_dir}" local rootfs_dir="$(make_temp_dir)" mount_loop_image_partition "${loopdev}" 3 "${rootfs_dir}" - "${SCRIPT_DIR}/sign_uefi.sh" "${rootfs_dir}/boot" "${KEY_DIR}/uefi" + "${SCRIPT_DIR}/sign_uefi.sh" "${rootfs_dir}/boot" "${KEY_DIR}/uefi" \ + "${efi_glob}" sudo umount "${rootfs_dir}" info "Signed UEFI binaries" @@ -817,14 +779,14 @@ fi } -# Sign a cr50 firmware image with the given keys. +# Sign a GSC firmware image with the given keys. # Args: CONTAINER KEY_DIR [OUTPUT_CONTAINER] -sign_cr50_firmware() { +sign_gsc_firmware() { local image=$1 local key_dir=$2 local output=$3 - "${SCRIPT_DIR}/sign_cr50_firmware.sh" \ + "${SCRIPT_DIR}/sign_gsc_firmware.sh" \ "${image}" "${key_dir}" "${output}" } @@ -843,7 +805,7 @@ local partnum for partnum in 2 4; do info "Considering Kernel partition ${partnum}" - kernel_config=$(sudo dump_kernel_config "${loopdev}p${partnum}") + kernel_config=$(sudo ${FUTILITY} dump_kernel_config "${loopdev}p${partnum}") local hash_image=$(make_temp_file) if ! calculate_rootfs_hash "${loop_rootfs}" "${kernel_config}" \ "${hash_image}"; then @@ -911,7 +873,8 @@ local loop_kernb="${loopdev}p4" # Update the Kernel B hash in Kernel A command line - local old_kerna_config="$(sudo dump_kernel_config "${loop_kerna}")" + local old_kerna_config="$(sudo ${FUTILITY} \ + dump_kernel_config "${loop_kerna}")" local old_kernb_hash="$(echo "$old_kerna_config" | sed -nEe "s#.*kern_b_hash=([a-z0-9]*).*#\1#p")" if [[ "${#old_kernb_hash}" -lt 64 ]]; then @@ -928,7 +891,7 @@ cat ${new_kerna_config} # Re-calculate kernel partition signature and command line. - sudo vbutil_kernel --repack "${loop_kerna}" \ + sudo ${FUTILITY} vbutil_kernel --repack "${loop_kerna}" \ --keyblock ${KEY_DIR}/recovery_kernel.keyblock \ --signprivate ${KEY_DIR}/recovery_kernel_data_key.vbprivk \ --version "${KERNEL_VERSION}" \ @@ -936,6 +899,58 @@ --config ${new_kerna_config} } +# Re-sign miniOS kernels with new keys. +# Args: LOOPDEV KEYBLOCK PRIVKEY +resign_minios_kernels() { + local loopdev="$1" + local keyblock="$2" + local priv_key="$3" + + info "Searching for miniOS kernels to resign..." + + local loop_minios + for loop_minios in "${loopdev}p"*; do + local part_type_guid + part_type_guid=$(sudo lsblk -rnb -o PARTTYPE "${loop_minios}") + if [[ "${part_type_guid}" != "${MINIOS_KERNEL_GUID}" ]]; then + continue + fi + + # Skip miniOS partitions which are empty. This happens when miniOS + # kernels aren't written to the partitions because the feature is not + # enabled. + if ! sudo "${FUTILITY}" dump_kernel_config "${loop_minios}"; then + info "Skipping empty miniOS partition ${loop_minios}." + continue + fi + + # Delay checking that keyblock and private key exist until we are certain + # of a valid miniOS partition. Images that don't support miniOS might not + # provide these. (This check is repeated twice, but that's okay.) + if [[ ! -e "${keyblock}" ]]; then + error "Resign miniOS: keyblock doesn't exist: ${keyblock}" + return 1 + fi + if [[ ! -e "${priv_key}" ]]; then + error "Resign miniOS: private key doesn't exist: ${priv_key}" + return 1 + fi + + # Assume this is a miniOS kernel. + local minios_kernel_version=$((KERNEL_VERSION >> 24)) + if sudo ${FUTILITY} vbutil_kernel --repack "${loop_minios}" \ + --keyblock "${keyblock}" \ + --signprivate "${priv_key}" \ + --version "${minios_kernel_version}" \ + --oldblob "${loop_minios}"; then + info "Resign miniOS ${loop_minios}: done" + else + error "Resign miniOS ${loop_minios}: failed" + return 1 + fi + done +} + # Update the legacy bootloader templates in EFI partition if available. # Args: LOOPDEV KERNEL update_legacy_bootloader() { @@ -952,7 +967,7 @@ fi # If we can't find the dm parameter in the kernel config, bail out now. - local kernel_config=$(sudo dump_kernel_config "${loop_kern}") + local kernel_config=$(sudo ${FUTILITY} dump_kernel_config "${loop_kern}") local root_hexdigest="$(get_hash_from_config "${kernel_config}")" if [[ -z "${root_hexdigest}" ]]; then error "Couldn't grab root_digest from kernel partition ${loop_kern}" @@ -983,7 +998,7 @@ # Sign an image file with proper keys. # Args: IMAGE_TYPE INPUT OUTPUT DM_PARTNO KERN_A_KEYBLOCK KERN_A_PRIVKEY \ -# KERN_B_KEYBLOCK KERN_B_PRIVKEY +# KERN_B_KEYBLOCK KERN_B_PRIVKEY MINIOS_KEYBLOCK MINIOS_PRIVKEY # # A ChromiumOS image file (INPUT) always contains 2 partitions (kernel A & B). # This function will rebuild hash data by DM_PARTNO, resign kernel partitions by @@ -1000,6 +1015,8 @@ local kernA_privkey="$6" local kernB_keyblock="$7" local kernB_privkey="$8" + local minios_keyblock="$9" + local minios_privkey="${10}" info "Preparing ${image_type} image..." cp --sparse=always "${input}" "${output}" @@ -1020,7 +1037,7 @@ # /boot in rootfs to update kernel. We infer the BIOS type from the kernel # config. local loop_kerna="${loopdev}p2" - local kerna_config="$(sudo dump_kernel_config "${loop_kerna}")" + local kerna_config="$(sudo ${FUTILITY} dump_kernel_config "${loop_kerna}")" if [[ "${image_type}" != "factory_install" && " ${kerna_config} " != *" cros_legacy "* && " ${kerna_config} " != *" cros_efi "* ]]; then @@ -1033,6 +1050,10 @@ if [[ "${image_type}" == "recovery" ]]; then update_recovery_kernel_hash "${loopdev}" fi + if ! resign_minios_kernels "${loopdev}" "${minios_keyblock}" \ + "${minios_privkey}"; then + return 1 + fi if ! update_legacy_bootloader "${loopdev}" "${loop_kern}"; then # Error is already logged. return 1 @@ -1047,7 +1068,7 @@ loopdev=$(loopback_partscan "${INPUT_IMAGE}") for partnum in 2 4; do info "kernel config in partition number ${partnum}:" - sudo dump_kernel_config "${loopdev}p${partnum}" + sudo ${FUTILITY} dump_kernel_config "${loopdev}p${partnum}" echo done exit 0 @@ -1077,46 +1098,36 @@ info "Using kernel version: ${KERNEL_VERSION}" # Make all modifications on output copy. -if [[ "${TYPE}" == "ssd" || "${TYPE}" == "base" ]]; then - sign_image_file "SSD" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ - "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk" \ - "${KEY_DIR}/kernel.keyblock" "${KEY_DIR}/kernel_data_key.vbprivk" -elif [[ "${TYPE}" == "usb" ]]; then - sign_image_file "USB" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ - "${KEY_DIR}/recovery_kernel.keyblock" \ - "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \ +if [[ "${TYPE}" == "base" ]]; then + sign_image_file "base" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ "${KEY_DIR}/kernel.keyblock" \ - "${KEY_DIR}/kernel_data_key.vbprivk" + "${KEY_DIR}/kernel_data_key.vbprivk" \ + "${KEY_DIR}/kernel.keyblock" \ + "${KEY_DIR}/kernel_data_key.vbprivk" \ + "${KEY_DIR}/minios_kernel.keyblock" \ + "${KEY_DIR}/minios_kernel_data_key.vbprivk" elif [[ "${TYPE}" == "recovery" ]]; then sign_image_file "recovery" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 4 \ "${KEY_DIR}/recovery_kernel.keyblock" \ "${KEY_DIR}/recovery_kernel_data_key.vbprivk" \ "${KEY_DIR}/kernel.keyblock" \ - "${KEY_DIR}/kernel_data_key.vbprivk" + "${KEY_DIR}/kernel_data_key.vbprivk" \ + "${KEY_DIR}/minios_kernel.keyblock" \ + "${KEY_DIR}/minios_kernel_data_key.vbprivk" elif [[ "${TYPE}" == "factory" ]]; then sign_image_file "factory_install" "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" 2 \ "${KEY_DIR}/installer_kernel.keyblock" \ "${KEY_DIR}/installer_kernel_data_key.vbprivk" \ "${KEY_DIR}/kernel.keyblock" \ - "${KEY_DIR}/kernel_data_key.vbprivk" + "${KEY_DIR}/kernel_data_key.vbprivk" \ + "${KEY_DIR}/minios_kernel.keyblock" \ + "${KEY_DIR}/minios_kernel_data_key.vbprivk" elif [[ "${TYPE}" == "firmware" ]]; then if [[ -e "${KEY_DIR}/loem.ini" ]]; then die "LOEM signing not implemented yet for firmware images" fi cp ${INPUT_IMAGE} ${OUTPUT_IMAGE} sign_firmware ${OUTPUT_IMAGE} ${KEY_DIR} ${FIRMWARE_VERSION} -elif [[ "${TYPE}" == "kernel" ]]; then - if [[ -e "${KEY_DIR}/loem.ini" ]]; then - die "LOEM signing not implemented yet for kernel images" - fi - cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" - sign_kernel "${OUTPUT_IMAGE}" "${KEY_DIR}" "${KERNEL_VERSION}" -elif [[ "${TYPE}" == "recovery_kernel" ]]; then - if [[ -e "${KEY_DIR}/loem.ini" ]]; then - die "LOEM signing not implemented yet for recovery_kernel images" - fi - cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" - sign_recovery_kernel "${OUTPUT_IMAGE}" "${KEY_DIR}" "${KERNEL_VERSION}" elif [[ "${TYPE}" == "update_payload" ]]; then sign_update_payload ${INPUT_IMAGE} ${KEY_DIR} ${OUTPUT_IMAGE} elif [[ "${TYPE}" == "accessory_usbpd" ]]; then @@ -1125,7 +1136,7 @@ KEY_NAME="${KEY_DIR}/key" fi cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" - futility sign --type usbpd1 --pem "${KEY_NAME}.pem" "${OUTPUT_IMAGE}" + ${FUTILITY} sign --type usbpd1 --pem "${KEY_NAME}.pem" "${OUTPUT_IMAGE}" elif [[ "${TYPE}" == "accessory_rwsig" ]]; then # If one key is present in this container, assume it's the right one. # See crbug.com/863464 @@ -1138,10 +1149,10 @@ fi fi cp "${INPUT_IMAGE}" "${OUTPUT_IMAGE}" - futility sign --type rwsig --prikey "${KEY_NAME}" \ + ${FUTILITY} sign --type rwsig --prikey "${KEY_NAME}" \ --version "${FIRMWARE_VERSION}" "${OUTPUT_IMAGE}" -elif [[ "${TYPE}" == "cr50_firmware" ]]; then - sign_cr50_firmware "${INPUT_IMAGE}" "${KEY_DIR}" "${OUTPUT_IMAGE}" +elif [[ "${TYPE}" == "gsc_firmware" ]]; then + sign_gsc_firmware "${INPUT_IMAGE}" "${KEY_DIR}" "${OUTPUT_IMAGE}" else die "Invalid type ${TYPE}" fi diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/sign_uefi.sh vboot-utils-0~R99-14469.B/scripts/image_signing/sign_uefi.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/sign_uefi.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/sign_uefi.sh 2022-02-11 14:46:09.000000000 +0000 @@ -9,7 +9,7 @@ usage() { cat </dev/null; then @@ -84,7 +85,8 @@ local working_dir="$(make_temp_dir)" local efi_file - for efi_file in "${bootloader_dir}"/*.efi; do + # Leave ${efi_glob} unquoted so that globbing occurs. + for efi_file in "${bootloader_dir}"/${efi_glob}; do if [[ ! -f "${efi_file}" ]]; then continue fi diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/strip_boot_from_image.sh vboot-utils-0~R99-14469.B/scripts/image_signing/strip_boot_from_image.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/strip_boot_from_image.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/strip_boot_from_image.sh 2022-02-11 14:46:09.000000000 +0000 @@ -27,7 +27,7 @@ local rootfs="$1" info "Zeroing freespace in ${rootfs}" - sudo fstrim -v "${rootfs}" + sudo sfill -llz "${rootfs}" } diff -Nru vboot-utils-0~R88-13597.B/scripts/image_signing/tag_image.sh vboot-utils-0~R99-14469.B/scripts/image_signing/tag_image.sh --- vboot-utils-0~R88-13597.B/scripts/image_signing/tag_image.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/image_signing/tag_image.sh 2022-02-11 14:46:09.000000000 +0000 @@ -196,9 +196,13 @@ fi # First round, mount as read-only and check if we need any modifications. -loopdev=$(loopback_partscan "${IMAGE}") -rootfs=$(make_temp_dir) -mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" +if [[ -d "${IMAGE}" ]]; then + rootfs="${IMAGE}" +else + loopdev=$(loopback_partscan "${IMAGE}") + rootfs=$(make_temp_dir) + mount_loop_image_partition_ro "${loopdev}" 3 "${rootfs}" +fi # we don't have tags in stateful partition yet... # stateful_dir=$(make_temp_dir) @@ -210,8 +214,10 @@ if [ ${g_modified} = ${FLAGS_TRUE} ]; then # Remount as RW. We can't use `mount -o rw,remount` because of the bits in # the ext4 header we've set to block that. See enable_rw_mount for details. - sudo umount "${rootfs}" - mount_loop_image_partition "${loopdev}" 3 "${rootfs}" + if [[ ! -d "${IMAGE}" ]]; then + sudo umount "${rootfs}" + mount_loop_image_partition "${loopdev}" 3 "${rootfs}" + fi # second round, apply the modification to image. process_all_tags "${rootfs}" ${FLAGS_TRUE} diff -Nru vboot-utils-0~R88-13597.B/scripts/keygeneration/common.sh vboot-utils-0~R99-14469.B/scripts/keygeneration/common.sh --- vboot-utils-0~R88-13597.B/scripts/keygeneration/common.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/keygeneration/common.sh 2022-02-11 14:46:09.000000000 +0000 @@ -58,18 +58,36 @@ DEV_FIRMWARE_DATAKEY_ALGOID=${RSA4096_SHA256_ALGOID} RECOVERY_KERNEL_ALGOID=${RSA4096_SHA512_ALGOID} +MINIOS_KERNEL_ALGOID=${RSA4096_SHA512_ALGOID} INSTALLER_KERNEL_ALGOID=${RSA4096_SHA512_ALGOID} KERNEL_SUBKEY_ALGOID=${RSA4096_SHA256_ALGOID} KERNEL_DATAKEY_ALGOID=${RSA2048_SHA256_ALGOID} +# AP RO Verification. +ARV_ROOT_ALGOID=${RSA4096_SHA256_ALGOID} +ARV_PLATFORM_ALGOID=${RSA4096_SHA256_ALGOID} + # Keyblock modes determine which boot modes a signing key is valid for use # in verification. -EC_KEYBLOCK_MODE=7 # Only allow RW EC firmware in non-recovery. -FIRMWARE_KEYBLOCK_MODE=7 # Only allow RW firmware in non-recovery. -DEV_FIRMWARE_KEYBLOCK_MODE=6 # Only allow in dev mode. -RECOVERY_KERNEL_KEYBLOCK_MODE=11 # Only in recovery mode. -KERNEL_KEYBLOCK_MODE=7 # Only allow in non-recovery. -INSTALLER_KERNEL_KEYBLOCK_MODE=10 # Only allow in Dev + Recovery. +# !DEV 0x1 DEV 0x2 +# !REC 0x4 REC 0x8 +# !MINIOS 0x10 MINIOS 0x20 +# Note that firmware keyblock modes are not used. Consider deprecating. + +# Only allow RW EC firmware in non-recovery + non-miniOS. +EC_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x4 | 0x10)) +# Only allow RW firmware in non-recovery + non-miniOS. +FIRMWARE_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x4 | 0x10)) +# Only allow in dev mode + non-recovery + non-miniOS. +DEV_FIRMWARE_KEYBLOCK_MODE=$((0x2 | 0x4 | 0x10)) +# Only allow in recovery mode + non-miniOS. +RECOVERY_KERNEL_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x8 | 0x10)) +# Only allow in recovery mode + miniOS. +MINIOS_KERNEL_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x8 | 0x20)) +# Only allow in non-recovery + non-miniOS. +KERNEL_KEYBLOCK_MODE=$((0x1 | 0x2 | 0x4 | 0x10)) +# Only allow in dev + recovery + non-miniOS. +INSTALLER_KERNEL_KEYBLOCK_MODE=$((0x2 | 0x8 | 0x10)) # Emit .vbpubk and .vbprivk using given basename and algorithm # NOTE: This function also appears in ../../utility/dev_make_keypair. Making @@ -125,6 +143,8 @@ # 0x02 Developer switch on # 0x04 Not recovery mode # 0x08 Recovery mode +# 0x10 Not miniOS mode +# 0x20 miniOS mode make_keyblock() { local base=$1 local flags=$2 diff -Nru vboot-utils-0~R88-13597.B/scripts/keygeneration/create_new_keys.sh vboot-utils-0~R99-14469.B/scripts/keygeneration/create_new_keys.sh --- vboot-utils-0~R88-13597.B/scripts/keygeneration/create_new_keys.sh 2020-12-01 09:49:27.000000000 +0000 +++ vboot-utils-0~R99-14469.B/scripts/keygeneration/create_new_keys.sh 2022-02-11 14:46:09.000000000 +0000 @@ -43,6 +43,7 @@ local root_key_algoid=${ROOT_KEY_ALGOID} local recovery_key_algoid=${RECOVERY_KEY_ALGOID} local recovery_kernel_algoid=${RECOVERY_KERNEL_ALGOID} + local minios_kernel_algoid=${MINIOS_KERNEL_ALGOID} local installer_kernel_algoid=${INSTALLER_KERNEL_ALGOID} local keyname local output_dir="${PWD}" setperms="false" @@ -166,7 +167,10 @@ # Create the recovery and factory installer keypairs make_pair recovery_key ${recovery_key_algoid} make_pair recovery_kernel_data_key ${recovery_kernel_algoid} + make_pair minios_kernel_data_key ${minios_kernel_algoid} make_pair installer_kernel_data_key ${installer_kernel_algoid} + make_pair arv_root ${ARV_ROOT_ALGOID} + make_pair arv_platform ${ARV_PLATFORM_ALGOID} # Create the firmware keyblock for use only in Normal mode. This is redundant, # since it's never even checked during Recovery mode. @@ -182,6 +186,9 @@ # Create the recovery kernel keyblock for use only in Recovery mode. make_keyblock recovery_kernel ${RECOVERY_KERNEL_KEYBLOCK_MODE} recovery_kernel_data_key recovery_key + # Create the miniOS kernel keyblock for use only in miniOS mode. + make_keyblock minios_kernel ${MINIOS_KERNEL_KEYBLOCK_MODE} minios_kernel_data_key recovery_key + # Create the normal kernel keyblock for use only in Normal mode. make_keyblock kernel ${KERNEL_KEYBLOCK_MODE} kernel_data_key kernel_subkey Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/android/networkstack.pk8 and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/android/networkstack.pk8 differ diff -Nru vboot-utils-0~R88-13597.B/tests/devkeys/android/networkstack.x509.pem vboot-utils-0~R99-14469.B/tests/devkeys/android/networkstack.x509.pem --- vboot-utils-0~R88-13597.B/tests/devkeys/android/networkstack.x509.pem 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/devkeys/android/networkstack.x509.pem 2022-02-11 14:46:09.000000000 +0000 @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxzCCAq+gAwIBAgIUcfGSt74kh+tpBdU4k71ijVm1/0cwDQYJKoZIhvcNAQEL +BQAwdDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM +DU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSBJbmMuMRAwDgYDVQQLDAdB +bmRyb2lkMRAwDgYDVQQDDAdBbmRyb2lkMB4XDTIxMDQwNTIzMDk1NloXDTQ4MDgy +MTIzMDk1NlowdDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAU +BgNVBAcMDU1vdW50YWluIFZpZXcxFDASBgNVBAoMC0dvb2dsZSBJbmMuMRAwDgYD +VQQLDAdBbmRyb2lkMRAwDgYDVQQDDAdBbmRyb2lkMIIBIDANBgkqhkiG9w0BAQEF +AAOCAQ0AMIIBCAKCAQEA0KHW5P5+dCq7OkVkGRmG0eYskcbgRK3DvTY7QPXCdnOm +Fmq08S2l23mN1C+3+XMon0/Gh3DRr+lVLX3GZPoHX3e2ZTt8tu0Ee3k8T8VopfG9 +OpPlSzfazgI8sKtLe3wJ3RDalTlNd8Ne2YNRMY8RIkIwbySzUqkTixVk57NgMXpj +tWmP19DOZPxXsGUa5m0qSS5/demnYAIoD+mg0Wd+xG2Y1ErT9O/j2l92ekm8+JKy +jJ0W47el/mqO392JgNAEvcI9NbrnTaNi5Zq2PKhBhK0ohXOMyHUodUSmtBTWtW8n +U+FK70ese+OzWQbjRryrmGYWB9ybc7YZ/FhH4US+rwIBA6NTMFEwHQYDVR0OBBYE +FMGqz0YmVUA8iWBwLCMdoTFsidIiMB8GA1UdIwQYMBaAFMGqz0YmVUA8iWBwLCMd +oTFsidIiMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAKygSG3r +7SHEb/nox88Pu31lxERrsjmNCtxJJMFlbf8sq1nWx59lmTLOW5sFKyWGH1Mf8f8O +nXiZ6V+5obyAt05MJOBiSIGKBk21ds9r2ACCuFpJ+MAS3SNN7HlSfNvzRbGV3+gb +V6FOH+2ndbqN3dkXUDctWXjNiq5QQlFFI4fIvvwiul45HZvDRrNRuexT1jzOlLVF +Qe45E5QbJYVPMUe37kCVm1Ty3N+e/s2n1NsSHoD5BK+kvb+BPL3pK4dK62HzcdVp +TB1EZFtrL8+aun1qhlEYNKlR/TNQdIPwZWH6ZmT7bF2GCfJcxshgWmajN/cW1rdc +OEUdUtGkI9lgNiI= +-----END CERTIFICATE----- Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/arv_platform.vbprivk and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/arv_platform.vbprivk differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/arv_platform.vbpubk and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/arv_platform.vbpubk differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/arv_root.vbprivk and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/arv_root.vbprivk differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/arv_root.vbpubk and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/arv_root.vbpubk differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/ec.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/ec.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/firmware.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/firmware.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/installer_kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/installer_kernel.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/kernel.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/minios_kernel_data_key.vbprivk and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/minios_kernel_data_key.vbprivk differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/minios_kernel_data_key.vbpubk and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/minios_kernel_data_key.vbpubk differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/minios_kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/minios_kernel.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/devkeys/recovery_kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/devkeys/recovery_kernel.keyblock differ diff -Nru vboot-utils-0~R88-13597.B/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock vboot-utils-0~R99-14469.B/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock --- vboot-utils-0~R88-13597.B/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock 2020-12-01 09:49:33.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/futility/expect_output/show.tests_devkeys_kernel.keyblock 2022-02-11 14:46:17.000000000 +0000 @@ -1,7 +1,7 @@ Keyblock: tests/devkeys/kernel.keyblock Signature: ignored Size: 0x4b8 - Flags: 7 !DEV DEV !REC + Flags: 23 !DEV DEV !REC !MINIOS Data key algorithm: 4 RSA2048 SHA256 Data key version: 1 Data key sha1sum: d6170aa480136f1f29cf339a5ab1b960585fa444 diff -Nru vboot-utils-0~R88-13597.B/tests/futility/expect_output/vbutil_firmware.verify vboot-utils-0~R99-14469.B/tests/futility/expect_output/vbutil_firmware.verify --- vboot-utils-0~R88-13597.B/tests/futility/expect_output/vbutil_firmware.verify 2020-12-01 09:49:33.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/futility/expect_output/vbutil_firmware.verify 2022-02-11 14:46:17.000000000 +0000 @@ -1,6 +1,6 @@ Keyblock: Size: 2232 - Flags: 7 (ignored) + Flags: 23 (ignored) Data key algorithm: 7 RSA4096 SHA256 Data key version: 1 Data key sha1sum: e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450 diff -Nru vboot-utils-0~R88-13597.B/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock vboot-utils-0~R99-14469.B/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock --- vboot-utils-0~R88-13597.B/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock 2020-12-01 09:49:33.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/futility/expect_output/vbutil_keyblock.tests_devkeys_kernel.keyblock 2022-02-11 14:46:17.000000000 +0000 @@ -1,6 +1,6 @@ Keyblock file: tests/devkeys/kernel.keyblock Signature valid -Flags: 7 !DEV DEV !REC +Flags: 23 !DEV DEV !REC !MINIOS Data key algorithm: 4 RSA2048 SHA256 Data key version: 1 Data key sha1sum: d6170aa480136f1f29cf339a5ab1b960585fa444 diff -Nru vboot-utils-0~R88-13597.B/tests/futility/test_sign_keyblocks.sh vboot-utils-0~R99-14469.B/tests/futility/test_sign_keyblocks.sh --- vboot-utils-0~R88-13597.B/tests/futility/test_sign_keyblocks.sh 2020-12-01 09:49:33.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/futility/test_sign_keyblocks.sh 2022-02-11 14:46:17.000000000 +0000 @@ -18,7 +18,7 @@ # Create a copy of an existing keyblock, using the old way ${FUTILITY} vbutil_keyblock --pack ${TMP}.keyblock0 \ --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \ - --flags 7 \ + --flags 23 \ --signprivate ${DEVKEYS}/root_key.vbprivk # Check it. @@ -32,7 +32,7 @@ # Now create it the new way ${FUTILITY} --debug sign \ --datapubkey ${DEVKEYS}/firmware_data_key.vbpubk \ - --flags 7 \ + --flags 23 \ --signprivate ${DEVKEYS}/root_key.vbprivk \ --outfile ${TMP}.keyblock1 diff -Nru vboot-utils-0~R88-13597.B/tests/futility/test_update.sh vboot-utils-0~R99-14469.B/tests/futility/test_update.sh --- vboot-utils-0~R88-13597.B/tests/futility/test_update.sh 2020-12-01 09:49:33.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/futility/test_update.sh 2022-02-11 14:46:17.000000000 +0000 @@ -48,6 +48,7 @@ cp -f ${PEPPY_BIOS} ${FROM_IMAGE} "${FUTILITY}" load_fmap "${FROM_IMAGE}" \ RO_VPD:"${RO_VPD_BLOB}" RW_VPD:"${RO_VPD_BLOB}" +cp -f "${FROM_IMAGE}" "${FROM_IMAGE}".unpatched patch_file() { local file="$1" @@ -347,6 +348,15 @@ --quirks min_platform_version=3 \ -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1,3 +test_update "Full update (incompatible platform)" \ + "${FROM_IMAGE}".unpatched "!platform is not compatible" \ + -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 + +test_update "Full update (--quirks no_check_platform)" \ + "${FROM_IMAGE}".unpatched "${TMP}.expected.full" \ + --quirks no_check_platform \ + -i "${TO_IMAGE}" --wp=0 --sys_props 0,0x10001,1 + # Test archive and manifest. A="${TMP}.archive" mkdir -p "${A}/bin" diff -Nru vboot-utils-0~R88-13597.B/tests/gpt_misc_tests.c vboot-utils-0~R99-14469.B/tests/gpt_misc_tests.c --- vboot-utils-0~R88-13597.B/tests/gpt_misc_tests.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/gpt_misc_tests.c 2022-02-11 14:46:17.000000000 +0000 @@ -0,0 +1,378 @@ +/* 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. + * + * Tests for vboot_kernel.c + */ + +#include "2api.h" +#include "cgptlib.h" +#include "cgptlib_internal.h" +#include "gpt.h" +#include "test_common.h" + +#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args) +#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, " calls") + +/* Assumes 512-byte disk sectors */ +#define MOCK_SECTOR_SIZE 512 +#define MOCK_SECTOR_COUNT 1024 + +/* Mock kernel partition */ +struct mock_part { + uint32_t start; + uint32_t size; +}; + +/* Mock data */ +static char call_log[4096]; +static int disk_read_to_fail; +static int disk_write_to_fail; + +static VbExDiskHandle_t handle; +static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT]; +static GptHeader *mock_gpt_primary = + (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1]; +static GptHeader *mock_gpt_secondary = + (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)]; + +/** + * Prepare a valid GPT header that will pass CheckHeader() tests + */ +static void SetupGptHeader(GptHeader *h, int is_secondary) +{ + memset(h, '\0', MOCK_SECTOR_SIZE); + + /* "EFI PART" */ + memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); + h->revision = GPT_HEADER_REVISION; + h->size = MIN_SIZE_OF_HEADER; + + /* 16KB: 128 entries of 128 bytes */ + h->size_of_entry = sizeof(GptEntry); + h->number_of_entries = MAX_NUMBER_OF_ENTRIES; + + /* Set LBA pointers for primary or secondary header */ + if (is_secondary) { + h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS; + h->entries_lba = h->my_lba - CalculateEntriesSectors(h, + MOCK_SECTOR_SIZE); + } else { + h->my_lba = GPT_PMBR_SECTORS; + h->entries_lba = h->my_lba + 1; + } + + h->first_usable_lba = 2 + CalculateEntriesSectors(h, MOCK_SECTOR_SIZE); + h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h, + MOCK_SECTOR_SIZE); + + h->header_crc32 = HeaderCrc(h); +} + +static void ResetCallLog(void) +{ + *call_log = 0; +} + +/** + * Reset mock data (for use before each test) + */ +static void ResetMocks(void) +{ + ResetCallLog(); + + memset(&mock_disk, 0, sizeof(mock_disk)); + SetupGptHeader(mock_gpt_primary, 0); + SetupGptHeader(mock_gpt_secondary, 1); + + disk_read_to_fail = -1; + disk_write_to_fail = -1; +} + +/* Mocks */ + +vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start, + uint64_t lba_count, void *buffer) +{ + LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count); + + if ((int)lba_start == disk_read_to_fail) + return VB2_ERROR_MOCK; + + memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE], + lba_count * MOCK_SECTOR_SIZE); + + return VB2_SUCCESS; +} + +vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start, + uint64_t lba_count, const void *buffer) +{ + LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count); + + if ((int)lba_start == disk_write_to_fail) + return VB2_ERROR_MOCK; + + memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer, + lba_count * MOCK_SECTOR_SIZE); + + return VB2_SUCCESS; +} + +/** + * Test reading/writing GPT + */ +static void ReadWriteGptTest(void) +{ + GptData g; + GptHeader *h; + + g.sector_bytes = MOCK_SECTOR_SIZE; + g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT; + g.valid_headers = g.valid_entries = MASK_BOTH; + + ResetMocks(); + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 2, 32)\n" + "VbExDiskRead(h, 1023, 1)\n" + "VbExDiskRead(h, 991, 32)\n"); + ResetCallLog(); + /* + * Valgrind complains about access to uninitialized memory here, so + * zero the primary header before each test. + */ + memset(g.primary_header, '\0', g.sector_bytes); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree"); + TEST_CALLS(""); + + /* + * Invalidate primary GPT header, + * check that AllocAndReadGptData still succeeds + */ + ResetMocks(); + memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary)); + TEST_EQ(AllocAndReadGptData(handle, &g), 0, + "AllocAndRead primary invalid"); + TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 1, "Primary header is invalid"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 0, "Secondary header is valid"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 1023, 1)\n" + "VbExDiskRead(h, 991, 32)\n"); + WriteAndFreeGptData(handle, &g); + + /* + * Invalidate secondary GPT header, + * check that AllocAndReadGptData still succeeds + */ + ResetMocks(); + memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary)); + TEST_EQ(AllocAndReadGptData(handle, &g), 0, + "AllocAndRead secondary invalid"); + TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 0, "Primary header is valid"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 1, "Secondary header is invalid"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 2, 32)\n" + "VbExDiskRead(h, 1023, 1)\n"); + WriteAndFreeGptData(handle, &g); + + /* + * Invalidate primary AND secondary GPT header, + * check that AllocAndReadGptData fails. + */ + ResetMocks(); + memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary)); + memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary)); + TEST_EQ(AllocAndReadGptData(handle, &g), 1, + "AllocAndRead primary and secondary invalid"); + TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 1, "Primary header is invalid"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 1, "Secondary header is invalid"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 1023, 1)\n"); + WriteAndFreeGptData(handle, &g); + + /* + * Invalidate primary GPT header and check that it is + * repaired by GptRepair(). + * + * This would normally be called by LoadKernel()->GptInit() + * but this callback is mocked in these tests. + */ + ResetMocks(); + memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary)); + TEST_EQ(AllocAndReadGptData(handle, &g), 0, + "Fix Primary GPT: AllocAndRead"); + /* Call GptRepair() with input indicating secondary GPT is valid */ + g.valid_headers = g.valid_entries = MASK_SECONDARY; + GptRepair(&g); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, + "Fix Primary GPT: WriteAndFreeGptData"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 1023, 1)\n" + "VbExDiskRead(h, 991, 32)\n" + "VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n"); + TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 0, "Fix Primary GPT: Primary header is valid"); + + /* + * Invalidate secondary GPT header and check that it can be + * repaired by GptRepair(). + * + * This would normally be called by LoadKernel()->GptInit() + * but this callback is mocked in these tests. + */ + ResetMocks(); + memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary)); + TEST_EQ(AllocAndReadGptData(handle, &g), 0, + "Fix Secondary GPT: AllocAndRead"); + /* Call GptRepair() with input indicating primary GPT is valid */ + g.valid_headers = g.valid_entries = MASK_PRIMARY; + GptRepair(&g); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, + "Fix Secondary GPT: WriteAndFreeGptData"); + TEST_CALLS("VbExDiskRead(h, 1, 1)\n" + "VbExDiskRead(h, 2, 32)\n" + "VbExDiskRead(h, 1023, 1)\n" + "VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, + g.gpt_drive_sectors, 0, g.sector_bytes), + 0, "Fix Secondary GPT: Secondary header is valid"); + + /* Data which is changed is written */ + ResetMocks(); + AllocAndReadGptData(handle, &g); + g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1; + ResetCallLog(); + memset(g.primary_header, '\0', g.sector_bytes); + h = (GptHeader*)g.primary_header; + h->entries_lba = 2; + h->number_of_entries = MAX_NUMBER_OF_ENTRIES; + h->size_of_entry = sizeof(GptEntry); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); + TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n"); + + /* Data which is changed is written */ + ResetMocks(); + AllocAndReadGptData(handle, &g); + g.modified = -1; + ResetCallLog(); + memset(g.primary_header, '\0', g.sector_bytes); + h = (GptHeader*)g.primary_header; + h->entries_lba = 2; + h->number_of_entries = MAX_NUMBER_OF_ENTRIES; + h->size_of_entry = sizeof(GptEntry); + h = (GptHeader*)g.secondary_header; + h->entries_lba = 991; + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); + TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n" + "VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + + /* If legacy signature, don't modify GPT header/entries 1 */ + ResetMocks(); + AllocAndReadGptData(handle, &g); + h = (GptHeader *)g.primary_header; + memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); + g.modified = -1; + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); + TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + + /* Error reading */ + ResetMocks(); + disk_read_to_fail = 1; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = g.valid_entries = MASK_SECONDARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); + TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" + "VbExDiskWrite(h, 2, 32)\n"); + + ResetMocks(); + disk_read_to_fail = 2; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = MASK_BOTH; + g.valid_entries = MASK_SECONDARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); + TEST_CALLS("VbExDiskWrite(h, 2, 32)\n"); + + ResetMocks(); + disk_read_to_fail = 991; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = MASK_BOTH; + g.valid_entries = MASK_PRIMARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); + TEST_CALLS("VbExDiskWrite(h, 991, 32)\n"); + + ResetMocks(); + disk_read_to_fail = 1023; + TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); + g.valid_headers = g.valid_entries = MASK_PRIMARY; + GptRepair(&g); + ResetCallLog(); + TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); + TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" + "VbExDiskWrite(h, 991, 32)\n"); + + /* Error writing */ + ResetMocks(); + disk_write_to_fail = 1; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + + ResetMocks(); + disk_write_to_fail = 2; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + h = (GptHeader*)g.primary_header; + h->entries_lba = 2; + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + + ResetMocks(); + disk_write_to_fail = 991; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + + ResetMocks(); + disk_write_to_fail = 1023; + AllocAndReadGptData(handle, &g); + g.modified = -1; + memset(g.primary_header, '\0', g.sector_bytes); + TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); + +} + +int main(void) +{ + ReadWriteGptTest(); + + return gTestSuccess ? 0 : 255; +} diff -Nru vboot-utils-0~R88-13597.B/tests/load_kernel_tests.sh vboot-utils-0~R99-14469.B/tests/load_kernel_tests.sh --- vboot-utils-0~R88-13597.B/tests/load_kernel_tests.sh 2020-12-01 09:49:33.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/load_kernel_tests.sh 2022-02-11 14:46:17.000000000 +0000 @@ -31,10 +31,10 @@ --key ${TESTKEY_DIR}/key_rsa2048.keyb --algorithm 4 # Keyblock with kernel data key is signed by kernel subkey -# Flags=5 means dev=0 rec=0 +# Flags=21 means dev=0 rec=0 minios=0 ${FUTILITY} vbutil_keyblock --pack keyblock.test \ --datapubkey datakey.test \ - --flags 5 \ + --flags 21 \ --signprivate ${SCRIPT_DIR}/devkeys/kernel_subkey.vbprivk # Kernel preamble is signed with the kernel data key Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/firmware.loem1.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/firmware.loem1.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/firmware.loem2.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/firmware.loem2.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/firmware.loem3.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/firmware.loem3.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/firmware.loem4.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/firmware.loem4.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/installer_kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/installer_kernel.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/kernel.keyblock differ Binary files /tmp/tmpq4my77qs/0HsbohJZhR/vboot-utils-0~R88-13597.B/tests/loemkeys/recovery_kernel.keyblock and /tmp/tmpq4my77qs/8n_UO9wrVN/vboot-utils-0~R99-14469.B/tests/loemkeys/recovery_kernel.keyblock differ diff -Nru vboot-utils-0~R88-13597.B/tests/test_common.c vboot-utils-0~R99-14469.B/tests/test_common.c --- vboot-utils-0~R88-13597.B/tests/test_common.c 2020-12-01 09:49:39.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/test_common.c 2022-02-11 14:46:23.000000000 +0000 @@ -147,6 +147,20 @@ return !result; } +int test_fail(int result, + const char *preamble, const char *desc, const char *comment) +{ + if (result != 0) { + print_passed(preamble, desc, comment); + } else { + print_failed(preamble, desc, comment); + fprintf(stderr, + " Didn't expect SUCCESS (0), but got it\n"); + gTestSuccess = 0; + } + return result; +} + int test_true(int result, const char *preamble, const char *desc, const char *comment) { diff -Nru vboot-utils-0~R88-13597.B/tests/test_common.h vboot-utils-0~R99-14469.B/tests/test_common.h --- vboot-utils-0~R88-13597.B/tests/test_common.h 2020-12-01 09:49:39.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/test_common.h 2022-02-11 14:46:23.000000000 +0000 @@ -120,6 +120,17 @@ #result " == 0", \ comment) +/* Return 1 if result is not 0 (VB2_SUCCESS or other), else return 1. + * Also update the global gTestSuccess flag if test fails. */ +int test_fail(int result, + const char *preamble, const char *desc, const char *comment); + +#define TEST_FAIL(result, comment) \ + test_fail(result, \ + __FILE__ ":" TOSTRING(__LINE__), \ + #result " != 0", \ + comment) + /* Return 1 if vb2ex_abort() was called, else return 0. * Also update the global gTestSuccess flag if test fails. */ int test_abort(int aborted, diff -Nru vboot-utils-0~R88-13597.B/tests/vb20_api_kernel_tests.c vboot-utils-0~R99-14469.B/tests/vb20_api_kernel_tests.c --- vboot-utils-0~R88-13597.B/tests/vb20_api_kernel_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb20_api_kernel_tests.c 2022-02-11 14:46:23.000000000 +0000 @@ -15,7 +15,6 @@ #include "2secdata.h" #include "2sysincludes.h" #include "test_common.h" -#include "vb2_common.h" #include "vboot_struct.h" /* Common context for tests */ @@ -60,6 +59,7 @@ "vb2api_init failed"); sd = vb2_get_sd(ctx); + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; vb2_nv_init(ctx); vb2api_secdata_kernel_create(ctx); diff -Nru vboot-utils-0~R88-13597.B/tests/vb20_kernel_tests.c vboot-utils-0~R99-14469.B/tests/vb20_kernel_tests.c --- vboot-utils-0~R88-13597.B/tests/vb20_kernel_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb20_kernel_tests.c 2022-02-11 14:46:23.000000000 +0000 @@ -15,7 +15,6 @@ #include "2secdata.h" #include "2sysincludes.h" #include "test_common.h" -#include "vb2_common.h" /* Common context for tests */ static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] @@ -228,7 +227,7 @@ reset_common_data(FOR_KEYBLOCK); mock_vblock.k.data_key_data[0] ^= 0xa0; TEST_EQ(vb2_verify_keyblock_hash(kb, kb->keyblock_size, &wb), - VB2_ERROR_KEYBLOCK_SIG_INVALID, + VB2_ERROR_KEYBLOCK_HASH_INVALID_IN_DEV_MODE, "Keyblock check hash invalid"); } diff -Nru vboot-utils-0~R88-13597.B/tests/vb20_misc_tests.c vboot-utils-0~R99-14469.B/tests/vb20_misc_tests.c --- vboot-utils-0~R88-13597.B/tests/vb20_misc_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb20_misc_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,450 +0,0 @@ -/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Tests for misc library - */ - -#include - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2rsa.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "test_common.h" -#include "vb2_common.h" - -/* Common context for tests */ -static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static struct vb2_gbb_header gbb; - -/* Mocked function data */ - -static struct { - struct vb2_gbb_header h; - struct vb2_packed_key rootkey; - char rootkey_data[32]; -} mock_gbb; - -static struct { - /* Keyblock */ - struct { - struct vb2_keyblock kb; - char data_key_data[16]; - uint8_t kbdata[128]; - } k; - /* Preamble follows keyblock */ - struct { - struct vb2_fw_preamble pre; - uint8_t predata[128]; - } p; - -} mock_vblock; - -static int mock_read_res_fail_on_call; -static int mock_unpack_key_retval; -static int mock_verify_keyblock_retval; -static int mock_verify_preamble_retval; - -/* Type of test to reset for */ -enum reset_type { - FOR_KEYBLOCK, - FOR_PREAMBLE -}; - -static void reset_common_data(enum reset_type t) -{ - struct vb2_keyblock *kb = &mock_vblock.k.kb; - struct vb2_fw_preamble *pre = &mock_vblock.p.pre; - - memset(workbuf, 0xaa, sizeof(workbuf)); - - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - - memset(&gbb, 0, sizeof(gbb)); - sd = vb2_get_sd(ctx); - - vb2_nv_init(ctx); - - vb2api_secdata_firmware_create(ctx); - vb2_secdata_firmware_init(ctx); - - vb2api_secdata_kernel_create(ctx); - vb2_secdata_kernel_init(ctx); - - mock_read_res_fail_on_call = 0; - mock_unpack_key_retval = VB2_SUCCESS; - mock_verify_keyblock_retval = VB2_SUCCESS; - mock_verify_preamble_retval = VB2_SUCCESS; - - /* Set up mock data for verifying keyblock */ - sd->fw_version_secdata = 0x20002; - vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, - sd->fw_version_secdata); - - gbb.rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey); - gbb.rootkey_size = sizeof(mock_gbb.rootkey_data); - sd->last_fw_result = VB2_FW_RESULT_SUCCESS; - - mock_gbb.rootkey.algorithm = 11; - mock_gbb.rootkey.key_offset = - vb2_offset_of(&mock_gbb.rootkey, - &mock_gbb.rootkey_data); - mock_gbb.rootkey.key_size = sizeof(mock_gbb.rootkey_data); - - kb->keyblock_size = sizeof(mock_vblock.k); - kb->data_key.algorithm = 7; - kb->data_key.key_version = 2; - kb->data_key.key_offset = - vb2_offset_of(&mock_vblock.k, &mock_vblock.k.data_key_data) - - vb2_offset_of(&mock_vblock.k, &kb->data_key); - kb->data_key.key_size = sizeof(mock_vblock.k.data_key_data); - strcpy(mock_vblock.k.data_key_data, "data key data!!"); - - pre->preamble_size = sizeof(mock_vblock.p); - pre->firmware_version = 2; - - /* If verifying preamble, verify keyblock first to set up data key */ - if (t == FOR_PREAMBLE) - vb2_load_fw_keyblock(ctx); -}; - -/* Mocked functions */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -vb2_error_t vb2ex_read_resource(struct vb2_context *c, - enum vb2_resource_index index, uint32_t offset, - void *buf, uint32_t size) -{ - uint8_t *rptr; - uint32_t rsize; - - if (--mock_read_res_fail_on_call == 0) - return VB2_ERROR_EX_READ_RESOURCE_INDEX; - - switch(index) { - case VB2_RES_GBB: - rptr = (uint8_t *)&mock_gbb; - rsize = sizeof(mock_gbb); - break; - case VB2_RES_FW_VBLOCK: - rptr = (uint8_t *)&mock_vblock; - rsize = sizeof(mock_vblock); - break; - default: - return VB2_ERROR_EX_READ_RESOURCE_INDEX; - } - - if (offset > rsize || offset + size > rsize) - return VB2_ERROR_EX_READ_RESOURCE_SIZE; - - memcpy(buf, rptr + offset, size); - return VB2_SUCCESS; -} - -vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, - const uint8_t *buf, uint32_t size) -{ - key->arrsize = 0; - return mock_unpack_key_retval; -} - -static struct vb2_public_key last_used_key; - -vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - memcpy(&last_used_key, key, sizeof(struct vb2_public_key)); - return mock_verify_keyblock_retval; -} - -vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble, - uint32_t size, - const struct vb2_public_key *key, - const struct vb2_workbuf *wb) -{ - memcpy(&last_used_key, key, sizeof(struct vb2_public_key)); - return mock_verify_preamble_retval; -} - -/* Tests */ - -static void verify_keyblock_tests(void) -{ - struct vb2_keyblock *kb = &mock_vblock.k.kb; - struct vb2_packed_key *k; - int expected_offset; - - /* Test successful call */ - reset_common_data(FOR_KEYBLOCK); - expected_offset = sd->workbuf_used; - TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); - TEST_EQ(sd->fw_version, 0x20000, "keyblock version"); - TEST_EQ(sd->vblock_preamble_offset, sizeof(mock_vblock.k), - "preamble offset"); - TEST_EQ(sd->data_key_offset, expected_offset, - "keyblock data key offset"); - TEST_EQ(sd->workbuf_used, - vb2_wb_round_up(sd->data_key_offset + - sd->data_key_size), - "workbuf used"); - - /* Make sure data key was properly saved */ - k = vb2_member_of(sd, sd->data_key_offset); - TEST_EQ(k->algorithm, 7, "data key algorithm"); - TEST_EQ(k->key_version, 2, "data key version"); - TEST_EQ(k->key_size, sizeof(mock_vblock.k.data_key_data), - "data key size"); - TEST_EQ(memcmp(vb2_member_of(k, k->key_offset), - mock_vblock.k.data_key_data, - sizeof(mock_vblock.k.data_key_data)), - 0, "data key data"); - TEST_EQ(sd->workbuf_used, - vb2_wb_round_up(sd->data_key_offset + - sd->data_key_size), - "workbuf used after"); - - /* Test hwcrypto conditions */ - reset_common_data(FOR_KEYBLOCK); - - TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden by TPM flag"); - - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden by TPM flag on recovery mode"); - - vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, - VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); - - TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden on recovery mode"); - - ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); - TEST_EQ(last_used_key.allow_hwcrypto, 1, "hwcrypto is allowed"); - - /* Test failures */ - reset_common_data(FOR_KEYBLOCK); - sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN - - vb2_wb_round_up(gbb.rootkey_size); - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY, - "keyblock not enough workbuf for root key"); - - reset_common_data(FOR_KEYBLOCK); - gbb.rootkey_size = sizeof(mock_gbb); - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_EX_READ_RESOURCE_SIZE, - "keyblock read root key"); - - reset_common_data(FOR_KEYBLOCK); - mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM, - "keyblock unpack root key"); - - reset_common_data(FOR_KEYBLOCK); - sd->workbuf_used = sd->workbuf_size - - vb2_wb_round_up(gbb.rootkey_size); - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER, - "keyblock not enough workbuf for header"); - - reset_common_data(FOR_KEYBLOCK); - mock_read_res_fail_on_call = 2; - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_EX_READ_RESOURCE_INDEX, - "keyblock read keyblock header"); - - reset_common_data(FOR_KEYBLOCK); - sd->workbuf_used = sd->workbuf_size - - vb2_wb_round_up(gbb.rootkey_size) - - vb2_wb_round_up(sizeof(struct vb2_keyblock)); - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_FW_KEYBLOCK_WORKBUF, - "keyblock not enough workbuf for entire keyblock"); - - reset_common_data(FOR_KEYBLOCK); - kb->keyblock_size = sizeof(mock_vblock) + 1; - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_EX_READ_RESOURCE_SIZE, - "keyblock read keyblock"); - - reset_common_data(FOR_KEYBLOCK); - mock_verify_keyblock_retval = VB2_ERROR_KEYBLOCK_MAGIC; - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_KEYBLOCK_MAGIC, - "keyblock verify keyblock"); - - reset_common_data(FOR_KEYBLOCK); - kb->data_key.key_version = 0x10000; - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE, - "keyblock version range"); - - reset_common_data(FOR_KEYBLOCK); - kb->data_key.key_version = 1; - TEST_EQ(vb2_load_fw_keyblock(ctx), - VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK, - "keyblock rollback"); - - reset_common_data(FOR_KEYBLOCK); - kb->data_key.key_version = 1; - gbb.flags |= VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK; - TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock rollback with GBB flag"); -} - -static void verify_preamble_tests(void) -{ - struct vb2_fw_preamble *pre = &mock_vblock.p.pre; - int expected_offset; - uint32_t v; - - /* Test successful call */ - reset_common_data(FOR_PREAMBLE); - expected_offset = sd->workbuf_used; - TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); - TEST_EQ(sd->fw_version, 0x20002, "combined version"); - TEST_EQ(sd->preamble_offset, expected_offset, - "preamble offset"); - TEST_EQ(sd->preamble_size, pre->preamble_size, "preamble size"); - TEST_EQ(sd->workbuf_used, - vb2_wb_round_up(sd->preamble_offset + - sd->preamble_size), - "workbuf used"); - - /* Test hwcrypto conditions */ - reset_common_data(FOR_PREAMBLE); - - TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden by TPM flag"); - - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden by TPM flag on recovery mode"); - - vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, - VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); - - TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden on recovery mode"); - - ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); - TEST_EQ(last_used_key.allow_hwcrypto, 1, - "hwcrypto is allowed"); - - - /* Expected failures */ - reset_common_data(FOR_PREAMBLE); - sd->data_key_size = 0; - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_FW_PREAMBLE2_DATA_KEY, - "preamble no data key"); - - reset_common_data(FOR_PREAMBLE); - mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM; - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM, - "preamble unpack data key"); - - reset_common_data(FOR_PREAMBLE); - sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN - - vb2_wb_round_up(sizeof(struct vb2_fw_preamble)); - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER, - "preamble not enough workbuf for header"); - - reset_common_data(FOR_PREAMBLE); - sd->vblock_preamble_offset = sizeof(mock_vblock); - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_EX_READ_RESOURCE_SIZE, - "preamble read header"); - - reset_common_data(FOR_PREAMBLE); - sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN - - vb2_wb_round_up(sizeof(mock_vblock.p)); - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_FW_PREAMBLE2_WORKBUF, - "preamble not enough workbuf"); - - reset_common_data(FOR_PREAMBLE); - pre->preamble_size = sizeof(mock_vblock); - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_EX_READ_RESOURCE_SIZE, - "preamble read full"); - - reset_common_data(FOR_PREAMBLE); - mock_verify_preamble_retval = VB2_ERROR_PREAMBLE_SIG_INVALID; - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_PREAMBLE_SIG_INVALID, - "preamble verify"); - - reset_common_data(FOR_PREAMBLE); - pre->firmware_version = 0x10000; - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_FW_PREAMBLE_VERSION_RANGE, - "preamble version range"); - - reset_common_data(FOR_PREAMBLE); - pre->firmware_version = 1; - TEST_EQ(vb2_load_fw_preamble(ctx), - VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK, - "preamble version rollback"); - - reset_common_data(FOR_PREAMBLE); - pre->firmware_version = 1; - gbb.flags |= VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK; - TEST_SUCC(vb2_load_fw_preamble(ctx), "version rollback with GBB flag"); - - reset_common_data(FOR_PREAMBLE); - pre->firmware_version = 3; - TEST_SUCC(vb2_load_fw_preamble(ctx), - "preamble version roll forward"); - v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS); - TEST_EQ(v, 0x20003, "roll forward"); - - /* Newer version without result success doesn't roll forward */ - reset_common_data(FOR_PREAMBLE); - pre->firmware_version = 3; - sd->last_fw_result = VB2_FW_RESULT_UNKNOWN; - TEST_SUCC(vb2_load_fw_preamble(ctx), - "preamble version no roll forward 1"); - v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS); - TEST_EQ(v, 0x20002, "no roll forward"); - - /* Newer version with success but for other slot doesn't roll forward */ - reset_common_data(FOR_PREAMBLE); - pre->firmware_version = 3; - sd->last_fw_slot = 1; - TEST_SUCC(vb2_load_fw_preamble(ctx), - "preamble version no roll forward 2"); - v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS); - TEST_EQ(v, 0x20002, "no roll forward"); -} - -int main(int argc, char* argv[]) -{ - verify_keyblock_tests(); - verify_preamble_tests(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vb20_rsa_padding_tests.c vboot-utils-0~R99-14469.B/tests/vb20_rsa_padding_tests.c --- vboot-utils-0~R88-13597.B/tests/vb20_rsa_padding_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb20_rsa_padding_tests.c 2022-02-11 14:46:23.000000000 +0000 @@ -6,13 +6,13 @@ #include #include +#include "2common.h" #include "2rsa.h" #include "2sysincludes.h" #include "file_keys.h" #include "host_key.h" #include "rsa_padding_test.h" #include "test_common.h" -#include "vb2_common.h" vb2_error_t hwcrypto_modexp_return_value = VB2_SUCCESS; vb2_error_t vb2ex_hwcrypto_modexp(const struct vb2_public_key *key, diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_api_tests.c vboot-utils-0~R99-14469.B/tests/vb2_api_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_api_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_api_tests.c 2022-02-11 14:46:23.000000000 +0000 @@ -15,7 +15,6 @@ #include "2secdata.h" #include "2sysincludes.h" #include "test_common.h" -#include "vb2_common.h" /* Common context for tests */ @@ -82,6 +81,9 @@ vb2api_secdata_kernel_create(ctx); vb2_secdata_kernel_init(ctx); + if (hwcrypto_state != HWCRYPTO_FORBIDDEN) + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, + VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); force_dev_mode = 0; retval_vb2_fw_init_gbb = VB2_SUCCESS; @@ -102,10 +104,7 @@ pre = vb2_member_of(sd, sd->preamble_offset); pre->body_signature.data_size = mock_body_size; pre->body_signature.sig_size = mock_sig_size; - if (hwcrypto_state == HWCRYPTO_FORBIDDEN) - pre->flags = VB2_FIRMWARE_PREAMBLE_DISALLOW_HWCRYPTO; - else - pre->flags = 0; + pre->flags = 0; sd->data_key_offset = sd->workbuf_used; sd->data_key_size = sizeof(*k) + 8; @@ -375,6 +374,8 @@ 0, " secdata firmware initialized"); TEST_NEQ(sd->status & VB2_SD_STATUS_SECDATA_KERNEL_INIT, 0, " secdata kernel initialized"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); retval_vb2_fw_init_gbb = VB2_ERROR_GBB_MAGIC; @@ -384,27 +385,25 @@ " recovery reason"); TEST_NEQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE, 0, " recovery flag"); TEST_NEQ(ctx->flags & VB2_CONTEXT_CLEAR_RAM, 0, " clear ram flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); - /* Dev switch error in normal mode reboots to recovery */ + /* Dev switch error proceeds to a recovery boot */ reset_common_data(FOR_MISC); retval_vb2_check_dev_switch = VB2_ERROR_MOCK; - TEST_EQ(vb2api_fw_phase1(ctx), VB2_ERROR_MOCK, "phase1 dev switch"); + TEST_EQ(vb2api_fw_phase1(ctx), VB2_ERROR_API_PHASE1_RECOVERY, + "phase1 dev switch error proceeds to recovery"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_DEV_SWITCH, " recovery request"); - - /* Dev switch error already in recovery mode just proceeds */ - reset_common_data(FOR_MISC); - vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_RO_UNSPECIFIED); - retval_vb2_check_dev_switch = VB2_ERROR_MOCK; - TEST_EQ(vb2api_fw_phase1(ctx), VB2_ERROR_API_PHASE1_RECOVERY, - "phase1 dev switch error in recovery"); - TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_UNSPECIFIED, + TEST_EQ(sd->recovery_reason, VB2_RECOVERY_DEV_SWITCH, " recovery reason"); /* Check that DISPLAY_AVAILABLE gets set on recovery mode. */ TEST_NEQ(ctx->flags & VB2_CONTEXT_DISPLAY_INIT, 0, " display init context flag"); TEST_NEQ(sd->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE, 0, " display available SD flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); ctx->secdata_firmware[0] ^= 0x42; @@ -414,6 +413,8 @@ " recovery reason"); TEST_NEQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE, 0, " recovery flag"); TEST_NEQ(ctx->flags & VB2_CONTEXT_CLEAR_RAM, 0, " clear ram flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); /* Bad secdata_kernel causes recovery mode */ reset_common_data(FOR_MISC); @@ -424,6 +425,8 @@ " recovery reason"); TEST_NEQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE, 0, " recovery flag"); TEST_NEQ(ctx->flags & VB2_CONTEXT_CLEAR_RAM, 0, " clear ram flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); /* Test secdata_firmware-requested reboot */ reset_common_data(FOR_MISC); @@ -435,6 +438,8 @@ 1, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " recovery request"); + TEST_EQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 1); @@ -445,6 +450,8 @@ 0, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " recovery request"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT; @@ -457,6 +464,8 @@ 1, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " recovery request"); + TEST_EQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT; @@ -469,6 +478,8 @@ 1, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_RO_TPM_REBOOT, " recovery request"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT; @@ -481,6 +492,8 @@ 1, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_RO_UNSPECIFIED, " recovery request"); + TEST_EQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); vb2_nv_set(ctx, VB2_NV_TPM_REQUESTED_REBOOT, 1); @@ -493,6 +506,8 @@ 0, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_RO_UNSPECIFIED, " recovery request"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); ctx->flags |= VB2_CONTEXT_SECDATA_WANTS_REBOOT; @@ -506,6 +521,8 @@ 1, " tpm reboot request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), VB2_RECOVERY_RO_UNSPECIFIED, " recovery request"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); /* Cases for checking DISPLAY_INIT and DISPLAY_AVAILABLE. */ reset_common_data(FOR_MISC); @@ -515,6 +532,8 @@ 0, " display init context flag"); TEST_NEQ(sd->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE, 0, " display available SD flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1); @@ -523,6 +542,8 @@ 0, " display init context flag"); TEST_NEQ(sd->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE, 0, " display available SD flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); reset_common_data(FOR_MISC); force_dev_mode = 1; @@ -531,6 +552,8 @@ 0, " display init context flag"); TEST_NEQ(sd->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE, 0, " display available SD flag"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, " recovery decided"); } static void phase2_tests(void) @@ -741,26 +764,28 @@ "check digest value"); /* Test hwcrypto conditions */ - reset_common_data(FOR_CHECK_HASH); - TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden by TPM flag"); - - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden by TPM flag on recovery mode"); - - vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, - VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); - - TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); - TEST_EQ(last_used_key.allow_hwcrypto, 0, - "hwcrypto is forbidden on recovery mode"); - - ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; - TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); - TEST_EQ(last_used_key.allow_hwcrypto, 1, "hwcrypto is allowed"); + if (hwcrypto_state == HWCRYPTO_FORBIDDEN) { + reset_common_data(FOR_CHECK_HASH); + TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden by TPM flag"); + + reset_common_data(FOR_CHECK_HASH); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden by TPM flag on recovery mode"); + } else { + reset_common_data(FOR_CHECK_HASH); + TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); + TEST_EQ(last_used_key.allow_hwcrypto, 1, "hwcrypto is allowed"); + + reset_common_data(FOR_CHECK_HASH); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2api_check_hash(ctx), "check hash good"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden on recovery mode"); + } reset_common_data(FOR_CHECK_HASH); TEST_EQ(vb2api_check_hash_get_digest(ctx, digest_result, diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_auxfw_sync_tests.c vboot-utils-0~R99-14469.B/tests/vb2_auxfw_sync_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_auxfw_sync_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_auxfw_sync_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -16,10 +16,7 @@ #include "host_common.h" #include "load_kernel_fw.h" #include "test_common.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" #include "vboot_struct.h" -#include "vboot_ui_legacy.h" /* Mock data */ static struct vb2_context *ctx; @@ -68,14 +65,15 @@ { *severity = auxfw_mock_severity; auxfw_update_severity = auxfw_mock_severity; - if (*severity == VB2_AUXFW_SLOW_UPDATE) - if (!auxfw_mock_display_available) - return VB2_REQUEST_REBOOT; return VB2_SUCCESS; } vb2_error_t vb2ex_auxfw_update(void) { + if (auxfw_update_severity == VB2_AUXFW_SLOW_UPDATE) + if (!auxfw_mock_display_available) + return VB2_REQUEST_REBOOT; + if (auxfw_update_severity != VB2_AUXFW_NO_DEVICE && auxfw_update_severity != VB2_AUXFW_NO_UPDATE) auxfw_update_req = 1; diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_common2_tests.c vboot-utils-0~R99-14469.B/tests/vb2_common2_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_common2_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_common2_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -9,34 +9,62 @@ #include #include +#include "2common.h" #include "2rsa.h" #include "2sysincludes.h" #include "file_keys.h" #include "host_common.h" #include "host_key21.h" #include "test_common.h" -#include "vb2_common.h" static const uint8_t test_data[] = "This is some test data to sign."; static const uint32_t test_size = sizeof(test_data); -static enum { +static enum hwcrypto_state { HWCRYPTO_OK, HWCRYPTO_NOTSUPPORTED, HWCRYPTO_ERROR, -} hwcrypto_state; + HWCRYPTO_ABORT, +} hwcrypto_state_rsa, hwcrypto_state_digest; -vb2_error_t vb2ex_hwcrypto_rsa_verify_digest(const struct vb2_public_key *key, - const uint8_t *sig, const uint8_t *digest) +static vb2_error_t hwcrypto_mock(enum hwcrypto_state *state) { - switch (hwcrypto_state) { + switch (*state) { case HWCRYPTO_OK: return VB2_SUCCESS; case HWCRYPTO_NOTSUPPORTED: return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; case HWCRYPTO_ERROR: - return VB2_ERROR_RSA_VERIFY_DIGEST; + return VB2_ERROR_MOCK; + case HWCRYPTO_ABORT: + vb2ex_abort(); + /* shouldn't reach here but added for compiler */ + return VB2_ERROR_MOCK; } + return VB2_ERROR_MOCK; +} + +vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, + uint32_t data_size) +{ + return hwcrypto_mock(&hwcrypto_state_digest); +} + +vb2_error_t vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size) +{ + return hwcrypto_mock(&hwcrypto_state_digest); +} + +vb2_error_t vb2ex_hwcrypto_digest_finalize(uint8_t *digest, + uint32_t digest_size) +{ + return hwcrypto_mock(&hwcrypto_state_digest); +} + +vb2_error_t vb2ex_hwcrypto_rsa_verify_digest(const struct vb2_public_key *key, + const uint8_t *sig, const uint8_t *digest) +{ + return hwcrypto_mock(&hwcrypto_state_rsa); } @@ -109,6 +137,9 @@ uint32_t sig_total_size = sig->sig_offset + sig->sig_size; struct vb2_signature *sig2; + hwcrypto_state_rsa = HWCRYPTO_ABORT; + hwcrypto_state_digest = HWCRYPTO_ABORT; + vb2_workbuf_init(&wb, workbuf, sizeof(workbuf)); /* Allocate signature copy for tests */ @@ -155,18 +186,57 @@ pubk.allow_hwcrypto = 1; - hwcrypto_state = HWCRYPTO_OK; + hwcrypto_state_digest = HWCRYPTO_OK; + hwcrypto_state_rsa = HWCRYPTO_OK; + memcpy(sig2, sig, sig_total_size); + vb2_signature_data_mutable(sig2)[0] ^= 0x5A; + TEST_EQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto ok"); + + hwcrypto_state_rsa = HWCRYPTO_ERROR; + memcpy(sig2, sig, sig_total_size); + TEST_NEQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto error"); + + hwcrypto_state_rsa = HWCRYPTO_NOTSUPPORTED; + memcpy(sig2, sig, sig_total_size); + TEST_EQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto fallback ok"); + + memcpy(sig2, sig, sig_total_size); + sig2->sig_size -= 16; + TEST_NEQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto fallback error"); + + hwcrypto_state_digest = HWCRYPTO_ERROR; + hwcrypto_state_rsa = HWCRYPTO_OK; + memcpy(sig2, sig, sig_total_size); + TEST_NEQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto error"); + + hwcrypto_state_rsa = HWCRYPTO_ERROR; + memcpy(sig2, sig, sig_total_size); + TEST_NEQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto error"); + + hwcrypto_state_rsa = HWCRYPTO_NOTSUPPORTED; + memcpy(sig2, sig, sig_total_size); + TEST_NEQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), + 0, "vb2_verify_data() hwcrypto fallback error"); + + hwcrypto_state_digest = HWCRYPTO_NOTSUPPORTED; + hwcrypto_state_rsa = HWCRYPTO_OK; memcpy(sig2, sig, sig_total_size); vb2_signature_data_mutable(sig2)[0] ^= 0x5A; TEST_EQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), 0, "vb2_verify_data() hwcrypto ok"); - hwcrypto_state = HWCRYPTO_ERROR; + hwcrypto_state_rsa = HWCRYPTO_ERROR; memcpy(sig2, sig, sig_total_size); TEST_NEQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), 0, "vb2_verify_data() hwcrypto error"); - hwcrypto_state = HWCRYPTO_NOTSUPPORTED; + hwcrypto_state_rsa = HWCRYPTO_NOTSUPPORTED; memcpy(sig2, sig, sig_total_size); TEST_EQ(vb2_verify_data(test_data, test_size, sig2, &pubk, &wb), 0, "vb2_verify_data() hwcrypto fallback ok"); diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_common3_tests.c vboot-utils-0~R99-14469.B/tests/vb2_common3_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_common3_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_common3_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -7,6 +7,7 @@ #include +#include "2common.h" #include "2rsa.h" #include "2sysincludes.h" #include "file_keys.h" @@ -15,7 +16,6 @@ #include "host_key.h" #include "host_signature.h" #include "test_common.h" -#include "vb2_common.h" static void resign_keyblock(struct vb2_keyblock *h, const struct vb2_private_key *key) diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_common_tests.c vboot-utils-0~R99-14469.B/tests/vb2_common_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_common_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_common_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -276,9 +276,11 @@ { struct vb2_packed_key k = {.key_offset = sizeof(k), .key_size = 128}; + const void *lower_base; TEST_SUCC(vb2_verify_packed_key_inside(&k, sizeof(k)+128, &k), "vb2_packed_key_inside() ok 1"); - TEST_SUCC(vb2_verify_packed_key_inside(&k - 1, + lower_base = (const void *)((uintptr_t)&k - sizeof(k)); + TEST_SUCC(vb2_verify_packed_key_inside(lower_base, 2*sizeof(k)+128, &k), "vb2_packed_key_inside() ok 2"); TEST_EQ(vb2_verify_packed_key_inside(&k, 128, &k), @@ -297,9 +299,11 @@ { struct vb2_signature s = {.sig_offset = sizeof(s), .sig_size = 128}; + const void *lower_base; TEST_SUCC(vb2_verify_signature_inside(&s, sizeof(s)+128, &s), "vb2_verify_signature_inside() ok 1"); - TEST_SUCC(vb2_verify_signature_inside(&s - 1, + lower_base = (const void *)((uintptr_t)&s - sizeof(s)); + TEST_SUCC(vb2_verify_signature_inside(lower_base, 2*sizeof(s)+128, &s), "vb2_verify_signature_inside() ok 2"); TEST_EQ(vb2_verify_signature_inside(&s, 128, &s), diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_ec_sync_tests.c vboot-utils-0~R99-14469.B/tests/vb2_ec_sync_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_ec_sync_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_ec_sync_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -13,10 +13,7 @@ #include "host_common.h" #include "load_kernel_fw.h" #include "test_common.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" #include "vboot_struct.h" -#include "vboot_ui_legacy.h" /* Mock data */ static int ec_ro_updated; @@ -99,6 +96,13 @@ memset(hmir, 0, sizeof(hmir)); hmir[0] = 42; vb2_secdata_kernel_set_ec_hash(ctx, hmir); + + /* + * This flag should not involve in the steps deciding whether EC is + * running RW. The only concern here is we need to clear this flag after + * attempting a jump to RW. + */ + ctx->flags |= VB2_CONTEXT_EC_TRUSTED; } /* Mock functions */ @@ -107,21 +111,6 @@ return &gbb; } -uint32_t VbExIsShutdownRequested(void) -{ - if (shutdown_request_calls_left == 0) - return 1; - else if (shutdown_request_calls_left > 0) - shutdown_request_calls_left--; - - return 0; -} - -int vb2ex_ec_trusted(void) -{ - return !ec_run_image; -} - vb2_error_t vb2ex_ec_running_rw(int *in_rw) { *in_rw = ec_run_image; @@ -518,6 +507,8 @@ TEST_EQ(ec_ro_protected, 1, "ec ro protected"); TEST_EQ(ec_rw_protected, 1, "ec rw protected"); TEST_EQ(ec_run_image, 1, "ec run image"); + TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED, + " VB2_CONTEXT_EC_TRUSTED is cleared"); ResetMocks(); test_ssync(0, 0, "AP-RW, EC-RO -> EC-RW"); @@ -526,6 +517,8 @@ TEST_EQ(ec_ro_protected, 1, " ec ro protected"); TEST_EQ(ec_rw_protected, 1, " ec rw protected"); TEST_EQ(ec_run_image, 1, " ec run image"); + TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED, + " VB2_CONTEXT_EC_TRUSTED is cleared"); ResetMocks(); jump_retval = VB2_ERROR_MOCK; @@ -536,6 +529,8 @@ TEST_EQ(ec_ro_protected, 0, " ec ro protected"); TEST_EQ(ec_rw_protected, 0, " ec rw protected"); TEST_EQ(ec_run_image, 0, " ec run image"); + TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED, + " VB2_CONTEXT_EC_TRUSTED is cleared"); ResetMocks(); jump_retval = VB2_REQUEST_REBOOT_EC_TO_RO; @@ -546,6 +541,8 @@ TEST_EQ(ec_ro_protected, 0, " ec ro protected"); TEST_EQ(ec_rw_protected, 0, " ec rw protected"); TEST_EQ(ec_run_image, 0, " ec run image"); + TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED, + " VB2_CONTEXT_EC_TRUSTED is cleared"); ResetMocks(); protect_retval = VB2_ERROR_MOCK; @@ -555,6 +552,8 @@ TEST_EQ(ec_ro_protected, 0, "ec ro protected"); TEST_EQ(ec_rw_protected, 0, "ec rw protected"); TEST_EQ(ec_run_image, 1, "ec run image"); + TEST_FALSE(ctx->flags & VB2_CONTEXT_EC_TRUSTED, + " VB2_CONTEXT_EC_TRUSTED is cleared"); /* No longer check for shutdown requested */ ResetMocks(); diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_firmware_tests.c vboot-utils-0~R99-14469.B/tests/vb2_firmware_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_firmware_tests.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_firmware_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -0,0 +1,449 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Tests for firmware verification library + */ + +#include + +#include "2api.h" +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2rsa.h" +#include "2secdata.h" +#include "2sysincludes.h" +#include "test_common.h" + +/* Common context for tests */ +static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE] + __attribute__((aligned(VB2_WORKBUF_ALIGN))); +static struct vb2_context *ctx; +static struct vb2_shared_data *sd; +static struct vb2_gbb_header gbb; + +/* Mocked function data */ + +static struct { + struct vb2_gbb_header h; + struct vb2_packed_key rootkey; + char rootkey_data[32]; +} mock_gbb; + +static struct { + /* Keyblock */ + struct { + struct vb2_keyblock kb; + char data_key_data[16]; + uint8_t kbdata[128]; + } k; + /* Preamble follows keyblock */ + struct { + struct vb2_fw_preamble pre; + uint8_t predata[128]; + } p; + +} mock_vblock; + +static int mock_read_res_fail_on_call; +static int mock_unpack_key_retval; +static int mock_verify_keyblock_retval; +static int mock_verify_preamble_retval; + +/* Type of test to reset for */ +enum reset_type { + FOR_KEYBLOCK, + FOR_PREAMBLE +}; + +static void reset_common_data(enum reset_type t) +{ + struct vb2_keyblock *kb = &mock_vblock.k.kb; + struct vb2_fw_preamble *pre = &mock_vblock.p.pre; + + memset(workbuf, 0xaa, sizeof(workbuf)); + + TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), + "vb2api_init failed"); + + memset(&gbb, 0, sizeof(gbb)); + sd = vb2_get_sd(ctx); + + vb2_nv_init(ctx); + + vb2api_secdata_firmware_create(ctx); + vb2_secdata_firmware_init(ctx); + + vb2api_secdata_kernel_create(ctx); + vb2_secdata_kernel_init(ctx); + + mock_read_res_fail_on_call = 0; + mock_unpack_key_retval = VB2_SUCCESS; + mock_verify_keyblock_retval = VB2_SUCCESS; + mock_verify_preamble_retval = VB2_SUCCESS; + + /* Set up mock data for verifying keyblock */ + sd->fw_version_secdata = 0x20002; + vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, + sd->fw_version_secdata); + + gbb.rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey); + gbb.rootkey_size = sizeof(mock_gbb.rootkey_data); + sd->last_fw_result = VB2_FW_RESULT_SUCCESS; + + mock_gbb.rootkey.algorithm = 11; + mock_gbb.rootkey.key_offset = + vb2_offset_of(&mock_gbb.rootkey, + &mock_gbb.rootkey_data); + mock_gbb.rootkey.key_size = sizeof(mock_gbb.rootkey_data); + + kb->keyblock_size = sizeof(mock_vblock.k); + kb->data_key.algorithm = 7; + kb->data_key.key_version = 2; + kb->data_key.key_offset = + vb2_offset_of(&mock_vblock.k, &mock_vblock.k.data_key_data) - + vb2_offset_of(&mock_vblock.k, &kb->data_key); + kb->data_key.key_size = sizeof(mock_vblock.k.data_key_data); + strcpy(mock_vblock.k.data_key_data, "data key data!!"); + + pre->preamble_size = sizeof(mock_vblock.p); + pre->firmware_version = 2; + + /* If verifying preamble, verify keyblock first to set up data key */ + if (t == FOR_PREAMBLE) + vb2_load_fw_keyblock(ctx); +}; + +/* Mocked functions */ +struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) +{ + return &gbb; +} + +vb2_error_t vb2ex_read_resource(struct vb2_context *c, + enum vb2_resource_index index, uint32_t offset, + void *buf, uint32_t size) +{ + uint8_t *rptr; + uint32_t rsize; + + if (--mock_read_res_fail_on_call == 0) + return VB2_ERROR_EX_READ_RESOURCE_INDEX; + + switch(index) { + case VB2_RES_GBB: + rptr = (uint8_t *)&mock_gbb; + rsize = sizeof(mock_gbb); + break; + case VB2_RES_FW_VBLOCK: + rptr = (uint8_t *)&mock_vblock; + rsize = sizeof(mock_vblock); + break; + default: + return VB2_ERROR_EX_READ_RESOURCE_INDEX; + } + + if (offset > rsize || offset + size > rsize) + return VB2_ERROR_EX_READ_RESOURCE_SIZE; + + memcpy(buf, rptr + offset, size); + return VB2_SUCCESS; +} + +vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, + const uint8_t *buf, uint32_t size) +{ + key->arrsize = 0; + return mock_unpack_key_retval; +} + +static struct vb2_public_key last_used_key; + +vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) +{ + memcpy(&last_used_key, key, sizeof(struct vb2_public_key)); + return mock_verify_keyblock_retval; +} + +vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble, + uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *wb) +{ + memcpy(&last_used_key, key, sizeof(struct vb2_public_key)); + return mock_verify_preamble_retval; +} + +/* Tests */ + +static void verify_keyblock_tests(void) +{ + struct vb2_keyblock *kb = &mock_vblock.k.kb; + struct vb2_packed_key *k; + int expected_offset; + + /* Test successful call */ + reset_common_data(FOR_KEYBLOCK); + expected_offset = sd->workbuf_used; + TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); + TEST_EQ(sd->fw_version, 0x20000, "keyblock version"); + TEST_EQ(sd->vblock_preamble_offset, sizeof(mock_vblock.k), + "preamble offset"); + TEST_EQ(sd->data_key_offset, expected_offset, + "keyblock data key offset"); + TEST_EQ(sd->workbuf_used, + vb2_wb_round_up(sd->data_key_offset + + sd->data_key_size), + "workbuf used"); + + /* Make sure data key was properly saved */ + k = vb2_member_of(sd, sd->data_key_offset); + TEST_EQ(k->algorithm, 7, "data key algorithm"); + TEST_EQ(k->key_version, 2, "data key version"); + TEST_EQ(k->key_size, sizeof(mock_vblock.k.data_key_data), + "data key size"); + TEST_EQ(memcmp(vb2_member_of(k, k->key_offset), + mock_vblock.k.data_key_data, + sizeof(mock_vblock.k.data_key_data)), + 0, "data key data"); + TEST_EQ(sd->workbuf_used, + vb2_wb_round_up(sd->data_key_offset + + sd->data_key_size), + "workbuf used after"); + + /* Test hwcrypto conditions */ + reset_common_data(FOR_KEYBLOCK); + + TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden by TPM flag"); + + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden by TPM flag on recovery mode"); + + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, + VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); + + TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden on recovery mode"); + + ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify"); + TEST_EQ(last_used_key.allow_hwcrypto, 1, "hwcrypto is allowed"); + + /* Test failures */ + reset_common_data(FOR_KEYBLOCK); + sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN - + vb2_wb_round_up(gbb.rootkey_size); + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY, + "keyblock not enough workbuf for root key"); + + reset_common_data(FOR_KEYBLOCK); + gbb.rootkey_size = sizeof(mock_gbb); + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "keyblock read root key"); + + reset_common_data(FOR_KEYBLOCK); + mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM; + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM, + "keyblock unpack root key"); + + reset_common_data(FOR_KEYBLOCK); + sd->workbuf_used = sd->workbuf_size - + vb2_wb_round_up(gbb.rootkey_size); + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER, + "keyblock not enough workbuf for header"); + + reset_common_data(FOR_KEYBLOCK); + mock_read_res_fail_on_call = 2; + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_EX_READ_RESOURCE_INDEX, + "keyblock read keyblock header"); + + reset_common_data(FOR_KEYBLOCK); + sd->workbuf_used = sd->workbuf_size - + vb2_wb_round_up(gbb.rootkey_size) - + vb2_wb_round_up(sizeof(struct vb2_keyblock)); + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_FW_KEYBLOCK_WORKBUF, + "keyblock not enough workbuf for entire keyblock"); + + reset_common_data(FOR_KEYBLOCK); + kb->keyblock_size = sizeof(mock_vblock) + 1; + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "keyblock read keyblock"); + + reset_common_data(FOR_KEYBLOCK); + mock_verify_keyblock_retval = VB2_ERROR_KEYBLOCK_MAGIC; + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_KEYBLOCK_MAGIC, + "keyblock verify keyblock"); + + reset_common_data(FOR_KEYBLOCK); + kb->data_key.key_version = 0x10000; + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE, + "keyblock version range"); + + reset_common_data(FOR_KEYBLOCK); + kb->data_key.key_version = 1; + TEST_EQ(vb2_load_fw_keyblock(ctx), + VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK, + "keyblock rollback"); + + reset_common_data(FOR_KEYBLOCK); + kb->data_key.key_version = 1; + gbb.flags |= VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK; + TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock rollback with GBB flag"); +} + +static void verify_preamble_tests(void) +{ + struct vb2_fw_preamble *pre = &mock_vblock.p.pre; + int expected_offset; + uint32_t v; + + /* Test successful call */ + reset_common_data(FOR_PREAMBLE); + expected_offset = sd->workbuf_used; + TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); + TEST_EQ(sd->fw_version, 0x20002, "combined version"); + TEST_EQ(sd->preamble_offset, expected_offset, + "preamble offset"); + TEST_EQ(sd->preamble_size, pre->preamble_size, "preamble size"); + TEST_EQ(sd->workbuf_used, + vb2_wb_round_up(sd->preamble_offset + + sd->preamble_size), + "workbuf used"); + + /* Test hwcrypto conditions */ + reset_common_data(FOR_PREAMBLE); + + TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden by TPM flag"); + + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden by TPM flag on recovery mode"); + + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, + VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); + + TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); + TEST_EQ(last_used_key.allow_hwcrypto, 0, + "hwcrypto is forbidden on recovery mode"); + + ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; + TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good"); + TEST_EQ(last_used_key.allow_hwcrypto, 1, + "hwcrypto is allowed"); + + + /* Expected failures */ + reset_common_data(FOR_PREAMBLE); + sd->data_key_size = 0; + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_FW_PREAMBLE2_DATA_KEY, + "preamble no data key"); + + reset_common_data(FOR_PREAMBLE); + mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM; + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM, + "preamble unpack data key"); + + reset_common_data(FOR_PREAMBLE); + sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN - + vb2_wb_round_up(sizeof(struct vb2_fw_preamble)); + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER, + "preamble not enough workbuf for header"); + + reset_common_data(FOR_PREAMBLE); + sd->vblock_preamble_offset = sizeof(mock_vblock); + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "preamble read header"); + + reset_common_data(FOR_PREAMBLE); + sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN - + vb2_wb_round_up(sizeof(mock_vblock.p)); + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_FW_PREAMBLE2_WORKBUF, + "preamble not enough workbuf"); + + reset_common_data(FOR_PREAMBLE); + pre->preamble_size = sizeof(mock_vblock); + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_EX_READ_RESOURCE_SIZE, + "preamble read full"); + + reset_common_data(FOR_PREAMBLE); + mock_verify_preamble_retval = VB2_ERROR_PREAMBLE_SIG_INVALID; + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_PREAMBLE_SIG_INVALID, + "preamble verify"); + + reset_common_data(FOR_PREAMBLE); + pre->firmware_version = 0x10000; + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_FW_PREAMBLE_VERSION_RANGE, + "preamble version range"); + + reset_common_data(FOR_PREAMBLE); + pre->firmware_version = 1; + TEST_EQ(vb2_load_fw_preamble(ctx), + VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK, + "preamble version rollback"); + + reset_common_data(FOR_PREAMBLE); + pre->firmware_version = 1; + gbb.flags |= VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK; + TEST_SUCC(vb2_load_fw_preamble(ctx), "version rollback with GBB flag"); + + reset_common_data(FOR_PREAMBLE); + pre->firmware_version = 3; + TEST_SUCC(vb2_load_fw_preamble(ctx), + "preamble version roll forward"); + v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS); + TEST_EQ(v, 0x20003, "roll forward"); + + /* Newer version without result success doesn't roll forward */ + reset_common_data(FOR_PREAMBLE); + pre->firmware_version = 3; + sd->last_fw_result = VB2_FW_RESULT_UNKNOWN; + TEST_SUCC(vb2_load_fw_preamble(ctx), + "preamble version no roll forward 1"); + v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS); + TEST_EQ(v, 0x20002, "no roll forward"); + + /* Newer version with success but for other slot doesn't roll forward */ + reset_common_data(FOR_PREAMBLE); + pre->firmware_version = 3; + sd->last_fw_slot = 1; + TEST_SUCC(vb2_load_fw_preamble(ctx), + "preamble version no roll forward 2"); + v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS); + TEST_EQ(v, 0x20002, "no roll forward"); +} + +int main(int argc, char* argv[]) +{ + verify_keyblock_tests(); + verify_preamble_tests(); + + return gTestSuccess ? 0 : 255; +} diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_host_flashrom_tests.c vboot-utils-0~R99-14469.B/tests/vb2_host_flashrom_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_host_flashrom_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_host_flashrom_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -58,7 +58,7 @@ int captured_verify_int = FLASHROM_VERIFY_UNSPECIFIED; struct option long_opts[] = { { - .name = "fast-verify", + .name = "noverify-all", .has_arg = no_argument, .flag = &captured_verify_int, .val = FLASHROM_VERIFY_FAST, diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_kernel_tests.c vboot-utils-0~R99-14469.B/tests/vb2_kernel_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_kernel_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_kernel_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -14,8 +14,8 @@ #include "2secdata.h" #include "2sysincludes.h" #include "test_common.h" -#include "vb2_common.h" #include "vboot_struct.h" +#include "vboot_api.h" /* Common context for tests */ static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] @@ -24,6 +24,7 @@ static struct vb2_shared_data *sd; static struct vb2_fw_preamble *fwpre; static const char fw_kernel_key_data[36] = "Test kernel key data"; +static enum vb2_boot_mode *boot_mode; /* Mocked function data */ @@ -82,6 +83,14 @@ mock_gbb.recovery_key.key_offset + mock_gbb.recovery_key.key_size; + /* For boot_mode */ + boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode; + if (t == FOR_PHASE1) + *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN; + else if (t == FOR_NORMAL_BOOT) + *boot_mode = VB2_BOOT_MODE_NORMAL; + else + *boot_mode = VB2_BOOT_MODE_UNDEFINED; if (t == FOR_PHASE1) { uint8_t *kdata; @@ -140,7 +149,7 @@ return VB2_SUCCESS; } -vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags) +vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t disk_flags) { /* * TODO: Currently we don't have a good way of testing for an ordered @@ -151,10 +160,10 @@ return mock_vbtlk_retval; TEST_EQ(!!mock_vbtlk_expect_fixed, - !!(get_info_flags & VB_DISK_FLAG_FIXED), + !!(disk_flags & VB_DISK_FLAG_FIXED), " VbTryLoadKernel unexpected fixed disk call"); TEST_EQ(!!mock_vbtlk_expect_removable, - !!(get_info_flags & VB_DISK_FLAG_REMOVABLE), + !!(disk_flags & VB_DISK_FLAG_REMOVABLE), " VbTryLoadKernel unexpected removable disk call"); return mock_vbtlk_retval; @@ -223,9 +232,9 @@ " phone recovery enabled"); TEST_EQ(vb2api_phone_recovery_ui_enabled(ctx), 0, " phone recovery ui disabled"); - /* Make sure diagnostic UI is disabled */ - TEST_EQ(vb2api_diagnostic_ui_enabled(ctx), 0, - " diagnostic ui disabled"); + /* Make sure diagnostic UI is enabled */ + TEST_EQ(vb2api_diagnostic_ui_enabled(ctx), 1, + " diagnostic ui enabled"); /* * Test flags are unchanged for experimental features in recovery path @@ -274,6 +283,7 @@ TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset"); TEST_EQ(sd->kernel_key_size, 0, " workbuf key size"); mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery"); reset_common_data(FOR_PHASE1); @@ -284,6 +294,7 @@ TEST_EQ(sd->kernel_key_offset, 0, " workbuf key offset"); TEST_EQ(sd->kernel_key_size, 0, " workbuf key size"); mock_gbb.h.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; mock_read_res_fail_on_call = 1; TEST_ABORT(vb2api_kernel_phase1(ctx), " fatal for manual recovery"); diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_keyblock_fuzzer.c vboot-utils-0~R99-14469.B/tests/vb2_keyblock_fuzzer.c --- vboot-utils-0~R88-13597.B/tests/vb2_keyblock_fuzzer.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_keyblock_fuzzer.c 2022-02-11 14:46:24.000000000 +0000 @@ -7,6 +7,7 @@ #include "2misc.h" #include "2nvstorage.h" #include "2rsa.h" +#include "2rsa_private.h" #include "2secdata.h" #include "vboot_test.h" diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_misc_tests.c vboot-utils-0~R99-14469.B/tests/vb2_misc_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_misc_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_misc_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -22,6 +22,7 @@ static struct vb2_shared_data *sd; static struct vb2_gbb_header gbb; static struct vb2_secdata_fwmp *fwmp; +static enum vb2_boot_mode *boot_mode; /* Mocked function data */ static enum vb2_resource_index mock_resource_index; @@ -29,7 +30,6 @@ static uint32_t mock_resource_size; static int mock_tpm_clear_called; static int mock_tpm_clear_retval; -static int allow_recovery_retval; static void reset_common_data(void) { @@ -40,7 +40,7 @@ "vb2api_init failed"); sd = vb2_get_sd(ctx); - sd->status = VB2_SD_STATUS_SECDATA_FWMP_INIT; + sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT; memset(&gbb, 0, sizeof(gbb)); @@ -53,16 +53,13 @@ mock_tpm_clear_called = 0; mock_tpm_clear_retval = VB2_SUCCESS; - allow_recovery_retval = 0; + + boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode; + *boot_mode = VB2_BOOT_MODE_NORMAL; }; /* Mocked functions */ -int vb2_allow_recovery(struct vb2_context *c) -{ - return allow_recovery_retval; -} - struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) { return &gbb; @@ -268,12 +265,17 @@ "vb_workbuf_from_ctx() size"); reset_common_data(); + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; TEST_ABORT(VB2_REC_OR_DIE(ctx, "die\n"), "REC_OR_DIE in normal mode"); reset_common_data(); + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; VB2_REC_OR_DIE(ctx, "VB2_REC_OR_DIE() test in recovery mode\n"); /* Would exit here if it didn't work as intended. */ + + reset_common_data(); + VB2_REC_OR_DIE(ctx, "VB2_REC_OR_DIE() test in fw_phase1\n"); } static void gbb_tests(void) @@ -421,12 +423,14 @@ { /* No recovery */ reset_common_data(); + TEST_EQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "recovery not yet decided before testing check_recovery()"); vb2_check_recovery(ctx); TEST_EQ(sd->recovery_reason, 0, "No recovery reason"); - TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, - 0, "Not manual recovery"); TEST_EQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE, 0, "Not recovery mode"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "Recovery decided"); /* From request */ reset_common_data(); @@ -434,10 +438,10 @@ vb2_check_recovery(ctx); TEST_EQ(sd->recovery_reason, 3, "Recovery reason from request"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 3, "NV not cleared"); - TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, - 0, "Not manual recovery"); TEST_NEQ(ctx->flags & VB2_CONTEXT_RECOVERY_MODE, 0, "Recovery mode"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "Recovery decided"); /* From request, but already failed */ reset_common_data(); @@ -447,6 +451,8 @@ TEST_EQ(sd->recovery_reason, 5, "Recovery reason already failed"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 4, "NV not cleared"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "Recovery decided"); /* Override */ reset_common_data(); @@ -455,8 +461,8 @@ vb2_check_recovery(ctx); TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_MANUAL, "Recovery reason forced"); - TEST_NEQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, - 0, "SD flag set"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "Recovery decided"); /* Override subcode TRAIN_AND_REBOOT */ reset_common_data(); @@ -465,8 +471,8 @@ vb2_check_recovery(ctx); TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_MANUAL, "Recovery reason forced"); - TEST_NEQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, - 0, "SD flag set"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "Recovery decided"); /* Promote subcode from BROKEN screen*/ reset_common_data(); @@ -475,8 +481,8 @@ vb2_check_recovery(ctx); TEST_EQ(sd->recovery_reason, VB2_RECOVERY_US_TEST, "Recovery reason forced from BROKEN"); - TEST_NEQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY, - 0, "SD flag set"); + TEST_NEQ(sd->status & VB2_SD_STATUS_RECOVERY_DECIDED, + 0, "Recovery decided"); } static void dev_switch_tests(void) @@ -505,14 +511,14 @@ /* Any normal mode boot clears dev boot flags */ reset_common_data(); vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1); vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1); vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, 1); TEST_SUCC(vb2_check_dev_switch(ctx), "dev mode off"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), 0, " cleared dev boot external"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_LEGACY), - 0, " cleared dev boot legacy"); + TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW), + 0, " cleared dev boot altfw"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY), 0, " cleared dev boot signed only"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT), @@ -589,13 +595,15 @@ /* * secdata_firmware failure in normal mode fails and shows dev=0 even - * if dev mode was on in the (inaccessible) secdata_firmware. + * if dev mode was on in the (inaccessible) secdata_firmware. Since this + * happens in fw_phase1, we do not abort -- we know that when secdata + * is uninitialized here, we must be headed for recovery mode. */ reset_common_data(); vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_FLAGS, VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE); sd->status &= ~VB2_SD_STATUS_SECDATA_FIRMWARE_INIT; - TEST_ABORT(vb2_check_dev_switch(ctx), "secdata_firmware fail normal"); + TEST_SUCC(vb2_check_dev_switch(ctx), "secdata_firmware fail normal"); TEST_EQ(sd->flags & VB2_SD_FLAG_DEV_MODE_ENABLED, 0, " sd not in dev"); TEST_EQ(ctx->flags & VB2_CONTEXT_DEVELOPER_MODE, 0, " ctx not in dev"); @@ -640,24 +648,33 @@ static void enable_dev_tests(void) { reset_common_data(); - vb2_enable_developer_mode(ctx); + TEST_FAIL(vb2api_enable_developer_mode(ctx), + "vb2api_enable_developer_mode - failed"); + TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) & + VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0, + " dev mode flag not set"); + + reset_common_data(); + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + TEST_SUCC(vb2api_enable_developer_mode(ctx), + "vb2api_enable_developer_mode - success"); TEST_NEQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) & VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0, - "dev mode flag set"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), BOOT_EXTERNAL_ON_DEV, - "NV_DEV_BOOT_EXTERNAL set according to compile-time flag"); + " dev mode flag set"); /* secdata_firmware not initialized, aborts */ reset_common_data(); + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; sd->status &= ~VB2_SD_STATUS_SECDATA_FIRMWARE_INIT; - TEST_ABORT(vb2_enable_developer_mode(ctx), + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; + TEST_ABORT(vb2api_enable_developer_mode(ctx), "secdata_firmware no init, enable dev mode aborted"); sd->status |= VB2_SD_STATUS_SECDATA_FIRMWARE_INIT; TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS) & VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE, 0, - "dev mode flag not set"); + " dev mode flag not set"); TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), 0, - "NV_DEV_BOOT_EXTERNAL not set"); + " NV_DEV_BOOT_EXTERNAL not set"); } static void tpm_clear_tests(void) @@ -799,7 +816,7 @@ /* Manual recovery */ reset_common_data(); - allow_recovery_retval = 1; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; sd->recovery_reason = 4; ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, 5); @@ -810,9 +827,9 @@ TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE), 0, " subcode cleared"); - /* BROKEN recovery */ + /* Broken screen */ reset_common_data(); - allow_recovery_retval = 0; + *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN; sd->recovery_reason = 4; ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, 5); @@ -892,14 +909,14 @@ VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL, "no default boot, boot disk"); - /* Set boot legacy by GBB */ + /* Set boot altfw by GBB */ reset_common_data(); - gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY; + gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_ALTFW; vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); TEST_EQ(vb2api_get_dev_default_boot_target(ctx), - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY, - "GBB set default boot legacy"); + VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW, + "GBB set default boot altfw"); /* Boot from internal disk */ reset_common_data(); @@ -911,7 +928,7 @@ /* Boot from external disk */ reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); + ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED; vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); TEST_EQ(vb2api_get_dev_default_boot_target(ctx), @@ -926,116 +943,132 @@ VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL, "default boot external not allowed"); reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); + ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED; vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); TEST_EQ(vb2api_get_dev_default_boot_target(ctx), VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL, "default boot external not allowed"); - /* Boot legacy */ + /* Boot altfw */ reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); + ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED; vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); + VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW); TEST_EQ(vb2api_get_dev_default_boot_target(ctx), - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY, - "set default boot legacy"); + VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW, + "set default boot altfw"); - /* Boot legacy not allowed */ + /* Boot altfw not allowed */ reset_common_data(); vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); + VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW); TEST_EQ(vb2api_get_dev_default_boot_target(ctx), VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL, - "default boot legacy not allowed"); + "default boot altfw not allowed"); reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); + ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED; vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); + VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW); TEST_EQ(vb2api_get_dev_default_boot_target(ctx), VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL, - "default boot legacy not allowed"); + "default boot altfw not allowed"); } -static void dev_boot_allowed_tests(void) +static void fill_dev_boot_flags_tests(void) { /* Dev boot - allowed by default */ reset_common_data(); - TEST_EQ(vb2_dev_boot_allowed(ctx), 1, "dev boot - allowed by default"); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALLOWED, + "dev boot - allowed by default"); /* Dev boot - disabled by FWMP */ reset_common_data(); fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - TEST_EQ(vb2_dev_boot_allowed(ctx), 0, "dev boot - FWMP disabled"); + vb2_fill_dev_boot_flags(ctx); + TEST_FALSE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALLOWED, + "dev boot - FWMP disabled"); /* Dev boot - force enabled by GBB */ reset_common_data(); fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON; - TEST_EQ(vb2_dev_boot_allowed(ctx), 1, "dev boot - GBB force dev on"); - - /* Legacy boot - not allowed by default */ - reset_common_data(); - TEST_EQ(vb2_dev_boot_legacy_allowed(ctx), 0, - "dev boot legacy - not allowed by default"); - - /* Legacy boot - enabled by nvdata */ - reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - TEST_EQ(vb2_dev_boot_legacy_allowed(ctx), 1, - "dev boot legacy - nvdata enabled"); - - /* Legacy boot - enabled by FWMP */ - reset_common_data(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY; - TEST_EQ(vb2_dev_boot_legacy_allowed(ctx), 1, - "dev boot legacy - secdata enabled"); - - /* Legacy boot - force enabled by GBB */ - reset_common_data(); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - TEST_EQ(vb2_dev_boot_legacy_allowed(ctx), 1, - "dev boot legacy - GBB force enabled"); - - /* Legacy boot - set all flags */ - reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY; - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - TEST_EQ(vb2_dev_boot_legacy_allowed(ctx), 1, - "dev boot legacy - all flags set"); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALLOWED, + "dev boot - GBB force dev on"); /* External boot - not allowed by default */ reset_common_data(); - TEST_EQ(vb2_dev_boot_external_allowed(ctx), 0, - "dev boot external - not allowed by default"); + vb2_fill_dev_boot_flags(ctx); + TEST_FALSE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED, + "dev boot external - not allowed by default"); /* External boot - enabled by nvdata */ reset_common_data(); vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1, - "dev boot external - nvdata enabled"); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED, + "dev boot external - nvdata enabled"); /* External boot - enabled by FWMP */ reset_common_data(); fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL; - TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1, - "dev boot external - secdata enabled"); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED, + "dev boot external - secdata enabled"); /* External boot - force enabled by GBB */ reset_common_data(); gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB; - TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1, - "dev boot external - GBB force enabled"); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED, + "dev boot external - GBB force enabled"); /* External boot - set all flags */ reset_common_data(); vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL; gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB; - TEST_EQ(vb2_dev_boot_external_allowed(ctx), 1, - "dev boot external - all flags set"); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED, + "dev boot external - all flags set"); + + /* Alternate boot - not allowed by default */ + reset_common_data(); + vb2_fill_dev_boot_flags(ctx); + TEST_FALSE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED, + "dev boot altfw - not allowed by default"); + + /* Alternate boot - enabled by nvdata */ + reset_common_data(); + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1); + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED, + "dev boot altfw - nvdata enabled"); + + /* Alternate boot - enabled by FWMP */ + reset_common_data(); + fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW; + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED, + "dev boot altfw - secdata enabled"); + + /* Alternate boot - force enabled by GBB */ + reset_common_data(); + gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW; + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED, + "dev boot altfw - GBB force enabled"); + + /* Alternate boot - set all flags */ + reset_common_data(); + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 1); + fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW; + gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW; + vb2_fill_dev_boot_flags(ctx); + TEST_TRUE(ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED, + "dev boot altfw - all flags set"); } static void use_dev_screen_short_delay_tests(void) @@ -1068,7 +1101,7 @@ phone_recovery_enabled_tests(); diagnostic_ui_enabled_tests(); dev_default_boot_tests(); - dev_boot_allowed_tests(); + fill_dev_boot_flags_tests(); use_dev_screen_short_delay_tests(); return gTestSuccess ? 0 : 255; diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_nvstorage_tests.c vboot-utils-0~R99-14469.B/tests/vb2_nvstorage_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_nvstorage_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_nvstorage_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -41,7 +41,7 @@ {VB2_NV_LOCALIZATION_INDEX, 0, 0x69, 0xB0, "localization index"}, {VB2_NV_KERNEL_FIELD, 0, 0x1234, 0xFEDC, "kernel field"}, {VB2_NV_DEV_BOOT_EXTERNAL, 0, 1, 0, "dev boot usb"}, - {VB2_NV_DEV_BOOT_LEGACY, 0, 1, 0, "dev boot legacy"}, + {VB2_NV_DEV_BOOT_ALTFW, 0, 1, 0, "dev boot altfw"}, {VB2_NV_DEV_BOOT_SIGNED_ONLY, 0, 1, 0, "dev boot custom"}, {VB2_NV_DEV_DEFAULT_BOOT, 0, 1, 2, "dev default boot"}, {VB2_NV_DIAG_REQUEST, 0, 1, 0, "diagnostic rom request"}, diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_preamble_fuzzer.c vboot-utils-0~R99-14469.B/tests/vb2_preamble_fuzzer.c --- vboot-utils-0~R88-13597.B/tests/vb2_preamble_fuzzer.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_preamble_fuzzer.c 2022-02-11 14:46:24.000000000 +0000 @@ -7,6 +7,7 @@ #include "2misc.h" #include "2nvstorage.h" #include "2rsa.h" +#include "2rsa_private.h" #include "2secdata.h" #include "vboot_test.h" diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_rsa_utility_tests.c vboot-utils-0~R99-14469.B/tests/vb2_rsa_utility_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_rsa_utility_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_rsa_utility_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -8,6 +8,7 @@ #include "2common.h" #include "2rsa.h" +#include "2rsa_private.h" #include "2sysincludes.h" #include "file_keys.h" #include "rsa_padding_test.h" diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_secdata_firmware_tests.c vboot-utils-0~R99-14469.B/tests/vb2_secdata_firmware_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_secdata_firmware_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_secdata_firmware_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -28,6 +28,9 @@ sd = vb2_get_sd(ctx); + /* Most tests assume we have passed fw_phase1() */ + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; + sec = (struct vb2_secdata_firmware *)ctx->secdata_firmware; } @@ -136,6 +139,25 @@ 0x123456ff), "Set uninitialized"); test_changed(ctx, 0, "Set uninitialized doesn't change data"); + + /* Read/write uninitialized in recovery mode */ + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS), 0, + "Get uninitialized (recmode)"); + test_changed(ctx, 0, "Get uninitialized (recmode) doesn't change data"); + vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, + 0x123456ff); + test_changed(ctx, 0, "Set uninitialized (recmode) doesn't change data"); + + /* Read/write early in fw_phase1 */ + ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; + sd->status &= ~VB2_SD_STATUS_RECOVERY_DECIDED; + TEST_EQ(vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS), 0, + "Get uninitialized (phase1)"); + test_changed(ctx, 0, "Get uninitialized (phase1) doesn't change data"); + vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS, + 0x123456ff); + test_changed(ctx, 0, "Set uninitialized (phase1) doesn't change data"); } int main(int argc, char* argv[]) diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_secdata_fwmp_tests.c vboot-utils-0~R99-14469.B/tests/vb2_secdata_fwmp_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_secdata_fwmp_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_secdata_fwmp_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -25,7 +25,8 @@ "vb2api_init failed"); sd = vb2_get_sd(ctx); - sd->status = VB2_SD_STATUS_SECDATA_FWMP_INIT; + sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT; + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; memset(&gbb, 0, sizeof(gbb)); @@ -199,6 +200,13 @@ sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT; TEST_ABORT(vb2_secdata_fwmp_get_flag(ctx, 0), "non-init in normal mode triggers abort"); + + /* FWMP hasn't been initialized (before recovery decision) */ + reset_common_data(); + sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT; + sd->status &= ~VB2_SD_STATUS_RECOVERY_DECIDED; + TEST_EQ(vb2_secdata_fwmp_get_flag(ctx, 0), 0, + "non-init in fw_phase1 forces default flag value"); } static void get_dev_key_hash_test(void) @@ -222,6 +230,13 @@ TEST_ABORT(vb2_secdata_fwmp_get_dev_key_hash(ctx), "non-init in normal mode triggers abort"); + /* FWMP hasn't been initialized (before recovery decision) */ + reset_common_data(); + sd->status &= ~VB2_SD_STATUS_SECDATA_FWMP_INIT; + sd->status &= ~VB2_SD_STATUS_RECOVERY_DECIDED; + TEST_TRUE(vb2_secdata_fwmp_get_dev_key_hash(ctx) == NULL, + "non-init in fw_phase1 forces NULL pointer"); + /* Success case */ reset_common_data(); TEST_TRUE(vb2_secdata_fwmp_get_dev_key_hash(ctx) == diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_secdata_kernel_tests.c vboot-utils-0~R99-14469.B/tests/vb2_secdata_kernel_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_secdata_kernel_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_secdata_kernel_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -30,6 +30,9 @@ sd = vb2_get_sd(ctx); + /* Most tests assume we have passed fw_phase1() */ + sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED; + sec02 = (struct vb2_secdata_kernel_v0 *)ctx->secdata_kernel; sec10 = (struct vb2_secdata_kernel_v1 *)ctx->secdata_kernel; } @@ -245,7 +248,27 @@ "Set uninitialized"); test_changed(ctx, 0, "Set uninitialized doesn't change data"); + /* Read/write uninitialized in recovery mode */ + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + TEST_EQ(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS), 0, + "Get uninitialized (recmode)"); + test_changed(ctx, 0, "Get uninitialized (recmode) doesn't change data"); + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, + 0x123456ff); + test_changed(ctx, 0, "Set uninitialized (recmode) doesn't change data"); + + /* Read/write early in fw_phase1 */ + ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE; + sd->status &= ~VB2_SD_STATUS_RECOVERY_DECIDED; + TEST_EQ(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS), 0, + "Get uninitialized (phase1)"); + test_changed(ctx, 0, "Get uninitialized (phase1) doesn't change data"); + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, + 0x123456ff); + test_changed(ctx, 0, "Set uninitialized (phase1) doesn't change data"); + /* Test EC hash set */ + reset_common_data(); vb2api_secdata_kernel_create(ctx); vb2_secdata_kernel_init(ctx); memset(ec_hash, 0xaa, sizeof(ec_hash)); diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_sha256_x86_tests.c vboot-utils-0~R99-14469.B/tests/vb2_sha256_x86_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_sha256_x86_tests.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_sha256_x86_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -0,0 +1,137 @@ +/* Copyright 2021 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. + */ + +/* FIPS 180-2 Tests for message digest functions. */ + +#include +#include + +#include "2api.h" +#include "2sha.h" +#include "sha_test_vectors.h" +#include "test_common.h" + +vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size, + enum vb2_hash_algorithm hash_alg, uint8_t *digest, + uint32_t digest_size) +{ + VB2_TRY(vb2ex_hwcrypto_digest_init(hash_alg, size)); + VB2_TRY(vb2ex_hwcrypto_digest_extend(buf, size)); + + return vb2ex_hwcrypto_digest_finalize(digest, digest_size); + +} + +static void sha256_tests(void) +{ + uint8_t digest[VB2_SHA256_DIGEST_SIZE]; + uint8_t *test_inputs[3]; + const uint8_t expect_multiple[VB2_SHA256_DIGEST_SIZE] = { + 0x07, 0x08, 0xb4, 0xca, 0x46, 0x4c, 0x40, 0x39, + 0x07, 0x06, 0x88, 0x80, 0x30, 0x55, 0x5d, 0x86, + 0x0e, 0x4a, 0x0d, 0x2b, 0xc6, 0xc4, 0x87, 0x39, + 0x2c, 0x16, 0x55, 0xb0, 0x82, 0x13, 0x16, 0x29 }; + int i; + + test_inputs[0] = (uint8_t *) oneblock_msg; + test_inputs[1] = (uint8_t *) multiblock_msg1; + test_inputs[2] = (uint8_t *) long_msg; + + for (i = 0; i < 3; i++) { + TEST_SUCC(vb2_digest_buffer(test_inputs[i], + strlen((char *)test_inputs[i]), + VB2_HASH_SHA256, + digest, sizeof(digest)), + "vb2_digest_buffer() SHA256"); + TEST_EQ(memcmp(digest, sha256_results[i], sizeof(digest)), + 0, "SHA-256 digest"); + } + + TEST_EQ(vb2_digest_buffer(test_inputs[0], + strlen((char *)test_inputs[0]), + VB2_HASH_SHA256, digest, sizeof(digest) - 1), + VB2_ERROR_SHA_FINALIZE_DIGEST_SIZE, + "vb2_digest_buffer() too small"); + + /* Test multiple small extends */ + vb2ex_hwcrypto_digest_init(VB2_HASH_SHA256, 15); + vb2ex_hwcrypto_digest_extend((uint8_t *)"test1", 5); + vb2ex_hwcrypto_digest_extend((uint8_t *)"test2", 5); + vb2ex_hwcrypto_digest_extend((uint8_t *)"test3", 5); + vb2ex_hwcrypto_digest_finalize(digest, VB2_SHA256_DIGEST_SIZE); + TEST_EQ(memcmp(digest, expect_multiple, sizeof(digest)), 0, + "SHA-256 multiple extends"); + + TEST_EQ(vb2_hash_block_size(VB2_HASH_SHA256), VB2_SHA256_BLOCK_SIZE, + "vb2_hash_block_size(VB2_HASH_SHA256)"); + +} + +static void known_value_tests(void) +{ + const char sentinel[] = "keepme"; + union { + struct vb2_hash hash; + char overflow[sizeof(struct vb2_hash) + 8]; + } test; + +#define TEST_KNOWN_VALUE(algo, str, value) \ + TEST_EQ(vb2_digest_size(algo), sizeof(value) - 1, \ + "Known hash size " #algo ": " #str); \ + { \ + char *sent_base = test.overflow + \ + offsetof(struct vb2_hash, raw) + sizeof(value) - 1; \ + strcpy(sent_base, sentinel); \ + strcpy(sent_base, sentinel); \ + TEST_SUCC(vb2_digest_buffer((const uint8_t *)str, \ + sizeof(str) - 1, \ + algo, test.hash.raw, \ + vb2_digest_size(algo)), \ + "Calculate known hash " #algo ": " #str); \ + TEST_EQ(memcmp(test.hash.raw, value, sizeof(value) - 1), 0, \ + "Known hash " #algo ": " #str); \ + TEST_EQ(strcmp(sent_base, sentinel), 0, \ + "Overflow known hash " #algo ": " #str); \ + } + + TEST_KNOWN_VALUE(VB2_HASH_SHA256, "", + "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9" + "\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52" + "\xb8\x55"); + + const char long_test_string[] = "abcdefghbcdefghicdefghijdefghijkefgh" + "ijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu"; + TEST_KNOWN_VALUE(VB2_HASH_SHA256, long_test_string, + "\xcf\x5b\x16\xa7\x78\xaf\x83\x80\x03\x6c\xe5\x9e\x7b\x04\x92" + "\x37\x0b\x24\x9b\x11\xe8\xf0\x7a\x51\xaf\xac\x45\x03\x7a\xfe" + "\xe9\xd1"); + + /* vim helper to escape hex: :s/\([a-f0-9]\{2\}\)/\\x\1/g */ +#undef TEST_KNOWN_VALUE +} + +int main(int argc, char *argv[]) +{ + uint32_t a, b = 0, c, d; + /* EAX = 07H, sub-leaf 0 */ + __get_cpuid_count(7, 0, &a, &b, &c, &d); + if ((b & bit_SHA) == 0) { + fprintf(stderr, "SHA-NI not supported.\n"); + return 254; + } + + /* Initialize long_msg with 'a' x 1,000,000 */ + long_msg = (char *) malloc(1000001); + memset(long_msg, 'a', 1000000); + long_msg[1000000]=0; + + sha256_tests(); + known_value_tests(); + + free(long_msg); + + return gTestSuccess ? 0 : 255; +} diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_sha_tests.c vboot-utils-0~R99-14469.B/tests/vb2_sha_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_sha_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_sha_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -172,21 +172,27 @@ static void known_value_tests(void) { const char sentinel[] = "keepme"; - struct { + union { struct vb2_hash hash; - uint8_t overflow[8]; + char overflow[sizeof(struct vb2_hash) + 8]; } test; + #define TEST_KNOWN_VALUE(algo, str, value) \ TEST_EQ(vb2_digest_size(algo), sizeof(value) - 1, \ "Known hash size " #algo ": " #str); \ - strcpy((char *)&test.hash.raw[sizeof(value) - 1], sentinel); \ - TEST_SUCC(vb2_hash_calculate(str, sizeof(str) - 1, algo, &test.hash), \ - "Calculate known hash " #algo ": " #str); \ - TEST_EQ(memcmp(test.hash.raw, value, sizeof(value) - 1), 0, \ - "Known hash " #algo ": " #str); \ - TEST_EQ(strcmp((char *)&test.hash.raw[sizeof(value) - 1], sentinel), 0,\ - "Overflow known hash " #algo ": " #str); + { \ + char *sent_base = test.overflow + \ + offsetof(struct vb2_hash, raw) + sizeof(value) - 1; \ + strcpy(sent_base, sentinel); \ + TEST_SUCC(vb2_hash_calculate(str, sizeof(str) - 1, \ + algo, &test.hash), \ + "Calculate known hash " #algo ": " #str); \ + TEST_EQ(memcmp(test.hash.raw, value, sizeof(value) - 1), 0, \ + "Known hash " #algo ": " #str); \ + TEST_EQ(strcmp(sent_base, sentinel), 0, \ + "Overflow known hash " #algo ": " #str); \ + } TEST_KNOWN_VALUE(VB2_HASH_SHA1, "", "\xda\x39\xa3\xee\x5e\x6b\x4b\x0d\x32\x55\xbf\xef\x95\x60\x18" diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_ui_action_tests.c vboot-utils-0~R99-14469.B/tests/vb2_ui_action_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_ui_action_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_ui_action_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1067 +0,0 @@ -/* Copyright 2020 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. - * - * Tests for UI related actions. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2ui.h" -#include "2ui_private.h" -#include "test_common.h" -#include "vboot_kernel.h" - -/* Fixed value for ignoring some checks. */ -#define MOCK_IGNORE 0xffffu - -/* Mock screen index for testing screen utility functions. */ -#define MOCK_NO_SCREEN 0xef00 -#define MOCK_SCREEN_BASE 0xef10 -#define MOCK_SCREEN_MENU 0xef11 -#define MOCK_SCREEN_TARGET0 0xef20 -#define MOCK_SCREEN_TARGET1 0xef21 -#define MOCK_SCREEN_TARGET2 0xef22 -#define MOCK_SCREEN_ACTION 0xef30 -#define MOCK_SCREEN_ALL_ACTION 0xef32 - -/* Mock data */ -/* TODO(b/156448738): Add tests for timer_disabled and error_code */ -struct display_call { - const struct vb2_screen_info *screen; - uint32_t locale_id; - uint32_t selected_item; - uint32_t disabled_item_mask; - uint32_t hidden_item_mask; - int timer_disabled; - uint32_t current_page; - enum vb2_ui_error error_code; -} __attribute__((packed)); - -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static struct vb2_gbb_header gbb; - -static int mock_calls_until_shutdown; - -static struct vb2_ui_context mock_ui_context; - -static struct display_call mock_displayed[64]; -static int mock_displayed_count; -static int mock_displayed_i; - -static uint32_t mock_key[64]; -static int mock_key_trusted[64]; -static int mock_key_count; -static int mock_key_total; - -static int mock_get_screen_info_called; - -static vb2_error_t mock_vbtlk_retval; -static uint32_t mock_vbtlk_expected_flag; - -static int mock_dev_boot_allowed; -static int mock_dev_boot_legacy_allowed; - -static int mock_vbexlegacy_called; -static enum VbAltFwIndex_t mock_altfw_num_last; -static uint32_t mock_bootloader_count; - -static uint32_t mock_time_ms; -static const uint32_t mock_time_start_ms = 31ULL * VB2_MSEC_PER_SEC; - -/* Mock actions */ -static uint32_t mock_action_called; -static uint32_t mock_action_countdown_limit; -static vb2_error_t mock_action_countdown(struct vb2_ui_context *ui) -{ - if (++mock_action_called >= mock_action_countdown_limit) - return VB2_SUCCESS; - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t mock_action_screen_change(struct vb2_ui_context *ui) -{ - return vb2_ui_screen_change(ui, MOCK_SCREEN_BASE); -} - -static vb2_error_t mock_action_base(struct vb2_ui_context *ui) -{ - mock_action_called++; - return VB2_SUCCESS; -} - -static int mock_action_flags; -static vb2_error_t mock_action_flag0(struct vb2_ui_context *ui) -{ - if ((1 << 0) & mock_action_flags) - return VB2_SUCCESS; - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t mock_action_flag1(struct vb2_ui_context *ui) -{ - if ((1 << 1) & mock_action_flags) - return VB2_SUCCESS; - return VB2_REQUEST_UI_CONTINUE; -} - -static vb2_error_t mock_action_flag2(struct vb2_ui_context *ui) -{ - if ((1 << 2) & mock_action_flags) - return VB2_SUCCESS; - return VB2_REQUEST_UI_CONTINUE; -} - -static uint32_t mock_action_delay_ms; -static vb2_error_t mock_action_msleep(struct vb2_ui_context *ui) -{ - vb2ex_msleep(mock_action_delay_ms); - return VB2_REQUEST_UI_CONTINUE; -} - -/* Mock screens */ -struct vb2_screen_info mock_screen_temp; -const struct vb2_screen_info mock_screen_blank = { - .id = VB2_SCREEN_BLANK, - .name = "mock_screen_blank", -}; -const struct vb2_screen_info mock_screen_base = { - .id = MOCK_SCREEN_BASE, - .name = "mock_screen_base: menuless screen", -}; -const struct vb2_menu_item mock_screen_menu_items[] = { - { - .text = "item 0", - .target = MOCK_SCREEN_TARGET0, - }, - { - .text = "item 1", - .target = MOCK_SCREEN_TARGET1, - }, - { - .text = "item 2", - .target = MOCK_SCREEN_TARGET2, - }, - { - .text = "item 3", - .action = mock_action_base, - }, - { - .text = "item 4 (no target)", - }, -}; -const struct vb2_screen_info mock_screen_menu = { - .id = MOCK_SCREEN_MENU, - .name = "mock_screen_menu: screen with 5 items", - .menu = { - .num_items = ARRAY_SIZE(mock_screen_menu_items), - .items = mock_screen_menu_items, - }, -}; -const struct vb2_screen_info mock_screen_target0 = { - .id = MOCK_SCREEN_TARGET0, - .name = "mock_screen_target0", -}; -const struct vb2_screen_info mock_screen_target1 = { - .id = MOCK_SCREEN_TARGET1, - .name = "mock_screen_target1", -}; -const struct vb2_screen_info mock_screen_target2 = { - .id = MOCK_SCREEN_TARGET2, - .name = "mock_screen_target2", -}; -const struct vb2_screen_info mock_screen_action = { - .id = MOCK_SCREEN_ACTION, - .name = "mock_screen_action", - .action = mock_action_countdown, -}; -const struct vb2_menu_item mock_screen_all_action_items[] = { - { - .text = "all_action_screen_item", - .action = mock_action_flag1, - }, -}; -const struct vb2_screen_info mock_screen_all_action = { - .id = MOCK_SCREEN_ALL_ACTION, - .name = "mock_screen_all_action", - .action = mock_action_flag0, - .menu = { - .num_items = ARRAY_SIZE(mock_screen_all_action_items), - .items = mock_screen_all_action_items, - }, -}; - -static void screen_state_eq(const struct vb2_screen_state *state, - enum vb2_screen screen, - uint32_t selected_item, - uint32_t hidden_item_mask) -{ - if (screen != MOCK_IGNORE) { - if (state->screen == NULL) - TEST_TRUE(0, " state.screen does not exist"); - else - TEST_EQ(state->screen->id, screen, " state.screen"); - } - if (selected_item != MOCK_IGNORE) - TEST_EQ(state->selected_item, - selected_item, " state.selected_item"); - if (hidden_item_mask != MOCK_IGNORE) - TEST_EQ(state->hidden_item_mask, - hidden_item_mask, " state.hidden_item_mask"); -} - -static void add_mock_key(uint32_t press, int trusted) -{ - if (mock_key_total >= ARRAY_SIZE(mock_key) || - mock_key_total >= ARRAY_SIZE(mock_key_trusted)) { - TEST_TRUE(0, " mock_key ran out of entries!"); - return; - } - - mock_key[mock_key_total] = press; - mock_key_trusted[mock_key_total] = trusted; - mock_key_total++; -} - -static void add_mock_keypress(uint32_t press) -{ - add_mock_key(press, 0); -} - - -static void set_mock_vbtlk(vb2_error_t retval, uint32_t get_info_flags) -{ - mock_vbtlk_retval = retval; - mock_vbtlk_expected_flag = get_info_flags; -} - -static void displayed_eq(const char *text, - enum vb2_screen screen, - uint32_t locale_id, - uint32_t selected_item, - uint32_t hidden_item_mask, - int line) -{ - char text_info[32], text_buf[128]; - - sprintf(text_info, "(line #%d, displayed #%d)", line, mock_displayed_i); - - if (mock_displayed_i >= mock_displayed_count) { - sprintf(text_buf, " %s missing screen %s", - text_info, text); - TEST_TRUE(0, text_buf); - return; - } - - if (screen != MOCK_IGNORE) { - sprintf(text_buf, " %s screen of %s", text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].screen->id, screen, - text_buf); - } - if (locale_id != MOCK_IGNORE) { - sprintf(text_buf, " %s locale_id of %s", text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].locale_id, locale_id, - text_buf); - } - if (selected_item != MOCK_IGNORE) { - sprintf(text_buf, " %s selected_item of %s", - text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].selected_item, - selected_item, text_buf); - } - if (hidden_item_mask != MOCK_IGNORE) { - sprintf(text_buf, " %s hidden_item_mask of %s", - text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].hidden_item_mask, - hidden_item_mask, text_buf); - } - mock_displayed_i++; -} - -static void displayed_no_extra(int line) -{ - char text_info[32], text_buf[128]; - - sprintf(text_info, "(line #%d)", line); - - if (mock_displayed_i == 0) - sprintf(text_buf, " %s no screen", text_info); - else - sprintf(text_buf, " %s no extra screens", text_info); - TEST_EQ(mock_displayed_count, mock_displayed_i, text_buf); -} - -#define DISPLAYED_EQ(...) displayed_eq(__VA_ARGS__, __LINE__) - -#define DISPLAYED_PASS() \ - displayed_eq("", MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, \ - __LINE__) - -#define DISPLAYED_NO_EXTRA() displayed_no_extra(__LINE__) - -/* Reset mock data (for use before each test) */ -static void reset_common_data(void) -{ - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - - memset(&gbb, 0, sizeof(gbb)); - - vb2_nv_init(ctx); - - sd = vb2_get_sd(ctx); - - /* For check_shutdown_request */ - mock_calls_until_shutdown = 10; - - /* Reset mock_screen_temp for test by test temporary screen_info */ - mock_screen_temp = (struct vb2_screen_info){ - .id = MOCK_NO_SCREEN, - .name = "mock_screen_temp", - }; - - /* Mock ui_context based on mock screens */ - memset(&mock_ui_context, 0, sizeof(mock_ui_context)); - mock_ui_context.ctx = ctx; - - if (!mock_ui_context.state) - mock_ui_context.state = malloc(sizeof(*mock_ui_context.state)); - memset(mock_ui_context.state, 0, sizeof(*mock_ui_context.state)); - mock_ui_context.state->screen = &mock_screen_temp; - - /* For vb2ex_display_ui */ - memset(mock_displayed, 0, sizeof(mock_displayed)); - mock_displayed_count = 0; - mock_displayed_i = 0; - - /* For VbExKeyboardRead */ - memset(mock_key, 0, sizeof(mock_key)); - memset(mock_key_trusted, 0, sizeof(mock_key_trusted)); - mock_key_count = 0; - mock_key_total = 0; - - /* For mock actions */ - mock_action_called = 0; - mock_action_countdown_limit = 1; - mock_action_flags = 0; - mock_action_delay_ms = 0; - - /* For chagen_screen and vb2_get_screen_info */ - mock_get_screen_info_called = 0; - - /* For VbTryLoadKernel */ - mock_vbtlk_retval = VB2_ERROR_MOCK; - mock_vbtlk_expected_flag = MOCK_IGNORE; - - /* For dev_boot* in 2misc.h */ - mock_dev_boot_allowed = 1; - mock_dev_boot_legacy_allowed = 0; - - /* For VbExLegacy */ - mock_vbexlegacy_called = 0; - mock_altfw_num_last = -100; - mock_bootloader_count = 2; - - /* For vb2ex_mtime and vb2ex_msleep */ - mock_time_ms = mock_time_start_ms; -} - -/* Mock functions */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -uint32_t VbExIsShutdownRequested(void) -{ - if (mock_calls_until_shutdown < 0) /* Never request shutdown */ - return 0; - if (mock_calls_until_shutdown == 0) - return 1; - mock_calls_until_shutdown--; - - return 0; -} - -const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen screen) -{ - mock_get_screen_info_called++; - - switch ((int)screen) { - case VB2_SCREEN_BLANK: - return &mock_screen_blank; - case MOCK_SCREEN_BASE: - return &mock_screen_base; - case MOCK_SCREEN_MENU: - return &mock_screen_menu; - case MOCK_SCREEN_TARGET0: - return &mock_screen_target0; - case MOCK_SCREEN_TARGET1: - return &mock_screen_target1; - case MOCK_SCREEN_TARGET2: - return &mock_screen_target2; - case MOCK_SCREEN_ACTION: - return &mock_screen_action; - case MOCK_SCREEN_ALL_ACTION: - return &mock_screen_all_action; - case MOCK_NO_SCREEN: - return NULL; - default: - mock_screen_temp.id = screen; - return &mock_screen_temp; - } -} - -vb2_error_t vb2ex_display_ui(enum vb2_screen screen, - uint32_t locale_id, - uint32_t selected_item, - uint32_t disabled_item_mask, - uint32_t hidden_item_mask, - int timer_disabled, - uint32_t current_page, - enum vb2_ui_error error_code) -{ - struct display_call displayed = (struct display_call){ - .screen = vb2_get_screen_info(screen), - .locale_id = locale_id, - .selected_item = selected_item, - .disabled_item_mask = disabled_item_mask, - .hidden_item_mask = hidden_item_mask, - .timer_disabled = timer_disabled, - .current_page = current_page, - .error_code = error_code, - }; - - /* Ignore repeated calls with same arguments */ - if (mock_displayed_count > 0 && - !memcmp(&mock_displayed[mock_displayed_count - 1], &displayed, - sizeof(struct display_call))) - return VB2_SUCCESS; - - VB2_DEBUG("displayed %d: screen=%#x, locale_id=%u, selected_item=%u, " - "disabled_item_mask=%#x, hidden_item_mask=%#x, " - "timer_disabled=%d, current_page=%u, error=%#x\n", - mock_displayed_count, screen, locale_id, selected_item, - disabled_item_mask, hidden_item_mask, - timer_disabled, current_page, error_code); - - if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) { - TEST_TRUE(0, " mock vb2ex_display_ui ran out of entries!"); - return VB2_ERROR_MOCK; - } - - mock_displayed[mock_displayed_count++] = displayed; - - return VB2_SUCCESS; -} - -uint32_t VbExKeyboardRead(void) -{ - return VbExKeyboardReadWithFlags(NULL); -} - -uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags) -{ - if (mock_key_count < mock_key_total) { - if (key_flags != NULL) { - if (mock_key_trusted[mock_key_count]) - *key_flags = VB_KEY_FLAG_TRUSTED_KEYBOARD; - else - *key_flags = 0; - } - return mock_key[mock_key_count++]; - } - - return 0; -} - -vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags) -{ - TEST_EQ(mock_vbtlk_expected_flag, get_info_flags, - " unexpected get_info_flags"); - return mock_vbtlk_retval; -} - -int vb2_dev_boot_allowed(struct vb2_context *c) -{ - return mock_dev_boot_allowed; -} - -int vb2_dev_boot_legacy_allowed(struct vb2_context *c) -{ - return mock_dev_boot_legacy_allowed; -} - -vb2_error_t VbExLegacy(enum VbAltFwIndex_t altfw_num) -{ - mock_vbexlegacy_called++; - mock_altfw_num_last = altfw_num; - - if (altfw_num <= mock_bootloader_count) - return VB2_SUCCESS; - else - return VB2_ERROR_UNKNOWN; -} - -uint32_t vb2ex_get_bootloader_count(void) -{ - return mock_bootloader_count; -} - -uint32_t vb2ex_mtime(void) -{ - return mock_time_ms; -} - -void vb2ex_msleep(uint32_t msec) -{ - mock_time_ms += msec; -} - -/* Tests */ -static void menu_prev_tests(void) -{ - VB2_DEBUG("Testing menu_prev...\n"); - - /* Valid action */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.key = VB_KEY_UP; - TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "valid action"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1, - MOCK_IGNORE); - - /* Valid action with hidden mask */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->hidden_item_mask = 0x0a; /* 0b01010 */ - mock_ui_context.key = VB_KEY_UP; - TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "valid action with hidden mask"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 0, - MOCK_IGNORE); - - /* Disabled mask does not affect menu_prev */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->disabled_item_mask = 0x0a; /* 0b01010 */ - mock_ui_context.key = VB_KEY_UP; - TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "valid action with disabled mask"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1, - MOCK_IGNORE); - - /* Invalid action (blocked) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 0; - mock_ui_context.key = VB_KEY_UP; - TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "invalid action (blocked)"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 0, - MOCK_IGNORE); - - /* Invalid action (blocked by mask) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->hidden_item_mask = 0x0b; /* 0b01011 */ - mock_ui_context.key = VB_KEY_UP; - TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "invalid action (blocked by mask)"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2, - MOCK_IGNORE); - - /* Ignore volume-up when not DETACHABLE */ - if (!DETACHABLE) { - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.key = VB_BUTTON_VOL_UP_SHORT_PRESS; - TEST_EQ(vb2_ui_menu_prev(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "ignore volume-up when not DETACHABLE"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2, - MOCK_IGNORE); - } - - VB2_DEBUG("...done.\n"); -} - -static void menu_next_tests(void) -{ - VB2_DEBUG("Testing menu_next...\n"); - - /* Valid action */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.key = VB_KEY_DOWN; - TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "valid action"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 3, - MOCK_IGNORE); - - /* Valid action with hidden mask */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->hidden_item_mask = 0x0a; /* 0b01010 */ - mock_ui_context.key = VB_KEY_DOWN; - TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "valid action with hidden mask"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4, - MOCK_IGNORE); - - /* Disabled mask does not affect menu_next */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->disabled_item_mask = 0x0a; /* 0b01010 */ - mock_ui_context.key = VB_KEY_DOWN; - TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "valid action with disabled mask"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 3, - MOCK_IGNORE); - - /* Invalid action (blocked) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 4; - mock_ui_context.key = VB_KEY_DOWN; - TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "invalid action (blocked)"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4, - MOCK_IGNORE); - - /* Invalid action (blocked by mask) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->hidden_item_mask = 0x1a; /* 0b11010 */ - mock_ui_context.key = VB_KEY_DOWN; - TEST_EQ(vb2_ui_menu_next(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "invalid action (blocked by mask)"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2, - MOCK_IGNORE); - - /* Ignore volume-down when not DETACHABLE */ - if (!DETACHABLE) { - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.key = VB_BUTTON_VOL_DOWN_SHORT_PRESS; - TEST_EQ(vb2_ui_menu_next(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "ignore volume-down when not DETACHABLE"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 2, - MOCK_IGNORE); - } - - VB2_DEBUG("...done.\n"); -} - -static void menu_select_tests(void) -{ - VB2_DEBUG("Testing menu_select...\n"); - - /* select action with no item screen */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_base; - mock_ui_context.key = VB_KEY_ENTER; - TEST_EQ(vb2_ui_menu_select(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "vb2_ui_menu_select with no item screen"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_BASE, 0, - MOCK_IGNORE); - - /* Try to select an item with a target (item 2) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 2; - mock_ui_context.key = VB_KEY_ENTER; - TEST_EQ(vb2_ui_menu_select(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "select an item with a target"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_TARGET2, 0, - MOCK_IGNORE); - - /* Try to select an item with an action (item 3) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 3; - mock_ui_context.key = VB_KEY_ENTER; - TEST_EQ(vb2_ui_menu_select(&mock_ui_context), - VB2_SUCCESS, "select an item with an action"); - TEST_EQ(mock_action_called, 1, " action called once"); - - /* Try to select an item with neither targets nor actions (item 4) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 4; - mock_ui_context.key = VB_KEY_ENTER; - TEST_EQ(vb2_ui_menu_select(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "select an item with neither targets nor actions"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 4, - MOCK_IGNORE); - - /* Cannot select a disabled item (item 3) */ - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 3; - mock_ui_context.state->disabled_item_mask = 0x08; /* 0b01000 */ - mock_ui_context.key = VB_KEY_ENTER; - TEST_EQ(vb2_ui_menu_select(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "cannot select a disabled item"); - TEST_EQ(mock_action_called, 0, " no action called"); - - /* Ignore power button short press when not DETACHABLE */ - if (!DETACHABLE) { - reset_common_data(); - mock_ui_context.state->screen = &mock_screen_menu; - mock_ui_context.state->selected_item = 1; - mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(vb2_ui_menu_select(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "ignore power button short press when not DETACHABLE"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, 1, - MOCK_IGNORE); - } - - VB2_DEBUG("...done.\n"); -} - -static void vb2_ui_developer_mode_boot_alternate_action_tests(void) -{ - VB2_DEBUG("Test developer mode boot alternate action...\n"); - - /* Not allowed: not in dev mode */ - reset_common_data(); - mock_dev_boot_legacy_allowed = 1; - TEST_EQ(vb2_ui_developer_mode_boot_alternate_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "not allowed: not in dev mode"); - TEST_EQ(mock_vbexlegacy_called, 0, " VbExLegacy not called"); - - /* Not allowed: dev boot not allowed */ - reset_common_data(); - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; - mock_dev_boot_allowed = 0; - mock_dev_boot_legacy_allowed = 1; - TEST_EQ(vb2_ui_developer_mode_boot_alternate_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "not allowed: dev boot not allowed"); - TEST_EQ(mock_vbexlegacy_called, 0, " VbExLegacy not called"); - - /* Not allowed: boot legacy not allowed */ - reset_common_data(); - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; - TEST_EQ(vb2_ui_developer_mode_boot_alternate_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "not allowed: boot legacy not allowed"); - TEST_EQ(mock_vbexlegacy_called, 0, " VbExLegacy not called"); - - /* Allowed */ - reset_common_data(); - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; - mock_dev_boot_legacy_allowed = 1; - mock_ui_context.state->selected_item = 2; - TEST_EQ(vb2_ui_developer_mode_boot_alternate_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "allowed"); - TEST_EQ(mock_vbexlegacy_called, 1, " VbExLegacy called once"); - TEST_EQ(mock_altfw_num_last, 2, " select bootloader #2"); - - /* CTRL+L = default bootloader */ - reset_common_data(); - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; - mock_dev_boot_legacy_allowed = 1; - mock_ui_context.key = VB_KEY_CTRL('L'); - mock_ui_context.state->selected_item = 4; /* Ignored */ - TEST_EQ(vb2_ui_developer_mode_boot_alternate_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "allowed: ctrl+l"); - TEST_EQ(mock_vbexlegacy_called, 1, " VbExLegacy called once"); - TEST_EQ(mock_altfw_num_last, 0, " select bootloader #0"); - - VB2_DEBUG("...done.\n"); -} - -static void manual_recovery_action_tests(void) -{ - VB2_DEBUG("Testing manual recovery action...\n"); - - /* SUCCESS */ - reset_common_data(); - set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_SUCCESS, "SUCCESS"); - TEST_EQ(mock_get_screen_info_called, 0, " no change_screen"); - - /* NO_DISK_FOUND */ - reset_common_data(); - set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "NO_DISK_FOUND"); - screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE); - - /* NO_DISK_FOUND -> INVALID_KERNEL -> SUCCESS */ - reset_common_data(); - set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "NO_DISK_FOUND"); - set_mock_vbtlk(VB2_ERROR_LK_INVALID_KERNEL_FOUND, - VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "INVALID_KERNEL"); - set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_SUCCESS, "SUCCESS"); - screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_INVALID, - MOCK_IGNORE, MOCK_IGNORE); - - /* INVALID_KERNEL */ - reset_common_data(); - set_mock_vbtlk(VB2_ERROR_LK_INVALID_KERNEL_FOUND, - VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "INVALID_KERNEL"); - screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_INVALID, - MOCK_IGNORE, MOCK_IGNORE); - - /* INVALID_KERNEL -> NO_DISK_FOUND -> SUCCESS */ - reset_common_data(); - set_mock_vbtlk(VB2_ERROR_LK_INVALID_KERNEL_FOUND, - VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "INVALID_KERNEL"); - set_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "NO_DISK_FOUND"); - set_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(manual_recovery_action(&mock_ui_context), - VB2_SUCCESS, "SUCCESS"); - screen_state_eq(mock_ui_context.state, VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE); - - VB2_DEBUG("...done.\n"); -} - -static void ui_loop_tests(void) -{ - int i; - const char *action_interfere_test_names[] = { - "hook all actions: screen action return SUCCESS", - "hook all actions: target action hooked return SUCCESS", - "hook all actions: global action return SUCCESS", - }; - - VB2_DEBUG("Testing ui_loop...\n"); - - /* Die if no root screen */ - reset_common_data(); - TEST_ABORT(ui_loop(ctx, MOCK_NO_SCREEN, NULL), - "die if no root screen"); - DISPLAYED_NO_EXTRA(); - - /* Shutdown if requested */ - reset_common_data(); - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, NULL), - VB2_REQUEST_SHUTDOWN, "shutdown if requested"); - TEST_EQ(mock_calls_until_shutdown, 0, " used up shutdown request"); - DISPLAYED_EQ("mock_screen_base", MOCK_SCREEN_BASE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Screen action */ - reset_common_data(); - mock_calls_until_shutdown = -1; - mock_action_countdown_limit = 10; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_ACTION, NULL), - VB2_SUCCESS, "screen action"); - TEST_EQ(mock_action_called, 10, " action called"); - - /* Global action */ - reset_common_data(); - mock_calls_until_shutdown = -1; - mock_action_countdown_limit = 10; - TEST_EQ(ui_loop(ctx, VB2_SCREEN_BLANK, mock_action_countdown), - VB2_SUCCESS, "global action"); - TEST_EQ(mock_action_called, 10, " action called"); - - /* Global action can change screen */ - reset_common_data(); - TEST_EQ(ui_loop(ctx, VB2_SCREEN_BLANK, mock_action_screen_change), - VB2_REQUEST_SHUTDOWN, "global action can change screen"); - DISPLAYED_PASS(); - DISPLAYED_EQ("change to mock_screen_base", MOCK_SCREEN_BASE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* - * Hook all actions, and receive SUCCESS from actions one by one - * Action #0: screen action - * Action #1: item target action - * Action #2: global action - */ - for (i = 0; i <= 2; i++) { - reset_common_data(); - add_mock_keypress(VB_KEY_ENTER); - mock_calls_until_shutdown = -1; - mock_action_flags |= (1 << i); - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_ALL_ACTION, mock_action_flag2), - VB2_SUCCESS, action_interfere_test_names[i]); - } - - /* KEY_UP, KEY_DOWN, and KEY_ENTER navigation */ - reset_common_data(); - add_mock_keypress(VB_KEY_UP); /* (blocked) */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); /* (blocked) */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_MENU, NULL), - VB2_REQUEST_SHUTDOWN, "KEY_UP, KEY_DOWN, and KEY_ENTER"); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 0, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 1, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 2, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 3, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 4, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 3, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, 2, - MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_target_2", MOCK_SCREEN_TARGET2, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* For DETACHABLE */ - if (DETACHABLE) { - reset_common_data(); - add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_DOWN_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_VOL_UP_SHORT_PRESS); - add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS); - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_MENU, NULL), - VB2_REQUEST_SHUTDOWN, "DETACHABLE"); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 0, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 1, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 2, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 3, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 4, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 3, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_menu", MOCK_SCREEN_MENU, MOCK_IGNORE, - 2, MOCK_IGNORE); - DISPLAYED_EQ("mock_screen_target_2", MOCK_SCREEN_TARGET2, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - } - - VB2_DEBUG("...done.\n"); -} - -static void ui_loop_delay_tests(void) -{ - VB2_DEBUG("Testing ui_loop delay...\n"); - - /* Sleep for 20 ms each iteration */ - reset_common_data(); - mock_calls_until_shutdown = 1; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep), - VB2_REQUEST_SHUTDOWN, " sleep for 20 ms in each iteration"); - TEST_EQ(mock_time_ms - mock_time_start_ms, KEY_DELAY_MS, - " delay 20 ms in total"); - - /* Complement to 20 ms */ - reset_common_data(); - mock_calls_until_shutdown = 1; - mock_action_delay_ms = KEY_DELAY_MS / 2; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep), - VB2_REQUEST_SHUTDOWN, " complement to 20 ms"); - TEST_EQ(mock_time_ms - mock_time_start_ms, KEY_DELAY_MS, - " delay 10 ms in total"); - - /* No extra sleep if an iteration takes longer than KEY_DELAY_MS */ - reset_common_data(); - mock_calls_until_shutdown = 1; - mock_action_delay_ms = 1234; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep), - VB2_REQUEST_SHUTDOWN, " no extra sleep time"); - TEST_EQ(mock_time_ms - mock_time_start_ms, mock_action_delay_ms, - " no extra delay"); - - /* Integer overflow */ - reset_common_data(); - mock_calls_until_shutdown = 1; - mock_time_ms = UINT32_MAX; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep), - VB2_REQUEST_SHUTDOWN, " integer overflow #1"); - TEST_EQ(mock_time_ms - UINT32_MAX, KEY_DELAY_MS, - " delay 20 ms in total"); - - reset_common_data(); - mock_calls_until_shutdown = 1; - mock_time_ms = UINT32_MAX; - mock_action_delay_ms = KEY_DELAY_MS / 2; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep), - VB2_REQUEST_SHUTDOWN, " integer overflow #2"); - TEST_EQ(mock_time_ms - UINT32_MAX, KEY_DELAY_MS, - " delay 10 ms in total"); - - reset_common_data(); - mock_calls_until_shutdown = 1; - mock_time_ms = UINT32_MAX; - mock_action_delay_ms = 1234; - TEST_EQ(ui_loop(ctx, MOCK_SCREEN_BASE, mock_action_msleep), - VB2_REQUEST_SHUTDOWN, " integer overflow #3"); - TEST_EQ(mock_time_ms - UINT32_MAX, mock_action_delay_ms, - " no extra delay"); - - VB2_DEBUG("...done.\n"); -} - -int main(void) -{ - /* Input actions */ - menu_prev_tests(); - menu_next_tests(); - menu_select_tests(); - - /* Screen actions */ - vb2_ui_developer_mode_boot_alternate_action_tests(); - - /* Global actions */ - manual_recovery_action_tests(); - - /* Core UI loop */ - ui_loop_tests(); - ui_loop_delay_tests(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_ui_tests.c vboot-utils-0~R99-14469.B/tests/vb2_ui_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_ui_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_ui_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1868 +0,0 @@ -/* Copyright 2020 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. - * - * Tests for developer and recovery mode UIs. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2struct.h" -#include "2ui.h" -#include "2ui_private.h" -#include "test_common.h" -#include "vboot_kernel.h" - -/* Fixed value for ignoring some checks */ -#define MOCK_IGNORE 0xffffu - -/* Fuzzy matches for check_time() */ -#define FUZZ_MS 200 - -/* Mock data */ -/* TODO(b/156448738): Add tests for timer_disabled and error_code */ -struct display_call { - const struct vb2_screen_info *screen; - uint32_t locale_id; - uint32_t selected_item; - uint32_t disabled_item_mask; - uint32_t hidden_item_mask; - int timer_disabled; - uint32_t current_page; - enum vb2_ui_error error_code; -} __attribute__((packed)); - -struct beep_call { - uint32_t msec; - uint32_t frequency; - uint32_t time_expected; -}; - -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static struct vb2_gbb_header gbb; - -static struct vb2_ui_context mock_ui_context; -static struct vb2_screen_state mock_state; - -static struct display_call mock_displayed[64]; -static int mock_displayed_count; -static int mock_displayed_i; - -static uint32_t mock_locale_count; - -static int mock_calls_until_shutdown; - -/* Iteration counter starts from 0 - Mock inputs should response according to this */ -static int mock_iters; - -static uint32_t mock_key[64]; -static int mock_key_trusted[64]; -static int mock_key_total; - -static uint32_t mock_time_ms; -static const uint32_t mock_time_start_ms = 31ULL * VB2_MSEC_PER_SEC; - -static struct beep_call mock_beep[8]; -static int mock_beep_count; -static int mock_beep_total; - -static enum vb2_dev_default_boot_target mock_default_boot; -static int mock_dev_boot_allowed; -static int mock_dev_boot_legacy_allowed; -static int mock_dev_boot_external_allowed; - -static int mock_vbexlegacy_called; -static enum VbAltFwIndex_t mock_altfw_num_last; -static uint32_t mock_bootloader_count; - -static vb2_error_t mock_vbtlk_retval[32]; -static uint32_t mock_vbtlk_expected_flag[32]; -static int mock_vbtlk_total; - -static int mock_allow_recovery; - -/* mock_pp_* = mock data for physical presence button */ -static int mock_pp_pressed[64]; -static int mock_pp_pressed_total; - -static int mock_enable_dev_mode; - -#define MOCK_PREPARE_LOG_SIZE 32 - -static int mock_snapshot_count; -static char mock_prepare_log[64][MOCK_PREPARE_LOG_SIZE]; -static int mock_prepare_log_count; -static uint32_t mock_log_page_count; - -static void add_mock_key(uint32_t press, int trusted) -{ - if (mock_key_total >= ARRAY_SIZE(mock_key) || - mock_key_total >= ARRAY_SIZE(mock_key_trusted)) { - TEST_TRUE(0, " mock_key ran out of entries!"); - return; - } - - mock_key[mock_key_total] = press; - mock_key_trusted[mock_key_total] = trusted; - mock_key_total++; -} - -static void add_mock_keypress(uint32_t press) -{ - add_mock_key(press, 0); -} - -static void add_mock_vbtlk(vb2_error_t retval, uint32_t get_info_flags) -{ - if (mock_vbtlk_total >= ARRAY_SIZE(mock_vbtlk_retval) || - mock_vbtlk_total >= ARRAY_SIZE(mock_vbtlk_expected_flag)) { - TEST_TRUE(0, " mock_vbtlk ran out of entries!"); - return; - } - - mock_vbtlk_retval[mock_vbtlk_total] = retval; - mock_vbtlk_expected_flag[mock_vbtlk_total] = get_info_flags; - mock_vbtlk_total++; -} - -static void add_mock_pp_pressed(int pressed) -{ - if (mock_pp_pressed_total >= ARRAY_SIZE(mock_pp_pressed)) { - TEST_TRUE(0, " mock_pp ran out of entries!"); - return; - } - - mock_pp_pressed[mock_pp_pressed_total++] = pressed; -} - -static void extend_calls_until_shutdown(void) -{ - if (mock_calls_until_shutdown < mock_key_total) - mock_calls_until_shutdown = mock_key_total; - if (mock_calls_until_shutdown < mock_vbtlk_total) - mock_calls_until_shutdown = mock_vbtlk_total; - if (mock_calls_until_shutdown < mock_pp_pressed_total) - mock_calls_until_shutdown = mock_pp_pressed_total; - mock_calls_until_shutdown++; -} - -static void displayed_eq(const char *text, - enum vb2_screen screen, - uint32_t locale_id, - uint32_t selected_item, - uint32_t disabled_item_mask, - uint32_t hidden_item_mask, - uint32_t current_page, - int line) -{ - char text_info[32], text_buf[128]; - - sprintf(text_info, "(line #%d, displayed #%d)", line, mock_displayed_i); - - if (mock_displayed_i >= mock_displayed_count) { - sprintf(text_buf, " %s missing screen %s", - text_info, text); - TEST_TRUE(0, text_buf); - return; - } - - if (screen != MOCK_IGNORE) { - sprintf(text_buf, " %s screen of %s", text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].screen->id, screen, - text_buf); - } - if (locale_id != MOCK_IGNORE) { - sprintf(text_buf, " %s locale_id of %s", text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].locale_id, locale_id, - text_buf); - } - if (selected_item != MOCK_IGNORE) { - sprintf(text_buf, " %s selected_item of %s", - text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].selected_item, - selected_item, text_buf); - } - if (disabled_item_mask != MOCK_IGNORE) { - sprintf(text_buf, " %s disabled_item_mask of %s", - text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].disabled_item_mask, - disabled_item_mask, text_buf); - } - if (hidden_item_mask != MOCK_IGNORE) { - sprintf(text_buf, " %s hidden_item_mask of %s", - text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].hidden_item_mask, - hidden_item_mask, text_buf); - } - if (current_page != MOCK_IGNORE) { - sprintf(text_buf, " %s current_page of %s", - text_info, text); - TEST_EQ(mock_displayed[mock_displayed_i].current_page, - current_page, text_buf); - } - mock_displayed_i++; -} - -static void displayed_no_extra(int line) -{ - char text_info[32], text_buf[128]; - - sprintf(text_info, "(line #%d)", line); - - if (mock_displayed_i == 0) - sprintf(text_buf, " %s no screen", text_info); - else - sprintf(text_buf, " %s no extra screens", text_info); - TEST_EQ(mock_displayed_count, mock_displayed_i, text_buf); -} - -#define DISPLAYED_EQ(...) displayed_eq(__VA_ARGS__, __LINE__) - -#define DISPLAYED_PASS() \ - displayed_eq("", MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, \ - MOCK_IGNORE, MOCK_IGNORE, __LINE__) - -#define DISPLAYED_NO_EXTRA() displayed_no_extra(__LINE__) - -static void expect_beep(uint32_t msec, - uint32_t frequency, - uint32_t time_expected) -{ - if (mock_beep_total >= ARRAY_SIZE(mock_beep)) { - TEST_TRUE(0, " mock_beep ran out of entries!"); - return; - } - - mock_beep[mock_beep_total++] = (struct beep_call){ - .msec = msec, - .frequency = frequency, - .time_expected = time_expected, - }; -} - -/* Check if the result time falls in range [expected, expected + FUZZ_MS) */ -static void check_time(uint32_t result, uint32_t expected, const char *desc) -{ - TEST_TRUE(result >= expected, desc); - TEST_TRUE(result - expected < FUZZ_MS, " within FUZZ_MS"); -} - -/* Type of test to reset for */ -enum reset_type { - FOR_DEVELOPER, - FOR_BROKEN_RECOVERY, - FOR_MANUAL_RECOVERY, - FOR_DIAGNOSTICS, -}; - -/* Reset mock data (for use before each test) */ -static void reset_common_data(enum reset_type t) -{ - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - - memset(&gbb, 0, sizeof(gbb)); - - vb2_nv_init(ctx); - - sd = vb2_get_sd(ctx); - sd->status |= VB2_SD_STATUS_SECDATA_KERNEL_INIT; - - if (t == FOR_DEVELOPER) { - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - } - - /* Mock ui_context based on real screens */ - memset(&mock_ui_context, 0, sizeof(mock_ui_context)); - mock_ui_context.ctx = ctx; - mock_ui_context.state = &mock_state; - - /* For vb2ex_display_ui */ - memset(mock_displayed, 0, sizeof(mock_displayed)); - mock_displayed_count = 0; - mock_displayed_i = 0; - - /* For vb2ex_get_locale_count */ - mock_locale_count = 1; - - /* For check_shutdown_request */ - if (t == FOR_DEVELOPER) - mock_calls_until_shutdown = 2000; /* Larger than 30s */ - else - mock_calls_until_shutdown = 10; - - /* For iteration counter */ - mock_iters = -1; /* Accumulates at the beginning of iterations */ - - /* For VbExKeyboardRead */ - memset(mock_key, 0, sizeof(mock_key)); - memset(mock_key_trusted, 0, sizeof(mock_key_trusted)); - mock_key_total = 0; - - /* For vb2ex_mtime and vb2ex_msleep */ - mock_time_ms = mock_time_start_ms; - - /* For vb2ex_beep */ - memset(mock_beep, 0, sizeof(mock_beep)); - mock_beep_count = 0; - mock_beep_total = 0; - - /* For dev_boot* in 2misc.h */ - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL; - mock_dev_boot_allowed = 1; - mock_dev_boot_legacy_allowed = 0; - mock_dev_boot_external_allowed = 1; - - /* For VbExLegacy */ - mock_vbexlegacy_called = 0; - mock_altfw_num_last = -100; - mock_bootloader_count = 2; - - /* For VbTryLoadKernel */ - memset(mock_vbtlk_retval, 0, sizeof(mock_vbtlk_retval)); - memset(mock_vbtlk_expected_flag, 0, sizeof(mock_vbtlk_expected_flag)); - mock_vbtlk_total = 0; - - /* For vb2_allow_recovery */ - mock_allow_recovery = t == FOR_MANUAL_RECOVERY; - - /* For vb2ex_physical_presence_pressed */ - memset(mock_pp_pressed, 0, sizeof(mock_pp_pressed)); - mock_pp_pressed_total = 0; - - /* For vb2_enable_developer_mode */ - mock_enable_dev_mode = 0; - - /* For vb2ex_prepare_log_screen */ - mock_snapshot_count = 0; - mock_prepare_log_count = 0; - mock_log_page_count = 1; - - /* Avoid Iteration #0 */ - add_mock_keypress(0); - if (t == FOR_MANUAL_RECOVERY) - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, - VB_DISK_FLAG_REMOVABLE); - else - add_mock_vbtlk(VB2_ERROR_MOCK, 0); - add_mock_pp_pressed(0); -} - -/* Mock functions */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -vb2_error_t vb2ex_display_ui(enum vb2_screen screen, - uint32_t locale_id, - uint32_t selected_item, - uint32_t disabled_item_mask, - uint32_t hidden_item_mask, - int timer_disabled, - uint32_t current_page, - enum vb2_ui_error error_code) -{ - struct display_call displayed = (struct display_call){ - .screen = vb2_get_screen_info(screen), - .locale_id = locale_id, - .selected_item = selected_item, - .disabled_item_mask = disabled_item_mask, - .hidden_item_mask = hidden_item_mask, - .timer_disabled = timer_disabled, - .current_page = current_page, - .error_code = error_code, - }; - - /* Ignore repeated calls with same arguments */ - if (mock_displayed_count > 0 && - !memcmp(&mock_displayed[mock_displayed_count - 1], &displayed, - sizeof(struct display_call))) - return VB2_SUCCESS; - - VB2_DEBUG("displayed %d: screen=%#x, locale_id=%u, selected_item=%u, " - "disabled_item_mask=%#x, hidden_item_mask=%#x, " - "timer_disabled=%d, current_page=%u, error=%#x\n", - mock_displayed_count, screen, locale_id, selected_item, - disabled_item_mask, hidden_item_mask, - timer_disabled, current_page, error_code); - - if (mock_displayed_count >= ARRAY_SIZE(mock_displayed)) { - TEST_TRUE(0, " mock vb2ex_display_ui ran out of entries!"); - return VB2_ERROR_MOCK; - } - - mock_displayed[mock_displayed_count++] = displayed; - - return VB2_SUCCESS; -} - -uint32_t vb2ex_get_locale_count(void) -{ - return mock_locale_count; -} - -uint32_t VbExIsShutdownRequested(void) -{ - if (mock_calls_until_shutdown < 0) /* Never request shutdown */ - return 0; - if (mock_calls_until_shutdown == 0) - return 1; - mock_calls_until_shutdown--; - - return 0; -} - -uint32_t VbExKeyboardRead(void) -{ - return VbExKeyboardReadWithFlags(NULL); -} - -uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags) -{ - mock_iters++; - if (mock_iters < mock_key_total) { - if (key_flags != NULL) { - if (mock_key_trusted[mock_iters]) - *key_flags = VB_KEY_FLAG_TRUSTED_KEYBOARD; - else - *key_flags = 0; - } - return mock_key[mock_iters]; - } - - return 0; -} - -uint32_t vb2ex_mtime(void) -{ - return mock_time_ms; -} - -void vb2ex_msleep(uint32_t msec) -{ - mock_time_ms += msec; -} - -void vb2ex_beep(uint32_t msec, uint32_t frequency) -{ - struct beep_call *beep; - uint32_t cur_time = mock_time_ms - mock_time_start_ms; - - VB2_DEBUG("beep %d: msec = %d, frequency = %d at %d msec\n", - mock_beep_count, msec, frequency, cur_time); - - if (mock_beep_total > 0) { - TEST_TRUE(mock_beep_count < mock_beep_total, - " too many beep calls!"); - - beep = &mock_beep[mock_beep_count]; - - VB2_DEBUG("beep expected: msec = %d, frequency = %d, " - "at %d msec\n", - beep->msec, beep->frequency, beep->time_expected); - - TEST_EQ(msec, beep->msec, " beep duration"); - TEST_EQ(frequency, beep->frequency, " beep frequency"); - check_time(cur_time, beep->time_expected, - " beep started after expected time"); - } - - mock_time_ms += msec; - mock_beep_count++; -} - -enum vb2_dev_default_boot_target vb2api_get_dev_default_boot_target( - struct vb2_context *c) -{ - return mock_default_boot; -} - -int vb2_dev_boot_allowed(struct vb2_context *c) -{ - return mock_dev_boot_allowed; -} - -int vb2_dev_boot_legacy_allowed(struct vb2_context *c) -{ - return mock_dev_boot_legacy_allowed; -} - -int vb2_dev_boot_external_allowed(struct vb2_context *c) -{ - return mock_dev_boot_external_allowed; -} - -vb2_error_t VbExLegacy(enum VbAltFwIndex_t altfw_num) -{ - mock_vbexlegacy_called++; - mock_altfw_num_last = altfw_num; - - return VB2_SUCCESS; -} - -uint32_t vb2ex_get_bootloader_count(void) -{ - return mock_bootloader_count; -} - -vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags) -{ - int i = mock_iters; - - /* Return last entry if called too many times */ - if (i >= mock_vbtlk_total) - i = mock_vbtlk_total - 1; - - TEST_EQ(mock_vbtlk_expected_flag[i], get_info_flags, - " unexpected get_info_flags"); - - return mock_vbtlk_retval[i]; -} - -int vb2_allow_recovery(struct vb2_context *c) -{ - return mock_allow_recovery; -} - -int vb2ex_physical_presence_pressed(void) -{ - if (mock_iters >= mock_pp_pressed_total) - return 0; - - return mock_pp_pressed[mock_iters]; -} - -void vb2_enable_developer_mode(struct vb2_context *c) -{ - mock_enable_dev_mode = 1; -} - -const char *vb2ex_get_debug_info(struct vb2_context *c) -{ - return "mocked debug info"; -} - -const char *vb2ex_get_firmware_log(int reset) -{ - static char mock_firmware_log_buf[MOCK_PREPARE_LOG_SIZE]; - if (reset) - mock_snapshot_count++; - snprintf(mock_firmware_log_buf, MOCK_PREPARE_LOG_SIZE, - "%d", mock_snapshot_count); - return mock_firmware_log_buf; -} - -uint32_t vb2ex_prepare_log_screen(const char *str) -{ - if (mock_prepare_log_count < ARRAY_SIZE(mock_prepare_log)) - strncpy(mock_prepare_log[mock_prepare_log_count], - str, MOCK_PREPARE_LOG_SIZE); - mock_prepare_log_count++; - - return mock_log_page_count; -} - -/* Tests */ -static void developer_tests(void) -{ - VB2_DEBUG("Testing developer mode...\n"); - - /* Power button short pressed = shutdown request */ - if (!DETACHABLE) { - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS); - mock_calls_until_shutdown = -1; - TEST_EQ(vb2_developer_menu(ctx), - VB2_REQUEST_SHUTDOWN, - "power button short pressed = shutdown"); - } - - /* Proceed to internal disk after timeout */ - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - expect_beep(250, 400, DEV_DELAY_BEEP1_MS); - expect_beep(250, 400, DEV_DELAY_BEEP2_MS); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "proceed to internal disk after timeout"); - check_time(mock_time_ms - mock_time_start_ms, DEV_DELAY_NORMAL_MS, - " finished delay"); - TEST_EQ(mock_beep_count, 2, " beeped twice"); - TEST_TRUE(mock_iters >= mock_vbtlk_total, " used up mock_vbtlk"); - - /* Use short delay */ - reset_common_data(FOR_DEVELOPER); - gbb.flags |= VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY; - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "use short delay"); - check_time(mock_time_ms - mock_time_start_ms, DEV_DELAY_SHORT_MS, - " finished delay"); - TEST_EQ(mock_beep_count, 0, " never beeped"); - - /* Stop timer on any user input: normal delay */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress('A'); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "stop timer on any user input: normal delay"); - TEST_TRUE(mock_time_ms - mock_time_start_ms > DEV_DELAY_NORMAL_MS, - " delay aborted"); - TEST_EQ(mock_calls_until_shutdown, 0, " loop forever"); - TEST_EQ(mock_beep_count, 0, " never beeped"); - - /* Stop timer on any user input: short delay */ - reset_common_data(FOR_DEVELOPER); - gbb.flags |= VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY; - add_mock_keypress('A'); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "stop timer on any user input: short delay"); - TEST_TRUE(mock_time_ms - mock_time_start_ms > DEV_DELAY_SHORT_MS, - " delay aborted"); - TEST_EQ(mock_calls_until_shutdown, 0, " loop forever"); - TEST_EQ(mock_beep_count, 0, " never beeped"); - - /* If fail to load internal disk, don't boot */ - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_ERROR_LK_NO_DISK_FOUND, - "if fail to load internal disk, don't boot"); - - /* Select boot internal in dev menu */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_ENTER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "select boot internal in dev menu"); - - /* Ctrl+U = boot external */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_CTRL('U')); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "ctrl+u = boot external"); - - /* Ctrl+D = boot internal */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_CTRL('D')); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "ctrl+d = boot internal"); - - /* VB_BUTTON_VOL_DOWN_LONG_PRESS = boot internal */ - if (DETACHABLE) { - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_BUTTON_VOL_DOWN_LONG_PRESS); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "VB_BUTTON_VOL_DOWN_LONG_PRESS = boot internal"); - } - - /* Proceed to external disk after timeout */ - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; - expect_beep(250, 400, DEV_DELAY_BEEP1_MS); - expect_beep(250, 400, DEV_DELAY_BEEP2_MS); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "proceed to external disk after timeout"); - check_time(mock_time_ms - mock_time_start_ms, DEV_DELAY_NORMAL_MS, - " finished delay"); - TEST_EQ(mock_beep_count, 2, " beeped twice"); - TEST_TRUE(mock_iters >= mock_vbtlk_total, " used up mock_vbtlk"); - - /* Default boot from external not allowed, don't boot */ - reset_common_data(FOR_DEVELOPER); - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; - mock_dev_boot_external_allowed = 0; - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "default boot from external disk not allowed, don't boot"); - - /* If no external disk, don't boot */ - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "if no external disk, don't boot"); - - /* Select boot external in dev menu */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_ENTER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "select boot external in dev menu"); - - /* Ctrl+L = boot legacy (allowed) */ - reset_common_data(FOR_DEVELOPER); - mock_dev_boot_legacy_allowed = 1; - add_mock_keypress(VB_KEY_CTRL('L')); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "ctrl+l = boot legacy"); - TEST_EQ(mock_vbexlegacy_called, 1, " VbExLegacy called"); - - /* Ctrl+L = boot legacy (disallowed) */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_CTRL('L')); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "ctrl+l = boot legacy"); - TEST_EQ(mock_vbexlegacy_called, 0, " VbExLegacy not called"); - - /* VB_BUTTON_VOL_UP_LONG_PRESS = boot external */ - if (DETACHABLE) { - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_BUTTON_VOL_UP_LONG_PRESS); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "VB_BUTTON_VOL_UP_LONG_PRESS = boot external"); - } - - /* If dev mode is disabled, goes to to_norm screen repeatedly */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_ESC); - mock_dev_boot_allowed = 0; - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "if dev mode is disabled, goes to to_norm screen repeatedly"); - DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_PASS(); - DISPLAYED_EQ("to_norm", VB2_SCREEN_DEVELOPER_TO_NORM, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Select to_norm in dev menu and confirm */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_REBOOT, - "select to_norm in dev menu and confirm"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - - /* Select to_norm in dev menu and cancel */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "select to_norm in dev menu and cancel"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 0, - " disable dev request"); - - /* Ctrl+S = to_norm */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_CTRL('S')); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_REBOOT, - "ctrl+s = to_norm"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - - /* Dev mode forced by GBB flag */ - reset_common_data(FOR_DEVELOPER); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON; - add_mock_keypress(VB_KEY_CTRL('S')); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "dev mode forced by GBB flag"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 0, - " disable dev request"); - - /* Power off */ - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - /* Navigate to the bottom most menu item */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "select power off"); - - VB2_DEBUG("...done.\n"); -} - -static void broken_recovery_tests(void) -{ - VB2_DEBUG("Testing broken recovery mode...\n"); - - /* Power button short pressed = shutdown request */ - if (!DETACHABLE) { - reset_common_data(FOR_BROKEN_RECOVERY); - add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS); - mock_calls_until_shutdown = -1; - TEST_EQ(vb2_broken_recovery_menu(ctx), - VB2_REQUEST_SHUTDOWN, - "power button short pressed = shutdown"); - } - - /* Shortcuts that are always ignored in BROKEN */ - reset_common_data(FOR_BROKEN_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_key(VB_KEY_CTRL('U'), 1); - add_mock_key(VB_KEY_CTRL('L'), 1); - add_mock_key(VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS, 1); - add_mock_key(VB_BUTTON_VOL_UP_LONG_PRESS, 1); - add_mock_key(VB_BUTTON_VOL_DOWN_LONG_PRESS, 1); - TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "Shortcuts ignored in BROKEN"); - TEST_EQ(mock_calls_until_shutdown, 0, " loop forever"); - TEST_EQ(mock_displayed_count, 1, " root screen only"); - - VB2_DEBUG("...done.\n"); -} - -static void manual_recovery_tests(void) -{ - VB2_DEBUG("Testing manual recovery mode...\n"); - - /* Timeout, shutdown */ - reset_common_data(FOR_MANUAL_RECOVERY); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "timeout, shutdown"); - TEST_EQ(mock_displayed_count, 1, " root screen only"); - - /* Power button short pressed = shutdown request */ - if (!DETACHABLE) { - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress(VB_BUTTON_POWER_SHORT_PRESS); - TEST_EQ(vb2_manual_recovery_menu(ctx), - VB2_REQUEST_SHUTDOWN, - "power button short pressed = shutdown"); - } - - /* Boots if we have a valid image on first try */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS, - "boots if valid on first try"); - - /* Boots eventually if we get a valid image later */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS, - "boots after valid image appears"); - - /* Invalid image, then remove, then valid image */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - add_mock_vbtlk(VB2_ERROR_MOCK, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_SUCCESS, - "boots after valid image appears"); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_EQ("recovery invalid", VB2_SCREEN_RECOVERY_INVALID, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Ctrl+D = to_dev; space = cancel */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_keypress(' '); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "ctrl+d = to_dev; space = cancel"); - TEST_EQ(mock_enable_dev_mode, 0, " dev mode not enabled"); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Cancel to_dev transition */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - if (PHYSICAL_PRESENCE_KEYBOARD) - add_mock_key(VB_KEY_DOWN, 1); - add_mock_key(VB_KEY_ENTER, 1); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "cancel to_dev transition"); - TEST_EQ(mock_enable_dev_mode, 0, " dev mode not enabled"); - - /* Confirm to_dev transition */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - if (PHYSICAL_PRESENCE_KEYBOARD) { - add_mock_key(VB_KEY_ENTER, 1); - } else { - add_mock_pp_pressed(0); - add_mock_pp_pressed(1); - add_mock_pp_pressed(1); - add_mock_pp_pressed(0); - } - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_REBOOT_EC_TO_RO, - "confirm to_dev transition"); - if (!PHYSICAL_PRESENCE_KEYBOARD) - TEST_TRUE(mock_iters >= mock_pp_pressed_total - 1, - " used up mock_pp_pressed"); - TEST_EQ(mock_enable_dev_mode, 1, " dev mode enabled"); - - /* Cannot confirm physical presence by untrusted keyboard */ - if (PHYSICAL_PRESENCE_KEYBOARD) { - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_key(VB_KEY_ENTER, 0); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "cannot confirm physical presence" - " by untrusted keyboard"); - TEST_EQ(mock_enable_dev_mode, 0, " dev mode not enabled"); - } - - /* Cannot enable dev mode if already enabled */ - reset_common_data(FOR_MANUAL_RECOVERY); - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - add_mock_key(VB_KEY_CTRL('D'), 1); - if (PHYSICAL_PRESENCE_KEYBOARD) { - add_mock_key(VB_KEY_ENTER, 1); - } else { - add_mock_pp_pressed(0); - add_mock_pp_pressed(1); - add_mock_pp_pressed(0); - } - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "cannot enable dev mode if already enabled"); - TEST_EQ(mock_enable_dev_mode, 0, " dev mode already on"); - - /* Physical presence button tests */ - if (!PHYSICAL_PRESENCE_KEYBOARD) { - /* Physical presence button stuck? */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_pp_pressed(1); /* Hold since boot */ - add_mock_pp_pressed(0); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "physical presence button stuck?"); - TEST_EQ(mock_enable_dev_mode, 0, " dev mode not enabled"); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Button stuck, enter to_dev again */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_pp_pressed(1); /* Hold since boot */ - add_mock_pp_pressed(0); - add_mock_pp_pressed(1); /* Press again */ - add_mock_pp_pressed(0); - TEST_EQ(vb2_manual_recovery_menu(ctx), - VB2_REQUEST_REBOOT_EC_TO_RO, - "button stuck, enter to_dev again"); - TEST_TRUE(mock_iters >= mock_pp_pressed_total - 1, - " used up mock_pp_pressed"); - TEST_EQ(mock_enable_dev_mode, 1, " dev mode enabled"); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Cancel with holding pp button, enter again */ - reset_common_data(FOR_MANUAL_RECOVERY); - /* Enter to_dev */ - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_pp_pressed(0); - /* Press pp button */ - add_mock_keypress(0); - add_mock_pp_pressed(1); - /* Space = back */ - add_mock_keypress(' '); - add_mock_pp_pressed(1); - /* Wait */ - add_mock_keypress(0); - add_mock_pp_pressed(0); - /* Enter to_dev again */ - add_mock_key(VB_KEY_CTRL('D'), 1); - add_mock_pp_pressed(0); - /* Press pp button again */ - add_mock_pp_pressed(1); - /* Release */ - add_mock_pp_pressed(0); - TEST_EQ(vb2_manual_recovery_menu(ctx), - VB2_REQUEST_REBOOT_EC_TO_RO, - "cancel with holding pp button, enter again"); - TEST_TRUE(mock_iters >= mock_pp_pressed_total - 1, - " used up mock_pp_pressed"); - TEST_EQ(mock_enable_dev_mode, 1, " dev mode enabled"); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("to_dev", VB2_SCREEN_RECOVERY_TO_DEV, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - } - - /* Enter diagnostics */ - if (DIAGNOSTIC_UI) { - /* Launch diagnostics is inside manual recovery */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_manual_recovery_menu(ctx), - VB2_REQUEST_REBOOT, - "Reboot immediately after request diagnostics"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 1, - "VB2_NV_DIAG_REQUEST is set"); - } - - VB2_DEBUG("...done.\n"); -} - -static void language_selection_tests(void) -{ - VB2_DEBUG("Testing language selection...\n"); - - /* Enter language menu and change language */ - reset_common_data(FOR_MANUAL_RECOVERY); - mock_locale_count = 100; - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, 23); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); /* select language */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); /* select locale 24 */ - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "change language"); - DISPLAYED_EQ("RECOVERY_SELECT default", VB2_SCREEN_RECOVERY_SELECT, - 23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("RECOVERY_SELECT lang", VB2_SCREEN_RECOVERY_SELECT, - 23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("LANGUAGE_SELECT 23", VB2_SCREEN_LANGUAGE_SELECT, - 23, 23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("LANGUAGE_SELECT 24", VB2_SCREEN_LANGUAGE_SELECT, - 23, 24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("RECOVERY_SELECT new locale", VB2_SCREEN_RECOVERY_SELECT, - 24, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 24, - " locale 24 saved to nvdata"); - - /* Locale count = 0 */ - reset_common_data(FOR_MANUAL_RECOVERY); - mock_locale_count = 0; - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, 23); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); /* select language */ - add_mock_keypress(VB_KEY_ENTER); /* select locale 0 */ - add_mock_vbtlk(VB2_ERROR_LK_NO_DISK_FOUND, VB_DISK_FLAG_REMOVABLE); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "enter language menu"); - DISPLAYED_EQ("RECOVERY_SELECT default", VB2_SCREEN_RECOVERY_SELECT, - 23, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("RECOVERY_SELECT lang", VB2_SCREEN_RECOVERY_SELECT, - 23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("LANGUAGE_SELECT index 0", VB2_SCREEN_LANGUAGE_SELECT, - 23, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("RECOVERY_SELECT locale 0", VB2_SCREEN_RECOVERY_SELECT, - 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - VB2_DEBUG("...done.\n"); -} - -static void debug_info_tests(void) -{ - VB2_DEBUG("Testing debug info screen...\n"); - - /* Tab = debug info for all menus */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress('\t'); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "tab = debug info in dev mode"); - DISPLAYED_PASS(); - DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - reset_common_data(FOR_BROKEN_RECOVERY); - add_mock_keypress('\t'); - TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "tab = debug info in broken recovery mode"); - DISPLAYED_PASS(); - DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress('\t'); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "tab = debug info in manual recovery mode"); - DISPLAYED_PASS(); - DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Failed to enter debug info */ - reset_common_data(FOR_MANUAL_RECOVERY); - mock_log_page_count = 0; - add_mock_keypress('\t'); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "failed to enter debug info"); - DISPLAYED_PASS(); - DISPLAYED_PASS(); /* error code */ - DISPLAYED_NO_EXTRA(); - - /* Get a one-page debug info */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress('\t'); - add_mock_keypress(VB_KEY_ENTER); /* back */ - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "get a one-page debug info"); - DISPLAYED_PASS(); - DISPLAYED_EQ("debug info", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 3, 0x6, 0x0, 0); - DISPLAYED_EQ("back to root screen", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Get a three-page debug info and navigate */ - reset_common_data(FOR_MANUAL_RECOVERY); - mock_log_page_count = 3; - add_mock_keypress('\t'); - add_mock_keypress(VB_KEY_ENTER); /* page 0, select on page down */ - add_mock_keypress(VB_KEY_ENTER); /* page 1, select on page down */ - add_mock_keypress(VB_KEY_UP); /* page 2, select on page down */ - add_mock_keypress(VB_KEY_ENTER); /* page 2, select on page up */ - add_mock_keypress(VB_KEY_ENTER); /* page 1, select on page up */ - add_mock_keypress(VB_KEY_DOWN); /* page 0, select on page up */ - add_mock_keypress(VB_KEY_ENTER); /* page 0, select on page down */ - add_mock_keypress(VB_KEY_DOWN); /* page 1, select on page down */ - add_mock_keypress(VB_KEY_ENTER); /* page 1, select on back */ - extend_calls_until_shutdown(); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "get a three-page debug info and navigate"); - DISPLAYED_PASS(); - DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 2, 0x2, 0x0, 0); - DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 2, 0x0, 0x0, 1); - DISPLAYED_EQ("debug info page #2", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 2, 0x4, 0x0, 2); - DISPLAYED_EQ("debug info page #2", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 1, 0x4, 0x0, 2); - DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 1, 0x0, 0x0, 1); - DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 1, 0x2, 0x0, 0); - DISPLAYED_EQ("debug info page #0", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 2, 0x2, 0x0, 0); - DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 2, 0x0, 0x0, 1); - DISPLAYED_EQ("debug info page #1", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, 3, 0x0, 0x0, 1); - DISPLAYED_EQ("back to root screen", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - VB2_DEBUG("...done.\n"); -} - -static void firmware_log_tests(void) -{ - VB2_DEBUG("Testing firmware log screens...\n"); - - /* Get firmware log */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - if (DIAGNOSTIC_UI) - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "get firmware log"); - TEST_EQ(mock_prepare_log_count, 1, - " prepared firmware log once"); - TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0, - " got correct firmware log"); - - /* Enter firmware log screen again will reacquire a newer one */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - if (DIAGNOSTIC_UI) - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "enter the screen again and reacquire a new log"); - TEST_EQ(mock_prepare_log_count, 2, - " prepared firmware log twice"); - TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0, - " got correct firmware log"); - TEST_EQ(strcmp(mock_prepare_log[1], "2"), 0, - " got a new firmware log"); - - /* Back to firmware log screen again will not reacquire a newer one */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - if (DIAGNOSTIC_UI) - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress('\t'); /* enter debug info screen */ - add_mock_keypress(VB_KEY_ESC); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "back to the screen and do not reacquire a new log"); - TEST_EQ(mock_prepare_log_count, 3, - " prepared firmware log three times"); - TEST_EQ(strcmp(mock_prepare_log[0], "1"), 0, - " got correct firmware log"); - /* Skip entry #1 which is for preparing debug info */ - TEST_EQ(strcmp(mock_prepare_log[2], "1"), 0, - " got the same firmware log"); - - VB2_DEBUG("...done.\n"); -} - -static void developer_screen_tests(void) -{ - VB2_DEBUG("Testing developer mode screens...\n"); - - /* Dev mode: default selected item */ - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen: set default selection to boot internal"); - DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen: set default selection to boot external"); - DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - - /* Dev mode: disabled and hidden item mask */ - reset_common_data(FOR_DEVELOPER); - mock_dev_boot_legacy_allowed = 1; - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen: no disabled or hidden item"); - DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE); - - reset_common_data(FOR_DEVELOPER); - mock_dev_boot_legacy_allowed = 1; - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON; - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen: hide to_norm item"); - DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE); - - reset_common_data(FOR_DEVELOPER); - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - mock_dev_boot_external_allowed = 0; - mock_dev_boot_legacy_allowed = 1; - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen: hide boot external"); - DISPLAYED_EQ("dev mode screen", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x8, MOCK_IGNORE); - - /* Dev mode screen */ - reset_common_data(FOR_DEVELOPER); /* Select #2 by default */ - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - /* #0: Language menu */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: Return to secure mode */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #2: Boot internal */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen"); - /* #0: Language menu */ - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: Return to secure mode */ - DISPLAYED_PASS(); - DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#1: return to secure mode", VB2_SCREEN_DEVELOPER_TO_NORM, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #2: Boot internal */ - DISPLAYED_PASS(); - DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - VB2_DEBUG("#2: boot internal (no extra screen)\n"); - DISPLAYED_NO_EXTRA(); - - reset_common_data(FOR_DEVELOPER); /* Select #3 by default */ - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_REMOVABLE); - mock_default_boot = VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL; - /* #3: Boot external */ - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_SUCCESS, - "dev mode screen"); - /* #3: Boot external */ - DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - VB2_DEBUG("#3: boot external (no extra screen)\n"); - DISPLAYED_NO_EXTRA(); - - reset_common_data(FOR_DEVELOPER); /* Select #2 by default */ - mock_dev_boot_legacy_allowed = 1; - /* #4: Alternate boot */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "dev mode screen"); - TEST_EQ(mock_vbexlegacy_called, 1, " VbExLegacy called"); - - reset_common_data(FOR_DEVELOPER); /* Select #2 by default */ - add_mock_vbtlk(VB2_SUCCESS, VB_DISK_FLAG_FIXED); - /* #5: Advanced options */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* End of menu */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); /* Blocked */ - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "dev mode screen"); - /* #5: Advanced options */ - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_EQ("dev mode", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#4: advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* End of menu */ - DISPLAYED_PASS(); - DISPLAYED_EQ("end of menu", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, 6, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Advanced options screen: disabled and hidden item mask */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "advanced options screen: hide to_dev"); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE); - - /* Advanced options screen */ - reset_common_data(FOR_DEVELOPER); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #0: Language menu */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: (Hidden) */ - /* #2: Debug info */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #3: Firmware log */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #4: Back */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* End of menu */ - add_mock_keypress(VB_KEY_ENTER); - extend_calls_until_shutdown(); - TEST_EQ(vb2_developer_menu(ctx), VB2_REQUEST_SHUTDOWN, - "advanced options screen"); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - /* #0: Language menu */ - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: (Hidden) */ - /* #2: Debug info */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #3: Firmware log */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #4: Back */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#4: back", VB2_SCREEN_DEVELOPER_MODE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* End of menu */ - DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - VB2_DEBUG("...done.\n"); -} - -static void broken_recovery_screen_tests(void) -{ - /* Broken screen: disabled and hidden item mask */ - reset_common_data(FOR_BROKEN_RECOVERY); - TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "broken screen: no disabled and hidden item mask"); - DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE); - - /* Broken screen */ - reset_common_data(FOR_BROKEN_RECOVERY); - /* #0: Language menu */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: Advanced options */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* End of menu */ - add_mock_keypress(VB_KEY_ESC); - extend_calls_until_shutdown(); - TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "broken screen"); - /* #0: Language menu */ - DISPLAYED_PASS(); - DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN, - MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: Advanced options */ - DISPLAYED_PASS(); - DISPLAYED_EQ("broken screen", VB2_SCREEN_RECOVERY_BROKEN, - MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#1: advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* End of menu */ - DISPLAYED_EQ("end of menu", VB2_SCREEN_RECOVERY_BROKEN, - MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Advanced options screen: disabled and hidden item mask */ - reset_common_data(FOR_BROKEN_RECOVERY); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "advanced options screen: hide to_dev item"); - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x2, MOCK_IGNORE); - - /* Advanced options screen */ - reset_common_data(FOR_BROKEN_RECOVERY); - add_mock_keypress(VB_KEY_ENTER); - /* #0: Language menu */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: (Hidden) */ - /* #2: Debug info */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #3: Firmware log */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #4: Back */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* End of menu */ - add_mock_keypress(VB_KEY_ENTER); - extend_calls_until_shutdown(); - TEST_EQ(vb2_broken_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "advanced options screen"); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - /* #0: Language menu */ - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: (Hidden) */ - /* #2: Debug info */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #3: Firmware log */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #4: Back */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#4: back", VB2_SCREEN_RECOVERY_BROKEN, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* End of menu */ - DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - VB2_DEBUG("...done.\n"); -} - -static void manual_recovery_screen_tests(void) -{ - /* Recovery select screen: disabled and hidden item mask */ - reset_common_data(FOR_MANUAL_RECOVERY); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - DIAGNOSTIC_UI ? - "recovery select screen: no disabled or hidden item" : - "recovery select screen: hide `launch diag`"); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, 0x0, DIAGNOSTIC_UI ? 0x0 : 0x8, - MOCK_IGNORE); - - /* Recovery select screen */ - reset_common_data(FOR_MANUAL_RECOVERY); - /* #0: Language menu */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: Phone recovery */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #2: External disk recovery */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_ESC); - /* #3: Launch diagnostics */ - if (DIAGNOSTIC_UI) - add_mock_keypress(VB_KEY_DOWN); - /* #4: Advanced options */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* End of menu */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); /* Blocked */ - extend_calls_until_shutdown(); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "recovery select screen"); - /* #0: Language menu */ - DISPLAYED_PASS(); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: Phone recovery */ - DISPLAYED_PASS(); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#1: phone recovery", VB2_SCREEN_RECOVERY_PHONE_STEP1, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #2: External disk recovery */ - DISPLAYED_PASS(); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#2: disk recovery", VB2_SCREEN_RECOVERY_DISK_STEP1, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - /* #3: Launch diagnostics */ - if (DIAGNOSTIC_UI) - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - /* #4: Advanced options */ - DISPLAYED_EQ("recovery select", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - - DISPLAYED_EQ("#3: advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* End of menu */ - DISPLAYED_PASS(); - DISPLAYED_EQ("end of menu", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, 5, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - /* Advanced options screen: disabled and hidden item mask */ - reset_common_data(FOR_MANUAL_RECOVERY); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - if (DIAGNOSTIC_UI) - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "advanced options screen: no disabled or hidden item"); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - if (DIAGNOSTIC_UI) - DISPLAYED_PASS(); - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE); - - /* Advanced options screen */ - reset_common_data(FOR_MANUAL_RECOVERY); - /* #0: Language menu */ - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_DOWN); - if (DIAGNOSTIC_UI) - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: Enable dev mode */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #2: Debug info */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #3: Firmware log */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #4: Back */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* End of menu */ - add_mock_keypress(VB_KEY_ENTER); - add_mock_keypress(VB_KEY_DOWN); - extend_calls_until_shutdown(); - TEST_EQ(vb2_manual_recovery_menu(ctx), VB2_REQUEST_SHUTDOWN, - "advanced options screen"); - DISPLAYED_PASS(); - DISPLAYED_PASS(); - if (DIAGNOSTIC_UI) - DISPLAYED_PASS(); - DISPLAYED_PASS(); - /* #0: Language menu */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 0, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: Enable dev mode */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 1, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#1: enable dev mode", VB2_SCREEN_RECOVERY_TO_DEV, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #2: Debug info */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#2: debug info", VB2_SCREEN_DEBUG_INFO, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #3: Firmware log */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 3, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#3: firmware log", VB2_SCREEN_FIRMWARE_LOG, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #4: Back */ - DISPLAYED_PASS(); - DISPLAYED_EQ("advanced options", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 4, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#4: back", VB2_SCREEN_RECOVERY_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* End of menu */ - DISPLAYED_PASS(); - DISPLAYED_EQ("end of menu", VB2_SCREEN_ADVANCED_OPTIONS, - MOCK_IGNORE, 2, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - VB2_DEBUG("...done.\n"); -} - -static void diagnostics_screen_tests(void) -{ - VB2_DEBUG("Testing diagnostic screens...\n"); - - /* Diagnostics screen: disabled and hidden item mask */ - reset_common_data(FOR_DIAGNOSTICS); - TEST_EQ(vb2_diagnostic_menu(ctx), VB2_REQUEST_SHUTDOWN, - "diagnostic screen: no disabled or hidden item"); - DISPLAYED_EQ("diagnostic menu", VB2_SCREEN_DIAGNOSTICS, - MOCK_IGNORE, MOCK_IGNORE, 0x0, 0x0, MOCK_IGNORE); - - /* Diagnostics screen */ - reset_common_data(FOR_DIAGNOSTICS); - - /* #0: Language menu */ - add_mock_keypress(VB_KEY_UP); - add_mock_keypress(VB_KEY_ENTER); - /* #1: Storage screen */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #2: Quick memory test screen */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #3: Full memory test screen */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - /* #4: Power off (End of menu) */ - add_mock_keypress(VB_KEY_ESC); - add_mock_keypress(VB_KEY_DOWN); - add_mock_keypress(VB_KEY_ENTER); - mock_calls_until_shutdown = -1; - TEST_EQ(vb2_diagnostic_menu(ctx), VB2_REQUEST_SHUTDOWN, - "diagnostic screen"); - - DISPLAYED_EQ("default on first button of menu", - VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 1, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - /* #0: Language menu */ - DISPLAYED_EQ("language selection", - VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 0, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#0: language menu", VB2_SCREEN_LANGUAGE_SELECT, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #1: Storage screen */ - DISPLAYED_PASS(); - DISPLAYED_EQ("storage button", - VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 1, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#1: storage screen", VB2_SCREEN_DIAGNOSTICS_STORAGE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, - MOCK_IGNORE); - /* #2: Quick memory test screen */ - DISPLAYED_PASS(); - DISPLAYED_EQ("quick memory test button", - VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 2, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#1: quick memory test screen", - VB2_SCREEN_DIAGNOSTICS_MEMORY_QUICK, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - /* #3: Full memory test screen */ - DISPLAYED_PASS(); - DISPLAYED_EQ("full memory test button", - VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 3, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_EQ("#3: full memory test screen", - VB2_SCREEN_DIAGNOSTICS_MEMORY_FULL, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE, MOCK_IGNORE); - /* #4: Power of (End of menu) */ - DISPLAYED_PASS(); - DISPLAYED_EQ("power off", - VB2_SCREEN_DIAGNOSTICS, MOCK_IGNORE, 4, MOCK_IGNORE, - MOCK_IGNORE, MOCK_IGNORE); - DISPLAYED_NO_EXTRA(); - - VB2_DEBUG("...done.\n"); -} - -int main(void) -{ - developer_tests(); - broken_recovery_tests(); - manual_recovery_tests(); - language_selection_tests(); - debug_info_tests(); - firmware_log_tests(); - - /* Screen displayed */ - developer_screen_tests(); - broken_recovery_screen_tests(); - manual_recovery_screen_tests(); - diagnostics_screen_tests(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vb2_ui_utility_tests.c vboot-utils-0~R99-14469.B/tests/vb2_ui_utility_tests.c --- vboot-utils-0~R88-13597.B/tests/vb2_ui_utility_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vb2_ui_utility_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,364 +0,0 @@ -/* Copyright 2020 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. - * - * Tests for UI utility functions. - */ - -#include "2api.h" -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2ui.h" -#include "2ui_private.h" -#include "test_common.h" -#include "vboot_api.h" - -/* Fixed value for ignoring some checks. */ -#define MOCK_IGNORE 0xffffu - -/* Mock screen index for testing screen utility functions. */ -#define MOCK_NO_SCREEN 0xef00 -#define MOCK_SCREEN_BASE 0xef10 -#define MOCK_SCREEN_MENU 0xef11 -#define MOCK_SCREEN_ROOT 0xefff - -/* Mock data */ -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_gbb_header gbb; - -static uint32_t mock_locale_count; -static int mock_shutdown_request; - -static struct vb2_ui_context mock_ui_context; - -/* Mock actions */ -static uint32_t mock_action_called; -static vb2_error_t mock_action_base(struct vb2_ui_context *ui) -{ - mock_action_called++; - return VB2_SUCCESS; -} - -/* Mock screens */ -struct vb2_screen_info mock_screen_blank = { - .id = VB2_SCREEN_BLANK, - .name = "mock_screen_blank", -}; -struct vb2_screen_info mock_screen_base = { - .id = MOCK_SCREEN_BASE, - .name = "mock_screen_base: menuless screen", -}; -struct vb2_menu_item mock_screen_menu_items[] = { - { - .text = "option 0: language selection", - .is_language_select = 1, - }, - { - .text = "option 1", - }, - { - .text = "option 2", - }, - { - .text = "option 3", - }, - { - .text = "option 4", - }, -}; -struct vb2_screen_info mock_screen_menu = { - .id = MOCK_SCREEN_MENU, - .name = "mock_screen_menu: screen with 5 options", - .menu = { - .num_items = ARRAY_SIZE(mock_screen_menu_items), - .items = mock_screen_menu_items, - }, -}; -struct vb2_screen_info mock_screen_root = { - .id = MOCK_SCREEN_ROOT, - .name = "mock_screen_root", -}; - -static void screen_state_eq(const struct vb2_screen_state *state, - enum vb2_screen screen, - uint32_t selected_item, - uint32_t hidden_item_mask) -{ - if (screen != MOCK_IGNORE) { - if (state->screen == NULL) - TEST_TRUE(0, " state.screen does not exist"); - else - TEST_EQ(state->screen->id, screen, " state.screen"); - } - if (selected_item != MOCK_IGNORE) - TEST_EQ(state->selected_item, - selected_item, " state.selected_item"); - if (hidden_item_mask != MOCK_IGNORE) - TEST_EQ(state->hidden_item_mask, - hidden_item_mask, " state.hidden_item_mask"); -} - -/* Reset mock data (for use before each test) */ -static void reset_common_data(void) -{ - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - - memset(&gbb, 0, sizeof(gbb)); - - vb2_nv_init(ctx); - - /* For vb2ex_get_locale_count */ - mock_locale_count = 1; - - /* For check_shutdown_request */ - mock_shutdown_request = MOCK_IGNORE; - - /* Mock ui_context based on mock screens */ - memset(&mock_ui_context, 0, sizeof(mock_ui_context)); - mock_ui_context.power_button = VB2_POWER_BUTTON_HELD_SINCE_BOOT; - - /* For mock actions */ - mock_action_called = 0; - - /* Reset init and action functions */ - mock_screen_blank.init = NULL; - mock_screen_blank.action = NULL; - mock_screen_base.init = NULL; - mock_screen_base.action = NULL; - mock_screen_menu.init = NULL; - mock_screen_menu.action = NULL; - mock_screen_root.init = NULL; - mock_screen_root.action = NULL; -} - -/* Mock functions */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -uint32_t vb2ex_get_locale_count(void) -{ - return mock_locale_count; -} - -uint32_t VbExIsShutdownRequested(void) -{ - if (mock_shutdown_request != MOCK_IGNORE) - return mock_shutdown_request; - - return 0; -} - -const struct vb2_screen_info *vb2_get_screen_info(enum vb2_screen screen) -{ - switch ((int)screen) { - case VB2_SCREEN_BLANK: - return &mock_screen_blank; - case MOCK_SCREEN_BASE: - return &mock_screen_base; - case MOCK_SCREEN_MENU: - return &mock_screen_menu; - case MOCK_SCREEN_ROOT: - return &mock_screen_root; - default: - return NULL; - } -} - -/* Tests */ -static void check_shutdown_request_tests(void) -{ - VB2_DEBUG("Testing check_shutdown_request...\n"); - - /* Release, press, hold, and release */ - if (!DETACHABLE) { - reset_common_data(); - mock_shutdown_request = 0; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "release, press, hold, and release"); - mock_shutdown_request = VB_SHUTDOWN_REQUEST_POWER_BUTTON; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, " press"); - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, " hold"); - mock_shutdown_request = 0; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_SHUTDOWN, " release"); - } - - /* Press is ignored because we may held since boot */ - if (!DETACHABLE) { - reset_common_data(); - mock_shutdown_request = VB_SHUTDOWN_REQUEST_POWER_BUTTON; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "press is ignored"); - } - - /* Power button short press from key */ - if (!DETACHABLE) { - reset_common_data(); - mock_shutdown_request = 0; - mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_SHUTDOWN, "power button short press"); - } - - /* Lid closure = shutdown request anyway */ - reset_common_data(); - mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_SHUTDOWN, "lid closure"); - mock_ui_context.key = 'A'; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_SHUTDOWN, " lidsw + random key"); - - /* Lid ignored by GBB flags */ - reset_common_data(); - gbb.flags |= VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN; - mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "lid ignored"); - if (!DETACHABLE) { /* Power button works for non DETACHABLE */ - mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED | - VB_SHUTDOWN_REQUEST_POWER_BUTTON; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, " lidsw + pwdsw"); - mock_shutdown_request = 0; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_SHUTDOWN, " pwdsw release"); - } - - /* Lid ignored; power button short pressed */ - if (!DETACHABLE) { - reset_common_data(); - gbb.flags |= VB2_GBB_FLAG_DISABLE_LID_SHUTDOWN; - mock_shutdown_request = VB_SHUTDOWN_REQUEST_LID_CLOSED; - mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_SHUTDOWN, - "lid ignored; power button short pressed"); - } - - /* DETACHABLE ignore power button */ - if (DETACHABLE) { - /* Flag pwdsw */ - reset_common_data(); - mock_shutdown_request = VB_SHUTDOWN_REQUEST_POWER_BUTTON; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, "DETACHABLE: ignore pwdsw"); - mock_shutdown_request = 0; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, " ignore on release"); - - /* Power button short press */ - reset_common_data(); - mock_shutdown_request = 0; - mock_ui_context.key = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(check_shutdown_request(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "DETACHABLE: ignore power button short press"); - } - - VB2_DEBUG("...done.\n"); -} - -static void screen_stack_tests(void) -{ - VB2_DEBUG("Testing screen stack functionality...\n"); - - /* Change to screen which does not exist */ - reset_common_data(); - TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_NO_SCREEN), - VB2_REQUEST_UI_CONTINUE, - "change to screen which does not exist"); - TEST_PTR_EQ(mock_ui_context.state, NULL, " stack is empty"); - - /* Screen back with empty stack */ - reset_common_data(); - TEST_EQ(vb2_ui_screen_back(&mock_ui_context), - VB2_REQUEST_UI_CONTINUE, - "screen back with empty stack"); - TEST_PTR_EQ(mock_ui_context.state, NULL, " stack is empty"); - - /* Back to previous screen, restoring the state */ - reset_common_data(); - mock_screen_base.init = mock_action_base; - vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_ROOT); - vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE); - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->hidden_item_mask = 0x10; - vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU); - TEST_EQ(vb2_ui_screen_back(&mock_ui_context), VB2_REQUEST_UI_CONTINUE, - "back to previous screen"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_BASE, 2, 0x10); - TEST_EQ(mock_action_called, 1, " action called once"); - - /* Change to target screen already in stack, restoring the state */ - reset_common_data(); - mock_screen_base.init = mock_action_base; - vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_ROOT); - vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE); - mock_ui_context.state->selected_item = 2; - mock_ui_context.state->hidden_item_mask = 0x10; - vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU); - TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_BASE), - VB2_REQUEST_UI_CONTINUE, "change to target in stack"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_BASE, 2, 0x10); - TEST_EQ(mock_action_called, 1, " action called once"); - - /* Change to screen without init; using default init() */ - reset_common_data(); - TEST_EQ(vb2_ui_screen_change(&mock_ui_context, MOCK_SCREEN_MENU), - VB2_REQUEST_UI_CONTINUE, - "change to screen with language selection"); - screen_state_eq(mock_ui_context.state, MOCK_SCREEN_MENU, - 1, /* Since index 0 is the language selection */ - 0); - - VB2_DEBUG("...done.\n"); -} - -static void get_language_menu_tests(void) -{ - const struct vb2_menu *menu; - const struct vb2_menu_item *items; - VB2_DEBUG("Testing get_language_menu...\n"); - - /* Only allocate menu items once */ - reset_common_data(); - mock_locale_count = 7; - menu = get_language_menu(&mock_ui_context); - TEST_PTR_NEQ(menu, NULL, "get language menu"); - TEST_EQ(menu->num_items, 7, " correct locale count"); - TEST_PTR_NEQ(menu->items, NULL, " items not null"); - items = menu->items; - - menu = get_language_menu(&mock_ui_context); - TEST_PTR_NEQ(menu, NULL, "get language menu again"); - TEST_EQ(menu->num_items, 7, " correct locale count again"); - TEST_PTR_EQ(menu->items, items, " same pointer of items"); - - /* Locale count = 0 */ - reset_common_data(); - mock_locale_count = 0; - menu = get_language_menu(&mock_ui_context); - TEST_PTR_NEQ(menu, NULL, "menu not null"); - TEST_EQ(menu->num_items, 1, " locale count 1"); - - VB2_DEBUG("...done.\n"); -} - -int main(void) -{ - check_shutdown_request_tests(); - screen_stack_tests(); - get_language_menu_tests(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_api_kernel4_tests.c vboot-utils-0~R99-14469.B/tests/vboot_api_kernel4_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_api_kernel4_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_api_kernel4_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -11,14 +11,11 @@ #include "2nvstorage.h" #include "2secdata.h" #include "2sysincludes.h" -#include "2ui.h" #include "host_common.h" #include "load_kernel_fw.h" #include "test_common.h" #include "tlcl.h" #include "tss_constants.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" #include "vboot_struct.h" #include "vboot_test.h" @@ -83,6 +80,9 @@ ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; expected_recovery_reason = recovery_reason; + /* The VbSelectAndLoadKernel directly leverages the value at + ctx->boot_mode, so we have to call vb2_set_boot_mode first. */ + vb2_set_boot_mode(ctx); TEST_EQ(VbSelectAndLoadKernel(ctx, &kparams), retval, desc); TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), recovery_reason, " recovery reason"); @@ -121,7 +121,7 @@ kernel_version = value; } -vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags) +vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t disk_flags) { sd->kernel_version = new_version; @@ -139,17 +139,7 @@ return vbboot_retval; } -vb2_error_t vb2_developer_menu(struct vb2_context *c) -{ - return boot_dev(c); -} - -vb2_error_t VbBootDeveloperLegacyClamshell(struct vb2_context *c) -{ - return boot_dev(c); -} - -vb2_error_t VbBootDeveloperLegacyMenu(struct vb2_context *c) +vb2_error_t vb2ex_developer_ui(struct vb2_context *c) { return boot_dev(c); } @@ -161,7 +151,7 @@ TEST_TRUE(commit_data_called, " commit data"); } -vb2_error_t vb2_manual_recovery_menu(struct vb2_context *c) +vb2_error_t vb2ex_manual_recovery_ui(struct vb2_context *c) { rec_check(c); if (vbboot_retval == -3) @@ -169,7 +159,7 @@ return vbboot_retval; } -vb2_error_t vb2_broken_recovery_menu(struct vb2_context *c) +vb2_error_t vb2ex_broken_screen_ui(struct vb2_context *c) { rec_check(c); if (vbboot_retval == -4) @@ -177,36 +167,8 @@ return vbboot_retval; } -vb2_error_t vb2_diagnostic_menu(struct vb2_context *c) -{ - TEST_TRUE(MENU_UI, "Using menu_ui"); - if (vbboot_retval == -5) - return VB2_ERROR_MOCK; - - return vbboot_retval; -} - -vb2_error_t VbBootRecoveryLegacyClamshell(struct vb2_context *c) -{ - rec_check(c); - /* Don't care if it's manual recovery or not */ - if (vbboot_retval == -3 || vbboot_retval == -4) - return VB2_ERROR_MOCK; - return vbboot_retval; -} - -vb2_error_t VbBootRecoveryLegacyMenu(struct vb2_context *c) +vb2_error_t vb2ex_diagnostic_ui(struct vb2_context *c) { - rec_check(c); - /* Don't care if it's manual recovery or not */ - if (vbboot_retval == -3 || vbboot_retval == -4) - return VB2_ERROR_MOCK; - return vbboot_retval; -} - -vb2_error_t VbBootDiagnosticLegacyClamshell(struct vb2_context *c) -{ - TEST_TRUE(!MENU_UI, "Not using menu_ui"); if (vbboot_retval == -5) return VB2_ERROR_MOCK; @@ -278,22 +240,19 @@ test_slk(VB2_ERROR_MOCK, 0, "Normal boot bad"); /* Check that NV_DIAG_REQUEST triggers diagnostic UI */ - if (DIAGNOSTIC_UI) { - reset_common_data(); - mock_diagnostic_ui_enabled = 1; - vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); - vbboot_retval = -5; - test_slk(VB2_ERROR_MOCK, 0, - "Normal boot with diag enabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0, - " diag not requested"); - - reset_common_data(); - vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); - test_slk(VB2_REQUEST_REBOOT, 0, - "Normal boot with diag disabled (reboot to " - "unset)"); - } + reset_common_data(); + mock_diagnostic_ui_enabled = 1; + vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); + vbboot_retval = -5; + test_slk(VB2_ERROR_MOCK, 0, + "Normal boot with diag enabled"); + TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0, + " diag not requested"); + + reset_common_data(); + vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1); + test_slk(VB2_REQUEST_REBOOT, 0, + "Normal boot with diag disabled (reboot to unset)"); /* Boot normal - phase1 failure */ reset_common_data(); @@ -369,7 +328,7 @@ reset_common_data(); sd->recovery_reason = VB2_RECOVERY_RO_MANUAL; vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 13); - sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY; + ctx->flags &= VB2_CONTEXT_FORCE_RECOVERY_MODE; test_slk(0, 0, "Manual recovery"); TEST_TRUE(commit_data_called, " commit data"); } diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_api_kernel_tests.c vboot-utils-0~R99-14469.B/tests/vboot_api_kernel_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_api_kernel_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_api_kernel_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -12,7 +12,6 @@ #include "load_kernel_fw.h" #include "test_common.h" #include "vboot_api.h" -#include "vboot_kernel.h" #include "vboot_test.h" #define MAX_TEST_DISKS 10 @@ -29,6 +28,7 @@ const char *name; /* inputs for test case */ + uint32_t ctx_flags; uint32_t want_flags; vb2_error_t diskgetinfo_return_val; disk_desc_t disks_to_provide[MAX_TEST_DISKS]; @@ -50,9 +50,46 @@ static const char pickme[] = "correct choice"; #define DONT_CARE ((const char *)42) -test_case_t test[] = { +test_case_t normal_tests[] = { + { + .name = "first drive (removable)", + .ctx_flags = 0, + .want_flags = VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_FIXED, + .disks_to_provide = { + {4096, 100, VB_DISK_FLAG_REMOVABLE, pickme}, + {4096, 100, VB_DISK_FLAG_FIXED, "holygrail"}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {0}, + .external_expected = {0}, + + .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED, + .expected_to_find_disk = pickme, + .expected_to_load_disk = pickme, + .expected_return_val = VB2_SUCCESS + }, + { + .name = "first drive (fixed)", + .ctx_flags = 0, + .want_flags = VB_DISK_FLAG_REMOVABLE | VB_DISK_FLAG_FIXED, + .disks_to_provide = { + {4096, 100, VB_DISK_FLAG_FIXED, pickme}, + {4096, 100, VB_DISK_FLAG_REMOVABLE, "holygrail"}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {0}, + .external_expected = {0}, + + .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED, + .expected_to_find_disk = pickme, + .expected_to_load_disk = pickme, + .expected_return_val = VB2_SUCCESS + }, { .name = "first removable drive", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_REMOVABLE, .disks_to_provide = { /* too small */ @@ -83,6 +120,7 @@ }, { .name = "first removable drive (skip external GPT)", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_REMOVABLE, .disks_to_provide = { /* too small */ @@ -115,6 +153,7 @@ }, { .name = "second removable drive", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_REMOVABLE, .disks_to_provide = { /* wrong flags */ @@ -133,6 +172,7 @@ }, { .name = "first fixed drive", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_FIXED, .disks_to_provide = { /* too small */ @@ -165,6 +205,7 @@ }, { .name = "no drives at all", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_FIXED, .disks_to_provide = {}, .disk_count_to_return = DEFAULT_COUNT, @@ -177,6 +218,7 @@ }, { .name = "VbExDiskGetInfo() error", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_FIXED, .disks_to_provide = { {512, 10, VB_DISK_FLAG_REMOVABLE, 0}, @@ -192,6 +234,7 @@ }, { .name = "invalid kernel", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_FIXED, .disks_to_provide = { /* too small */ @@ -223,6 +266,7 @@ }, { .name = "invalid kernel, order flipped", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_FIXED, .disks_to_provide = { {512, 1000, VB_DISK_FLAG_FIXED, "stateful partition"}, @@ -240,6 +284,7 @@ }, { .name = "no Chrome OS partitions", + .ctx_flags = 0, .want_flags = VB_DISK_FLAG_FIXED, .disks_to_provide = { {512, 100, VB_DISK_FLAG_FIXED, "stateful partition"}, @@ -257,6 +302,43 @@ }, { .name = "invalid kernel (removable)", + .ctx_flags = 0, + .want_flags = VB_DISK_FLAG_REMOVABLE, + .disks_to_provide = { + {512, 100, VB_DISK_FLAG_REMOVABLE, "corrupted"}, + {512, 100, VB_DISK_FLAG_REMOVABLE, "data"}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND, + VB2_ERROR_LK_NO_KERNEL_FOUND}, + + .expected_recovery_request_val = VB2_RECOVERY_RW_INVALID_OS, + .expected_to_find_disk = DONT_CARE, + .expected_to_load_disk = 0, + .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND, + }, + { + .name = "invalid kernel (removable, rec mode)", + .ctx_flags = VB2_CONTEXT_RECOVERY_MODE, + .want_flags = VB_DISK_FLAG_REMOVABLE, + .disks_to_provide = { + {512, 100, VB_DISK_FLAG_REMOVABLE, "corrupted"}, + {512, 100, VB_DISK_FLAG_REMOVABLE, "data"}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND, + VB2_ERROR_LK_NO_KERNEL_FOUND}, + + .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED, + .expected_to_find_disk = DONT_CARE, + .expected_to_load_disk = 0, + .expected_return_val = VB2_ERROR_LK_INVALID_KERNEL_FOUND, + }, + { + .name = "invalid kernel (removable, dev mode)", + .ctx_flags = VB2_CONTEXT_DEVELOPER_MODE, .want_flags = VB_DISK_FLAG_REMOVABLE, .disks_to_provide = { {512, 100, VB_DISK_FLAG_REMOVABLE, "corrupted"}, @@ -274,6 +356,23 @@ }, { .name = "no kernel (removable)", + .ctx_flags = 0, + .want_flags = VB_DISK_FLAG_REMOVABLE, + .disks_to_provide = { + {512, 100, VB_DISK_FLAG_REMOVABLE, "data"}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {VB2_ERROR_LK_NO_KERNEL_FOUND}, + + .expected_recovery_request_val = VB2_RECOVERY_RW_NO_KERNEL, + .expected_to_find_disk = DONT_CARE, + .expected_to_load_disk = 0, + .expected_return_val = VB2_ERROR_LK_NO_KERNEL_FOUND, + }, + { + .name = "no kernel (removable, rec mode)", + .ctx_flags = VB2_CONTEXT_RECOVERY_MODE, .want_flags = VB_DISK_FLAG_REMOVABLE, .disks_to_provide = { {512, 100, VB_DISK_FLAG_REMOVABLE, "data"}, @@ -289,12 +388,52 @@ }, }; +test_case_t minios_tests[] = { + { + .name = "pick first fixed drive", + .ctx_flags = 0, + .disks_to_provide = { + {4096, 100, VB_DISK_FLAG_REMOVABLE, 0}, + {4096, 100, VB_DISK_FLAG_FIXED, pickme}, + {4096, 100, VB_DISK_FLAG_FIXED, "holygrail"}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {0}, + .external_expected = {0}, + + .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED, + .expected_to_find_disk = pickme, + .expected_to_load_disk = pickme, + .expected_return_val = VB2_SUCCESS + }, + { + .name = "skip failed fixed drive", + .ctx_flags = 0, + .disks_to_provide = { + {4096, 100, VB_DISK_FLAG_FIXED, "holygrail"}, + {4096, 100, VB_DISK_FLAG_FIXED, pickme}, + }, + .disk_count_to_return = DEFAULT_COUNT, + .diskgetinfo_return_val = VB2_SUCCESS, + .loadkernel_return_val = {VB2_ERROR_LK_INVALID_KERNEL_FOUND, 0}, + .external_expected = {0}, + + .expected_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED, + .expected_to_find_disk = pickme, + .expected_to_load_disk = pickme, + .expected_return_val = VB2_SUCCESS + }, +}; + /****************************************************************************/ /* Mock data */ static VbDiskInfo mock_disks[MAX_TEST_DISKS]; static test_case_t *t; static int load_kernel_calls; +static int lk_normal_calls; +static int lk_minios_calls; static uint32_t got_recovery_request_val; static const char *got_find_disk; static const char *got_load_disk; @@ -303,26 +442,31 @@ static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] __attribute__((aligned(VB2_WORKBUF_ALIGN))); static struct vb2_context *ctx; +static struct VbSelectAndLoadKernelParams kparams; /** * Reset mock data (for use before each test) */ -static void ResetMocks(int i) +static void ResetMocks(test_case_t *test_case) { TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), "vb2api_init failed"); - memset(VbApiKernelGetParams(), 0, sizeof(LoadKernelParams)); + memset(&kparams, 0, sizeof(VbSelectAndLoadKernelParams)); + *VbApiKernelGetParamsPtr() = &kparams; + memset(&mock_disks, 0, sizeof(mock_disks)); load_kernel_calls = 0; + lk_normal_calls = 0; + lk_minios_calls = 0; got_recovery_request_val = VB2_RECOVERY_NOT_REQUESTED; got_find_disk = 0; got_load_disk = 0; got_return_val = 0xdeadbeef; - t = test + i; + t = test_case; } static int is_nonzero(const void *vptr, size_t count) @@ -395,18 +539,36 @@ return VB2_SUCCESS; } -vb2_error_t LoadKernel(struct vb2_context *c, LoadKernelParams *params) +static vb2_error_t LoadKernelImpl(struct vb2_context *c, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info) { got_find_disk = (const char *)params->disk_handle; VB2_DEBUG("%s(%d): got_find_disk = %s\n", __FUNCTION__, load_kernel_calls, got_find_disk ? got_find_disk : "0"); if (t->external_expected[load_kernel_calls] != - !!(params->boot_flags & BOOT_FLAG_EXTERNAL_GPT)) + !!(disk_info->flags & VB_DISK_FLAG_EXTERNAL_GPT)) got_external_mismatch++; return t->loadkernel_return_val[load_kernel_calls++]; } +vb2_error_t LoadKernel(struct vb2_context *c, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info) +{ + lk_normal_calls++; + return LoadKernelImpl(c, params, disk_info); +} + +vb2_error_t LoadMiniOsKernel(struct vb2_context *c, + VbSelectAndLoadKernelParams *params, + VbDiskInfo *disk_info, uint32_t minios_flags) +{ + lk_minios_calls++; + return LoadKernelImpl(c, params, disk_info); +} + void vb2_nv_set(struct vb2_context *c, enum vb2_nv_param param, uint32_t value) @@ -423,12 +585,38 @@ static void VbTryLoadKernelTest(void) { int i; - int num_tests = sizeof(test) / sizeof(test[0]); + int num_tests = ARRAY_SIZE(normal_tests); + + for (i = 0; i < num_tests; i++) { + printf("Test case: %s ...\n", normal_tests[i].name); + ResetMocks(&normal_tests[i]); + ctx->flags = t->ctx_flags; + TEST_EQ(VbTryLoadKernel(ctx, t->want_flags), + t->expected_return_val, " return value"); + TEST_EQ(got_recovery_request_val, + t->expected_recovery_request_val, " recovery_request"); + if (t->expected_to_find_disk != DONT_CARE) { + TEST_PTR_EQ(got_find_disk, t->expected_to_find_disk, + " find disk"); + TEST_PTR_EQ(got_load_disk, t->expected_to_load_disk, + " load disk"); + } + TEST_EQ(got_external_mismatch, 0, " external GPT errors"); + } + TEST_EQ(lk_normal_calls, load_kernel_calls, " LoadKernel called"); + TEST_EQ(lk_minios_calls, 0, " LoadMiniOsKernel not called"); +} + +static void VbTryLoadMiniOsKernelTest(void) +{ + int i; + int num_tests = ARRAY_SIZE(minios_tests); for (i = 0; i < num_tests; i++) { - printf("Test case: %s ...\n", test[i].name); - ResetMocks(i); - TEST_EQ(VbTryLoadKernel(ctx, test[i].want_flags), + printf("Test case: %s ...\n", minios_tests[i].name); + ResetMocks(&minios_tests[i]); + ctx->flags = t->ctx_flags; + TEST_EQ(VbTryLoadMiniOsKernel(ctx, 0), t->expected_return_val, " return value"); TEST_EQ(got_recovery_request_val, t->expected_recovery_request_val, " recovery_request"); @@ -440,11 +628,15 @@ } TEST_EQ(got_external_mismatch, 0, " external GPT errors"); } + TEST_EQ(lk_normal_calls, 0, " LoadKernel not called"); + TEST_EQ(lk_minios_calls, load_kernel_calls, + " LoadMiniOsKernel called"); } int main(void) { VbTryLoadKernelTest(); + VbTryLoadMiniOsKernelTest(); return gTestSuccess ? 0 : 255; } diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_kernel2_tests.c vboot-utils-0~R99-14469.B/tests/vboot_kernel2_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_kernel2_tests.c 1970-01-01 00:00:00.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_kernel2_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -0,0 +1,459 @@ +/* Copyright 2021 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. + * + * Tests for miniOS kernel selection, loading, verification, and booting. + */ + +#include "2api.h" +#include "2common.h" +#include "2misc.h" +#include "2nvstorage.h" +#include "2secdata.h" +#include "load_kernel_fw.h" +#include "test_common.h" +#include "vboot_api.h" + +#define MAX_MOCK_KERNELS 10 +#define KBUF_SIZE 65536 + +/* Internal struct to simulate a stream for sector-based disks */ +struct disk_stream { + /* Disk handle */ + VbExDiskHandle_t handle; + + /* Next sector to read */ + uint64_t sector; + + /* Number of sectors left */ + uint64_t sectors_left; +}; + +/* Represent a "kernel" located on the disk */ +struct mock_kernel { + /* Sector where the kernel begins */ + uint64_t sector; + + /* Return value from vb2_load_partition */ + vb2_error_t rv; + + /* Number of times the sector was read */ + int read_count; +}; + +/* Mock data */ +static struct vb2_context *ctx; +static struct vb2_shared_data *sd; +static struct vb2_workbuf wb; +static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] + __attribute__((aligned(VB2_WORKBUF_ALIGN))); +static enum vb2_boot_mode *boot_mode; + +static VbSelectAndLoadKernelParams lkp; +static VbDiskInfo disk_info; +static struct vb2_keyblock kbh; +static struct vb2_kernel_preamble kph; +static uint8_t kernel_buffer[80000]; + +static struct mock_kernel kernels[MAX_MOCK_KERNELS]; +static int kernel_count; +static struct mock_kernel *cur_kernel; + +static int mock_tpm_set_mode_calls; + +static void add_mock_kernel(uint64_t sector, vb2_error_t rv) +{ + if (kernel_count >= ARRAY_SIZE(kernels)) { + TEST_TRUE(0, " kernel_count ran out of entries!"); + return; + } + + kernels[kernel_count].sector = sector; + kernels[kernel_count].rv = rv; + kernel_count++; +} + +static void reset_common_data(void) +{ + TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), + "vb2api_init failed"); + vb2_workbuf_from_ctx(ctx, &wb); + vb2_nv_init(ctx); + vb2api_secdata_kernel_create(ctx); + vb2_secdata_kernel_init(ctx); + ctx->flags = VB2_CONTEXT_RECOVERY_MODE; + + boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + + sd = vb2_get_sd(ctx); + sd->kernel_version_secdata = 0xabcdef | (1 << 24); + + memset(&lkp, 0, sizeof(lkp)); + lkp.kernel_buffer = kernel_buffer; + lkp.kernel_buffer_size = sizeof(kernel_buffer); + lkp.disk_handle = (VbExDiskHandle_t)1; + + memset(&disk_info, 0, sizeof(disk_info)); + disk_info.bytes_per_lba = 512; + disk_info.lba_count = 1024; + disk_info.handle = lkp.disk_handle; + + memset(&kbh, 0, sizeof(kbh)); + kbh.data_key.key_version = 2; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_DEVELOPER_1 + | VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_MINIOS_1; + kbh.keyblock_size = sizeof(kbh); + + memset(&kph, 0, sizeof(kph)); + kph.kernel_version = 1; + kph.preamble_size = 4096 - kbh.keyblock_size; + kph.body_signature.data_size = 0; + kph.bootloader_address = 0xbeadd008; + kph.bootloader_size = 0x1234; + + + memset(&kernels, 0, sizeof(kernels)); + kernel_count = 0; + cur_kernel = NULL; + + mock_tpm_set_mode_calls = 0; +} + +/* Mocks */ + +vb2_error_t VbExStreamOpen(VbExDiskHandle_t handle, uint64_t lba_start, + uint64_t lba_count, VbExStream_t *stream) +{ + struct disk_stream *s; + uint64_t i; + + if (!handle) { + *stream = NULL; + return VB2_ERROR_UNKNOWN; + } + + if (lba_start + lba_count > disk_info.lba_count) + return VB2_ERROR_UNKNOWN; + + s = malloc(sizeof(*s)); + s->handle = handle; + s->sector = lba_start; + s->sectors_left = lba_count; + + *stream = (void *)s; + + for (i = 0; i < kernel_count; i++) { + if (kernels[i].sector == lba_start) + cur_kernel = &kernels[i]; + } + + return VB2_SUCCESS; +} + +vb2_error_t VbExStreamRead(VbExStream_t stream, uint32_t bytes, void *buffer) +{ + struct disk_stream *s = (struct disk_stream *)stream; + uint64_t sectors; + uint64_t i; + + if (!s) + return VB2_ERROR_UNKNOWN; + + /* For now, require reads to be a multiple of the LBA size */ + if (bytes % disk_info.bytes_per_lba) + return VB2_ERROR_UNKNOWN; + + /* Fail on overflow */ + sectors = bytes / disk_info.bytes_per_lba; + if (sectors > s->sectors_left) + return VB2_ERROR_UNKNOWN; + + memset(buffer, 0, bytes); + for (i = 0; i < kernel_count; i++) { + if (kernels[i].sector >= s->sector && + kernels[i].sector < s->sector + sectors) { + VB2_DEBUG("Simulating kernel %" PRIu64 " match\n", i); + uint64_t buf_offset = (kernels[i].sector - s->sector) + * disk_info.bytes_per_lba; + memcpy(buffer + buf_offset, VB2_KEYBLOCK_MAGIC, + VB2_KEYBLOCK_MAGIC_SIZE); + kernels[i].read_count++; + TEST_TRUE(kernels[i].read_count <= 2, + " Max read count exceeded"); + } + } + + s->sector += sectors; + s->sectors_left -= sectors; + + return VB2_SUCCESS; +} + +void VbExStreamClose(VbExStream_t stream) +{ + free(stream); +} + +vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key, + const uint8_t *buf, uint32_t size) +{ + return cur_kernel->rv; +} + +vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size, + const struct vb2_public_key *key, + const struct vb2_workbuf *w) +{ + /* Use this as an opportunity to override the keyblock */ + memcpy((void *)block, &kbh, sizeof(kbh)); + + return cur_kernel->rv; +} + +vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block, + uint32_t size, + const struct vb2_workbuf *w) +{ + /* Use this as an opportunity to override the keyblock */ + memcpy((void *)block, &kbh, sizeof(kbh)); + + return cur_kernel->rv; +} + +vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble, + uint32_t size, const struct vb2_public_key *key, + const struct vb2_workbuf *w) +{ + /* Use this as an opportunity to override the preamble */ + memcpy((void *)preamble, &kph, sizeof(kph)); + + return cur_kernel->rv; +} + +vb2_error_t vb2_verify_data(const uint8_t *data, uint32_t size, + struct vb2_signature *sig, + const struct vb2_public_key *key, + const struct vb2_workbuf *w) +{ + return cur_kernel->rv; +} + +vb2_error_t vb2_digest_buffer(const uint8_t *buf, uint32_t size, + enum vb2_hash_algorithm hash_alg, uint8_t *digest, + uint32_t digest_size) +{ + return cur_kernel->rv; +} + +vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val) +{ + mock_tpm_set_mode_calls++; + return VB2_SUCCESS; +} + +/* Make sure nothing tested here ever calls this directly. */ +void vb2api_fail(struct vb2_context *c, uint8_t reason, uint8_t subcode) +{ + TEST_TRUE(0, " called vb2api_fail()"); +} + +/* Tests */ + +static void load_minios_kernel_tests(void) +{ + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 1; + add_mock_kernel(0, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "{valid kernel}"); + TEST_EQ(mock_tpm_set_mode_calls, 1, + " TPM disabled"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 1; + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, "{no kernel}"); + TEST_EQ(mock_tpm_set_mode_calls, 0, + " TPM not disabled"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(1, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "{no kernel, valid kernel}"); + TEST_EQ(cur_kernel->sector, 1, " select kernel"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_ERROR_MOCK); + add_mock_kernel(1, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "{invalid kernel, valid kernel}"); + TEST_EQ(cur_kernel->sector, 1, " select second kernel"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_ERROR_MOCK); + add_mock_kernel(1, VB2_ERROR_MOCK); + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "{invalid kernel, invalid kernel}"); + TEST_EQ(mock_tpm_set_mode_calls, 0, + " TPM not disabled"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + add_mock_kernel(1, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "{valid kernel, valid kernel} minios_priority=0"); + TEST_EQ(cur_kernel->sector, 0, " select first kernel"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + add_mock_kernel(1, VB2_SUCCESS); + vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "{valid kernel, valid kernel} minios_priority=1"); + TEST_EQ(cur_kernel->sector, 1, " select second kernel"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + add_mock_kernel(1, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, + VB_MINIOS_FLAG_NON_ACTIVE), + "{valid kernel, valid kernel} minios_priority=0 non-active"); + TEST_EQ(cur_kernel->sector, 1, " select second kernel"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_ERROR_MOCK); + add_mock_kernel(1, VB2_SUCCESS); + vb2_nv_set(ctx, VB2_NV_MINIOS_PRIORITY, 1); + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, + VB_MINIOS_FLAG_NON_ACTIVE), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "{invalid kernel, valid kernel} minios_priority=1 non-active"); + + reset_common_data(); + disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE; + disk_info.lba_count = 4; + add_mock_kernel(1, VB2_SUCCESS); + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "valid kernel header near start of disk (disk too small)"); + + reset_common_data(); + disk_info.bytes_per_lba = VB2_KEYBLOCK_MAGIC_SIZE; + disk_info.lba_count = 1000; + add_mock_kernel(999, VB2_SUCCESS); + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "valid kernel header near end of disk"); + + reset_common_data(); + disk_info.bytes_per_lba = 1024; + disk_info.lba_count = 128; + add_mock_kernel(63, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "start/end overlap assuming >128 MB search range (start)"); + + reset_common_data(); + disk_info.bytes_per_lba = 1024; + disk_info.lba_count = 128; + add_mock_kernel(64, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "start/end overlap assuming >128 MB search range (end)"); + + reset_common_data(); + disk_info.bytes_per_lba = 128; + disk_info.lba_count = 1024; + add_mock_kernel(3, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "kernel at last sector in batch assuming 512 KB batches"); + + reset_common_data(); + disk_info.bytes_per_lba = 256; + disk_info.lba_count = 1024; + add_mock_kernel(3, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "kernel at last sector in batch assuming 1 MB batches"); + + reset_common_data(); + disk_info.bytes_per_lba = 512; + disk_info.lba_count = 1024; + add_mock_kernel(3, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "kernel at last sector in batch assuming 2 MB batches"); + + reset_common_data(); + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_MINIOS_1; + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "kernel with minios keyblock flag"); + + reset_common_data(); + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_MINIOS_0; + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "kernel with !minios keyblock flag"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + sd->kernel_version_secdata = 5 << 24; + kph.kernel_version = 4; + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "kernel version too old"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + sd->kernel_version_secdata = 5 << 24; + kph.kernel_version = 0x100; + TEST_EQ(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + VB2_ERROR_LK_NO_KERNEL_FOUND, + "kernel version greater than 0xff"); + + reset_common_data(); + disk_info.bytes_per_lba = KBUF_SIZE; + disk_info.lba_count = 2; + add_mock_kernel(0, VB2_SUCCESS); + sd->kernel_version_secdata = 5 << 24; + kph.kernel_version = 6; + TEST_SUCC(LoadMiniOsKernel(ctx, &lkp, &disk_info, 0), + "newer kernel version"); +} + +int main(void) +{ + load_minios_kernel_tests(); + + return gTestSuccess ? 0 : 255; +} diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_kernel_tests.c vboot-utils-0~R99-14469.B/tests/vboot_kernel_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_kernel_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_kernel_tests.c 2022-02-11 14:46:24.000000000 +0000 @@ -11,24 +11,12 @@ #include "2nvstorage.h" #include "2secdata.h" #include "2secdata_struct.h" -#include "2sha.h" -#include "2sysincludes.h" #include "cgptlib.h" #include "cgptlib_internal.h" -#include "crc32.h" #include "gpt.h" -#include "host_common.h" #include "load_kernel_fw.h" #include "test_common.h" -#include "vb2_common.h" #include "vboot_api.h" -#include "vboot_kernel.h" - -#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args) -#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, " calls") - -#define MOCK_SECTOR_SIZE 512 -#define MOCK_SECTOR_COUNT 1024 /* Mock kernel partition */ struct mock_part { @@ -42,10 +30,8 @@ static int mock_part_next; /* Mock data */ -static char call_log[4096]; static uint8_t kernel_buffer[80000]; static int disk_read_to_fail; -static int disk_write_to_fail; static int gpt_init_fail; static int keyblock_verify_fail; /* 0=ok, 1=sig, 2=hash */ static int preamble_verify_fail; @@ -54,74 +40,25 @@ static int gpt_flag_external; static struct vb2_gbb_header gbb; -static VbExDiskHandle_t handle; -static LoadKernelParams lkp; +static VbSelectAndLoadKernelParams lkp; +static VbDiskInfo disk_info; static struct vb2_keyblock kbh; static struct vb2_kernel_preamble kph; static struct vb2_secdata_fwmp *fwmp; -static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT]; -static GptHeader *mock_gpt_primary = - (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1]; -static GptHeader *mock_gpt_secondary = - (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)]; static uint8_t mock_digest[VB2_SHA256_DIGEST_SIZE] = {12, 34, 56, 78}; static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] __attribute__((aligned(VB2_WORKBUF_ALIGN))); static struct vb2_context *ctx; static struct vb2_shared_data *sd; static struct vb2_packed_key mock_key; - -/** - * Prepare a valid GPT header that will pass CheckHeader() tests - */ -static void SetupGptHeader(GptHeader *h, int is_secondary) -{ - memset(h, '\0', MOCK_SECTOR_SIZE); - - /* "EFI PART" */ - memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE); - h->revision = GPT_HEADER_REVISION; - h->size = MIN_SIZE_OF_HEADER; - - /* 16KB: 128 entries of 128 bytes */ - h->size_of_entry = sizeof(GptEntry); - h->number_of_entries = MAX_NUMBER_OF_ENTRIES; - - /* Set LBA pointers for primary or secondary header */ - if (is_secondary) { - h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS; - h->entries_lba = h->my_lba - CalculateEntriesSectors(h, - MOCK_SECTOR_SIZE); - } else { - h->my_lba = GPT_PMBR_SECTORS; - h->entries_lba = h->my_lba + 1; - } - - h->first_usable_lba = 2 + CalculateEntriesSectors(h, MOCK_SECTOR_SIZE); - h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h, - MOCK_SECTOR_SIZE); - - h->header_crc32 = HeaderCrc(h); -} - -static void ResetCallLog(void) -{ - *call_log = 0; -} +static enum vb2_boot_mode *boot_mode; /** * Reset mock data (for use before each test) */ static void ResetMocks(void) { - ResetCallLog(); - - memset(&mock_disk, 0, sizeof(mock_disk)); - SetupGptHeader(mock_gpt_primary, 0); - SetupGptHeader(mock_gpt_secondary, 1); - disk_read_to_fail = -1; - disk_write_to_fail = -1; gpt_init_fail = 0; keyblock_verify_fail = 0; @@ -137,13 +74,16 @@ gbb.flags = 0; memset(&lkp, 0, sizeof(lkp)); - lkp.bytes_per_lba = 512; - lkp.streaming_lba_count = 1024; - lkp.gpt_lba_count = 1024; lkp.kernel_buffer = kernel_buffer; lkp.kernel_buffer_size = sizeof(kernel_buffer); lkp.disk_handle = (VbExDiskHandle_t)1; + memset(&disk_info, 0, sizeof(disk_info)); + disk_info.bytes_per_lba = 512; + disk_info.streaming_lba_count = 1024; + disk_info.lba_count = 1024; + disk_info.handle = lkp.disk_handle; + memset(&kbh, 0, sizeof(kbh)); kbh.data_key.key_version = 2; kbh.keyblock_flags = -1; @@ -168,14 +108,22 @@ vb2_nv_init(ctx); sd = vb2_get_sd(ctx); - sd->kernel_version = 0x20001; + sd->kernel_version_secdata = 0x20001; /* CRC will be invalid after here, but nobody's checking */ sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT; fwmp = (struct vb2_secdata_fwmp *)ctx->secdata_fwmp; memcpy(&fwmp->dev_key_hash, mock_digest, sizeof(fwmp->dev_key_hash)); - // TODO: more workbuf fields - flags, secdata_firmware, secdata_kernel + boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode; + *boot_mode = VB2_BOOT_MODE_NORMAL; + + // TODO: more workbuf fields - flags, secdata_firmware + + vb2api_secdata_kernel_create(ctx); + vb2_secdata_kernel_init(ctx); + vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, + VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED); } /* Mocks */ @@ -211,29 +159,15 @@ vb2_error_t VbExDiskRead(VbExDiskHandle_t h, uint64_t lba_start, uint64_t lba_count, void *buffer) { - LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count); - if ((int)lba_start == disk_read_to_fail) return VB2_ERROR_MOCK; - memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE], - lba_count * MOCK_SECTOR_SIZE); - return VB2_SUCCESS; } -vb2_error_t VbExDiskWrite(VbExDiskHandle_t h, uint64_t lba_start, - uint64_t lba_count, const void *buffer) +int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) { - LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count); - - if ((int)lba_start == disk_write_to_fail) - return VB2_ERROR_MOCK; - - memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer, - lba_count * MOCK_SECTOR_SIZE); - - return VB2_SUCCESS; + return GPT_SUCCESS; } int GptInit(GptData *gpt) @@ -258,6 +192,16 @@ return GPT_SUCCESS; } +int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type) +{ + return GPT_SUCCESS; +} + +int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata) +{ + return GPT_SUCCESS; +} + void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest) { static char fake_guid[] = "FakeGuid"; @@ -335,260 +279,9 @@ TEST_TRUE(0, " called vb2api_fail()"); } -/** - * Test reading/writing GPT - */ -static void ReadWriteGptTest(void) -{ - GptData g; - GptHeader *h; - - g.sector_bytes = MOCK_SECTOR_SIZE; - g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT; - g.valid_headers = g.valid_entries = MASK_BOTH; - - ResetMocks(); - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 2, 32)\n" - "VbExDiskRead(h, 1023, 1)\n" - "VbExDiskRead(h, 991, 32)\n"); - ResetCallLog(); - /* - * Valgrind complains about access to uninitialized memory here, so - * zero the primary header before each test. - */ - memset(g.primary_header, '\0', g.sector_bytes); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree"); - TEST_CALLS(""); - - /* - * Invalidate primary GPT header, - * check that AllocAndReadGptData still succeeds - */ - ResetMocks(); - memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary)); - TEST_EQ(AllocAndReadGptData(handle, &g), 0, - "AllocAndRead primary invalid"); - TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 1, "Primary header is invalid"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 0, "Secondary header is valid"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 1023, 1)\n" - "VbExDiskRead(h, 991, 32)\n"); - WriteAndFreeGptData(handle, &g); - - /* - * Invalidate secondary GPT header, - * check that AllocAndReadGptData still succeeds - */ - ResetMocks(); - memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary)); - TEST_EQ(AllocAndReadGptData(handle, &g), 0, - "AllocAndRead secondary invalid"); - TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 0, "Primary header is valid"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 1, "Secondary header is invalid"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 2, 32)\n" - "VbExDiskRead(h, 1023, 1)\n"); - WriteAndFreeGptData(handle, &g); - - /* - * Invalidate primary AND secondary GPT header, - * check that AllocAndReadGptData fails. - */ - ResetMocks(); - memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary)); - memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary)); - TEST_EQ(AllocAndReadGptData(handle, &g), 1, - "AllocAndRead primary and secondary invalid"); - TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 1, "Primary header is invalid"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 1, "Secondary header is invalid"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 1023, 1)\n"); - WriteAndFreeGptData(handle, &g); - - /* - * Invalidate primary GPT header and check that it is - * repaired by GptRepair(). - * - * This would normally be called by LoadKernel()->GptInit() - * but this callback is mocked in these tests. - */ - ResetMocks(); - memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary)); - TEST_EQ(AllocAndReadGptData(handle, &g), 0, - "Fix Primary GPT: AllocAndRead"); - /* Call GptRepair() with input indicating secondary GPT is valid */ - g.valid_headers = g.valid_entries = MASK_SECONDARY; - GptRepair(&g); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, - "Fix Primary GPT: WriteAndFreeGptData"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 1023, 1)\n" - "VbExDiskRead(h, 991, 32)\n" - "VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n"); - TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 0, "Fix Primary GPT: Primary header is valid"); - - /* - * Invalidate secondary GPT header and check that it can be - * repaired by GptRepair(). - * - * This would normally be called by LoadKernel()->GptInit() - * but this callback is mocked in these tests. - */ - ResetMocks(); - memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary)); - TEST_EQ(AllocAndReadGptData(handle, &g), 0, - "Fix Secondary GPT: AllocAndRead"); - /* Call GptRepair() with input indicating primary GPT is valid */ - g.valid_headers = g.valid_entries = MASK_PRIMARY; - GptRepair(&g); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, - "Fix Secondary GPT: WriteAndFreeGptData"); - TEST_CALLS("VbExDiskRead(h, 1, 1)\n" - "VbExDiskRead(h, 2, 32)\n" - "VbExDiskRead(h, 1023, 1)\n" - "VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors, - g.gpt_drive_sectors, 0, g.sector_bytes), - 0, "Fix Secondary GPT: Secondary header is valid"); - - /* Data which is changed is written */ - ResetMocks(); - AllocAndReadGptData(handle, &g); - g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1; - ResetCallLog(); - memset(g.primary_header, '\0', g.sector_bytes); - h = (GptHeader*)g.primary_header; - h->entries_lba = 2; - h->number_of_entries = MAX_NUMBER_OF_ENTRIES; - h->size_of_entry = sizeof(GptEntry); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); - TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n"); - - /* Data which is changed is written */ - ResetMocks(); - AllocAndReadGptData(handle, &g); - g.modified = -1; - ResetCallLog(); - memset(g.primary_header, '\0', g.sector_bytes); - h = (GptHeader*)g.primary_header; - h->entries_lba = 2; - h->number_of_entries = MAX_NUMBER_OF_ENTRIES; - h->size_of_entry = sizeof(GptEntry); - h = (GptHeader*)g.secondary_header; - h->entries_lba = 991; - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); - TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n" - "VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - - /* If legacy signature, don't modify GPT header/entries 1 */ - ResetMocks(); - AllocAndReadGptData(handle, &g); - h = (GptHeader *)g.primary_header; - memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE); - g.modified = -1; - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all"); - TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - - /* Error reading */ - ResetMocks(); - disk_read_to_fail = 1; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = g.valid_entries = MASK_SECONDARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); - TEST_CALLS("VbExDiskWrite(h, 1, 1)\n" - "VbExDiskWrite(h, 2, 32)\n"); - - ResetMocks(); - disk_read_to_fail = 2; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = MASK_BOTH; - g.valid_entries = MASK_SECONDARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1"); - TEST_CALLS("VbExDiskWrite(h, 2, 32)\n"); - - ResetMocks(); - disk_read_to_fail = 991; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = MASK_BOTH; - g.valid_entries = MASK_PRIMARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); - TEST_CALLS("VbExDiskWrite(h, 991, 32)\n"); - - ResetMocks(); - disk_read_to_fail = 1023; - TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail"); - g.valid_headers = g.valid_entries = MASK_PRIMARY; - GptRepair(&g); - ResetCallLog(); - TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 2"); - TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n" - "VbExDiskWrite(h, 991, 32)\n"); - - /* Error writing */ - ResetMocks(); - disk_write_to_fail = 1; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - - ResetMocks(); - disk_write_to_fail = 2; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - h = (GptHeader*)g.primary_header; - h->entries_lba = 2; - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - - ResetMocks(); - disk_write_to_fail = 991; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - - ResetMocks(); - disk_write_to_fail = 1023; - AllocAndReadGptData(handle, &g); - g.modified = -1; - memset(g.primary_header, '\0', g.sector_bytes); - TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail"); - -} - static void TestLoadKernel(int expect_retval, const char *test_name) { - TEST_EQ(LoadKernel(ctx, &lkp), expect_retval, test_name); + TEST_EQ(LoadKernel(ctx, &lkp, &disk_info), expect_retval, test_name); } /** @@ -603,6 +296,7 @@ /* This causes the stream open call to fail */ ResetMocks(); lkp.disk_handle = NULL; + disk_info.handle = NULL; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad disk handle"); } @@ -647,6 +341,7 @@ /* In dev mode, fail if hash is bad too */ ResetMocks(); ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; keyblock_verify_fail = 2; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Fail key block dev hash"); @@ -654,6 +349,7 @@ /* But just bad sig is ok */ ResetMocks(); ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; keyblock_verify_fail = 1; TestLoadKernel(0, "Succeed keyblock dev sig"); TEST_EQ(sd->flags & VB2_SD_FLAG_KERNEL_SIGNED, 0, " use hash"); @@ -661,6 +357,7 @@ /* In dev mode and requiring signed kernel, fail if sig is bad */ ResetMocks(); ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1); keyblock_verify_fail = 1; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, @@ -668,39 +365,110 @@ ResetMocks(); ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY; keyblock_verify_fail = 1; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Fail key block dev sig fwmp"); - /* Check keyblock flag mismatches */ + /* Check keyblock flags */ ResetMocks(); - kbh.keyblock_flags = - VB2_KEYBLOCK_FLAG_RECOVERY_0 | VB2_KEYBLOCK_FLAG_DEVELOPER_1; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0 + | VB2_KEYBLOCK_FLAG_DEVELOPER_1 + | VB2_KEYBLOCK_FLAG_MINIOS_0; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Keyblock dev flag mismatch"); ResetMocks(); - kbh.keyblock_flags = - VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_0; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_0; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Keyblock rec flag mismatch"); ResetMocks(); + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_1; + TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, + "Keyblock minios flag mismatch"); + + ResetMocks(); ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; - kbh.keyblock_flags = - VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_1; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_1 + | VB2_KEYBLOCK_FLAG_MINIOS_0; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Keyblock recdev flag mismatch"); ResetMocks(); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_0; + TestLoadKernel(0, "Keyblock rec flag okay"); + + ResetMocks(); ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE; - kbh.keyblock_flags = - VB2_KEYBLOCK_FLAG_RECOVERY_1 | VB2_KEYBLOCK_FLAG_DEVELOPER_0; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_0; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Keyblock rec!dev flag mismatch"); ResetMocks(); + ctx->flags |= VB2_CONTEXT_RECOVERY_MODE | VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_1 + | VB2_KEYBLOCK_FLAG_MINIOS_0; + TestLoadKernel(0, "Keyblock recdev flag okay"); + + /* Check keyblock flags (dev mode + signed kernel required) */ + ResetMocks(); + ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1); + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_0; + TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, + "Keyblock dev flag mismatch (signed kernel required)"); + + ResetMocks(); + ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_0; + TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, + "Keyblock dev flag mismatch (signed kernel required)"); + + ResetMocks(); + ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY; + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0 + | VB2_KEYBLOCK_FLAG_DEVELOPER_0 + | VB2_KEYBLOCK_FLAG_MINIOS_1; + TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, + "Keyblock dev flag mismatch (signed kernel required)"); + + ResetMocks(); + ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1); + kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0 + | VB2_KEYBLOCK_FLAG_DEVELOPER_1 + | VB2_KEYBLOCK_FLAG_MINIOS_0; + TestLoadKernel(0, "Keyblock dev flag okay (signed kernel required)"); + + /* Check kernel key version */ + ResetMocks(); kbh.data_key.key_version = 1; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Keyblock kernel key rollback"); @@ -725,12 +493,12 @@ ResetMocks(); kbh.data_key.key_version = 1; - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; TestLoadKernel(0, "Key version ignored in dev mode"); ResetMocks(); kbh.data_key.key_version = 1; - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; TestLoadKernel(0, "Key version ignored in rec mode"); ResetMocks(); @@ -748,25 +516,49 @@ ResetMocks(); kph.kernel_version = 0; - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; TestLoadKernel(0, "Kernel version ignored in dev mode"); ResetMocks(); kph.kernel_version = 0; - ctx->flags |= VB2_CONTEXT_RECOVERY_MODE; + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; TestLoadKernel(0, "Kernel version ignored in rec mode"); + /* Check kernel version (dev mode + signed kernel required) */ + ResetMocks(); + kbh.data_key.key_version = 0; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1); + TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, + "Keyblock key version checked in dev mode " + "(signed kernel required)"); + + ResetMocks(); + kbh.data_key.key_version = 0; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; + fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY; + TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, + "Keyblock key version checked in dev mode " + "(signed kernel required)"); + /* Check developer key hash - bad */ ResetMocks(); - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH; fwmp->dev_key_hash[0]++; TestLoadKernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Fail keyblock dev fwmp hash"); + /* Check developer key hash - bad (recovery mode) */ + ResetMocks(); + *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY; + fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH; + fwmp->dev_key_hash[0]++; + TestLoadKernel(0, "Bad keyblock dev fwmp hash ignored in rec mode"); + /* Check developer key hash - good */ ResetMocks(); - ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; + *boot_mode = VB2_BOOT_MODE_DEVELOPER; fwmp->flags |= VB2_SECDATA_FWMP_DEV_USE_KEY_HASH; TestLoadKernel(0, "Good keyblock dev fwmp hash"); @@ -814,7 +606,7 @@ /* Check that EXTERNAL_GPT flag makes it down */ ResetMocks(); - lkp.boot_flags |= BOOT_FLAG_EXTERNAL_GPT; + disk_info.flags |= VB_DISK_FLAG_EXTERNAL_GPT; TestLoadKernel(0, "Succeed external GPT"); TEST_EQ(gpt_flag_external, 1, "GPT was external"); @@ -826,7 +618,6 @@ int main(void) { - ReadWriteGptTest(); InvalidParamsTest(); LoadKernelTest(); diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_clamshell_beep_tests.c vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_clamshell_beep_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_clamshell_beep_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_clamshell_beep_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,274 +0,0 @@ -/* Copyright (c) 2011 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. - * - * Tests for vboot_api_firmware - */ - -#include -#include -#include -#include - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2secdata.h" -#include "2sysincludes.h" -#include "crc32.h" -#include "host_common.h" -#include "load_kernel_fw.h" -#include "test_common.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" - -/* Expected results */ - -#define MAX_NOTE_EVENTS 10 -#define TIME_FUZZ 500 -#define KBD_READ_TIME 60 - -typedef struct { - uint16_t msec; - uint16_t freq; - int time; -} note_event_t; - -typedef struct { - const char *name; - uint32_t gbb_flags; - uint32_t keypress_key; - int keypress_at_count; - int num_events; - note_event_t notes[MAX_NOTE_EVENTS]; -} test_case_t; - -test_case_t test[] = { - - { "VbBootDeveloperSoundTest( fast )", - VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY, 0, 0, - 1, - { - {0, 0, 2000}, // off and return at 2 seconds - }}, - - { "VbBootDeveloperSoundTest( normal )", - 0, 0, 0, - 3, - { - {250, 400, 20000}, // first beep at 20 seconds - {250, 400, 20510}, // second beep shortly after - {0, 0, 30020}, // off and return at 30 seconds - }}, - - // Now with some keypresses - - { "VbBootDeveloperSoundTest( normal, Ctrl-D )", - 0, 4, 20400, // Ctrl-D between beeps - 2, - { - {250, 400, 20000}, // first beep at 20 seconds - {0, 0, 20400}, // sees Ctrl-D, sound off, return - }}, - - { "VbBootDeveloperSoundTest( normal, Ctrl-U not allowed )", - 0, 21, 10000, // Ctrl-U at 10 seconds - 5, - { - {120, 400, 10000}, // complains about Ctrl-U (one beep) - {120, 400, 10240}, // complains about Ctrl-U (two beeps) - {250, 400, 20000}, // starts first beep at 20 seconds - {250, 400, 20510}, // starts second beep - {0, 0, 30020}, // returns at 30 seconds + 360ms - }}, -}; - -/* Mock data */ -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static struct vb2_gbb_header gbb; -static uint32_t current_time; -static uint32_t current_ticks; -static int current_event; -static int max_events; -static int matched_events; -static int kbd_fire_at; -static uint32_t kbd_fire_key; -static note_event_t *expected_event; - -/* Audio open count, so we can reset it */ -extern int audio_open_count; - -/* Reset mock data (for use before each test) */ -static void ResetMocks(void) -{ - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - vb2_nv_init(ctx); - - sd = vb2_get_sd(ctx); - - ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP; - sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT; - - memset(&gbb, 0, sizeof(gbb)); - - current_ticks = 0; - current_time = 0; - - current_event = 0; - kbd_fire_at = 0; - kbd_fire_key = 0; - audio_open_count = 0; - - matched_events = 0; - max_events = 0; -} - -/****************************************************************************/ -/* Mocked verification functions */ -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -vb2_error_t vb2ex_commit_data(struct vb2_context *c) -{ - return VB2_SUCCESS; -} - -vb2_error_t VbExDiskGetInfo(VbDiskInfo** infos_ptr, uint32_t* count, - uint32_t disk_flags) -{ - return VB2_ERROR_UNKNOWN; -} - -vb2_error_t VbExDiskFreeInfo(VbDiskInfo* infos, - VbExDiskHandle_t preserve_handle) -{ - return VB2_SUCCESS; -} - -vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, - uint64_t lba_count, void* buffer) -{ - return VB2_ERROR_UNKNOWN; -} - -vb2_error_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, - uint64_t lba_count, const void* buffer) -{ - return VB2_ERROR_UNKNOWN; -} - -uint32_t VbExIsShutdownRequested(void) -{ - return 0; -} - -uint32_t VbExKeyboardRead(void) -{ - uint32_t tmp; - uint32_t now; - - vb2ex_msleep(KBD_READ_TIME); - now = current_time; - - if (kbd_fire_key && now >= kbd_fire_at) { - VB2_DEBUG("returning %d at %d msec\n", - kbd_fire_key, now); - tmp = kbd_fire_key; - kbd_fire_key = 0; - return tmp; - } - VB2_DEBUG("returning %d at %d msec\n", 0, now); - return 0; -} - -void vb2ex_msleep(uint32_t msec) -{ - current_ticks += msec; - current_time = current_ticks; - VB2_DEBUG("msec=%d at %d msec\n", msec, current_time); -} - -uint32_t vb2ex_mtime(void) -{ - return current_ticks; -} - -void vb2ex_beep(uint32_t msec, uint32_t frequency) -{ - VB2_DEBUG("msec=%d, frequency=%d at %d msec\n", - msec, frequency, current_time); - - if (current_event < max_events && - msec == expected_event[current_event].msec && - frequency == expected_event[current_event].freq && - (current_time - expected_event[current_event].time) < TIME_FUZZ) - matched_events++; - - if (msec) - vb2ex_msleep(msec); - current_event++; -} - -vb2_error_t VbExDisplayScreen(uint32_t screen_type, uint32_t locale, - const VbScreenData *data) -{ - switch (screen_type) { - case VB_SCREEN_BLANK: - VB2_DEBUG("screen_type=BLANK\n"); - break; - case VB_SCREEN_DEVELOPER_WARNING: - VB2_DEBUG("screen_type=DEV\n"); - break; - case VB_SCREEN_RECOVERY_INSERT: - VB2_DEBUG("screen_type=INSERT\n"); - break; - case VB_SCREEN_RECOVERY_NO_GOOD: - VB2_DEBUG("screen_type=NO_GOOD\n"); - break; - case VB_SCREEN_OS_BROKEN: - VB2_DEBUG("screen_type=BROKEN\n"); - break; - default: - VB2_DEBUG("screen_type=%#x\n", screen_type); - } - - VB2_DEBUG("current_time is %d msec\n", current_time); - - return VB2_SUCCESS; -} - -/****************************************************************************/ - -static void VbBootDeveloperSoundTest(void) -{ - int i; - int num_tests = sizeof(test) / sizeof(test_case_t); - - for (i = 0; i < num_tests; i++) { - VB2_DEBUG("STARTING %s ...\n", test[i].name); - ResetMocks(); - gbb.flags = test[i].gbb_flags; - kbd_fire_key = test[i].keypress_key; - kbd_fire_at = test[i].keypress_at_count; - max_events = test[i].num_events; - expected_event = test[i].notes; - VbBootDeveloperLegacyClamshell(ctx); - vb2ex_beep(0, 0); /* Dummy call to determine end time */ - VB2_DEBUG("INFO: matched %d total %d expected %d\n", - matched_events, current_event, test[i].num_events); - TEST_TRUE(matched_events == test[i].num_events && - current_event == test[i].num_events, test[i].name); - } -} - -int main(int argc, char* argv[]) -{ - VbBootDeveloperSoundTest(); - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_clamshell_tests.c vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_clamshell_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_clamshell_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_clamshell_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1655 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Tests for vboot_api_kernel, part 2 - */ - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2secdata.h" -#include "2secdata_struct.h" -#include "host_common.h" -#include "load_kernel_fw.h" -#include "test_common.h" -#include "tss_constants.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#include "vboot_test.h" -#include "vboot_ui_legacy.h" - -/* Mock data */ -static LoadKernelParams lkp; -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static struct vb2_gbb_header gbb; -static struct vb2_secdata_fwmp *fwmp; - -static int audio_looping_calls_left; -static uint32_t vbtlk_retval; -static int vbtlk_expect_fixed; -static int vbtlk_expect_removable; -static int vbexlegacy_called; -static enum VbAltFwIndex_t altfw_num; -static uint32_t current_ticks; -static int trust_ec; -static int virtdev_set; -static uint32_t virtdev_fail; -static uint32_t mock_keypress[16]; -static uint32_t mock_keyflags[8]; -static uint32_t mock_keypress_count; - -#define GPIO_SHUTDOWN 1 -#define GPIO_PRESENCE 2 -#define GPIO_LID_CLOSED 4 -typedef struct GpioState { - uint32_t gpio_flags; - uint32_t count; -} GpioState; -struct GpioState mock_gpio[8]; -static uint32_t mock_gpio_count; - -static uint32_t screens_displayed[8]; -static uint32_t screens_count = 0; -static uint32_t mock_num_disks[8]; -static uint32_t mock_num_disks_count; -static int tpm_set_mode_called; -static enum vb2_tpm_mode tpm_mode; - -/* Extra character to guarantee null termination. */ -static char set_vendor_data[VENDOR_DATA_LENGTH + 2]; -static int set_vendor_data_called; - -/* - * Mocks the assertion of 1 or more gpios in |gpio_flags| for 100 ticks after - * an optional |ticks| delay. - */ -static void MockGpioAfter(uint32_t ticks, uint32_t gpio_flags) -{ - uint32_t index = 0; - if (ticks > 0) - mock_gpio[index++].count = ticks - 1; - - mock_gpio[index].gpio_flags = gpio_flags; - mock_gpio[index].count = 100; -} - -/* Reset mock data (for use before each test) */ -static void ResetMocks(void) -{ - vb2_reset_power_button(); - - memset(&lkp, 0, sizeof(lkp)); - - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - vb2_nv_init(ctx); - - sd = vb2_get_sd(ctx); - sd->flags |= VB2_SD_FLAG_DISPLAY_AVAILABLE; - - /* CRC will be invalid after here, but nobody's checking */ - sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT; - fwmp = (struct vb2_secdata_fwmp *)ctx->secdata_fwmp; - - memset(&gbb, 0, sizeof(gbb)); - - audio_looping_calls_left = 30; - vbtlk_retval = VB2_ERROR_MOCK; - vbtlk_expect_fixed = 0; - vbtlk_expect_removable = 0; - vbexlegacy_called = 0; - altfw_num = -100; - current_ticks = 0; - trust_ec = 0; - virtdev_set = 0; - virtdev_fail = 0; - set_vendor_data_called = 0; - - memset(screens_displayed, 0, sizeof(screens_displayed)); - screens_count = 0; - - memset(mock_keypress, 0, sizeof(mock_keypress)); - memset(mock_keyflags, 0, sizeof(mock_keyflags)); - mock_keypress_count = 0; - memset(mock_gpio, 0, sizeof(mock_gpio)); - mock_gpio_count = 0; - memset(mock_num_disks, 0, sizeof(mock_num_disks)); - mock_num_disks_count = 0; - - tpm_set_mode_called = 0; - tpm_mode = VB2_TPM_MODE_ENABLED_TENTATIVE; -} - -/* Mock functions */ - -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -uint32_t VbExIsShutdownRequested(void) -{ - uint32_t result = 0; - if (mock_gpio_count >= ARRAY_SIZE(mock_gpio)) - return 0; - if (mock_gpio[mock_gpio_count].gpio_flags & GPIO_SHUTDOWN) - result |= VB_SHUTDOWN_REQUEST_POWER_BUTTON; - if (mock_gpio[mock_gpio_count].gpio_flags & GPIO_LID_CLOSED) - result |= VB_SHUTDOWN_REQUEST_LID_CLOSED; - if (mock_gpio[mock_gpio_count].count > 0) { - --mock_gpio[mock_gpio_count].count; - } else { - ++mock_gpio_count; - } - return result; -} - -uint32_t VbExKeyboardRead(void) -{ - return VbExKeyboardReadWithFlags(NULL); -} - -uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags) -{ - if (mock_keypress_count < ARRAY_SIZE(mock_keypress)) { - if (key_flags != NULL && - mock_keypress_count < ARRAY_SIZE(mock_keyflags)) - *key_flags = mock_keyflags[mock_keypress_count]; - return mock_keypress[mock_keypress_count++]; - } else - return 0; -} - -int vb2ex_physical_presence_pressed(void) -{ - uint32_t result = 0; - - if (mock_gpio_count >= ARRAY_SIZE(mock_gpio)) - return 0; - - if ((mock_gpio[mock_gpio_count].gpio_flags & GPIO_PRESENCE)) - result = 1; - - if (mock_gpio[mock_gpio_count].count > 0) - --mock_gpio[mock_gpio_count].count; - else - ++mock_gpio_count; - - return result; -} - -vb2_error_t VbExLegacy(enum VbAltFwIndex_t _altfw_num) -{ - vbexlegacy_called++; - altfw_num = _altfw_num; - - /* VbExLegacy() can only return failure, or not return at all. */ - return VB2_ERROR_UNKNOWN; -} - -void vb2ex_msleep(uint32_t msec) -{ - current_ticks += msec; -} - -uint32_t vb2ex_mtime(void) -{ - return current_ticks; -} - -vb2_error_t VbExDiskGetInfo(VbDiskInfo **infos_ptr, uint32_t *count, - uint32_t disk_flags) -{ - if (mock_num_disks_count < ARRAY_SIZE(mock_num_disks)) { - if (mock_num_disks[mock_num_disks_count] == -1) - return VB2_ERROR_MOCK; - else - *count = mock_num_disks[mock_num_disks_count++]; - } else { - *count = 0; - } - return VB2_SUCCESS; -} - -vb2_error_t VbExDiskFreeInfo(VbDiskInfo *infos, - VbExDiskHandle_t preserve_handle) -{ - return VB2_SUCCESS; -} - -int vb2ex_ec_trusted(void) -{ - return trust_ec; -} - -int vb2_audio_looping(void) -{ - if (audio_looping_calls_left == 0) - return 0; - else if (audio_looping_calls_left > 0) - audio_looping_calls_left--; - - return 1; -} - -vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags) -{ - /* - * TODO: Currently we don't have a good way of testing for an ordered - * sequence of VB_DISK_FLAG_FIXED and then VB_DISK_FLAG_REMOVABLE. If - * both are set, then just assume success. - */ - if (vbtlk_expect_fixed && vbtlk_expect_removable) - return vbtlk_retval; - - TEST_EQ(!!vbtlk_expect_fixed, - !!(get_info_flags & VB_DISK_FLAG_FIXED), - " VbTryLoadKernel unexpected fixed disk call"); - TEST_EQ(!!vbtlk_expect_removable, - !!(get_info_flags & VB_DISK_FLAG_REMOVABLE), - " VbTryLoadKernel unexpected removable disk call"); - - return vbtlk_retval; -} - -vb2_error_t VbDisplayScreen(struct vb2_context *c, uint32_t screen, int force, - const VbScreenData *data) -{ - if (screens_count < ARRAY_SIZE(screens_displayed)) - screens_displayed[screens_count++] = screen; - - return VB2_SUCCESS; -} - -void vb2_enable_developer_mode(struct vb2_context *c) -{ - VB2_ASSERT(!virtdev_fail); - virtdev_set = 1; -} - -vb2_error_t VbExSetVendorData(const char *vendor_data_value) -{ - set_vendor_data_called = 1; - /* - * set_vendor_data is a global variable, so it is automatically - * initialized to zero, and so the -1 will ensure the string is null - * terminated. - */ - strncpy(set_vendor_data, vendor_data_value, sizeof(set_vendor_data) - 1); - - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_tpm_set_mode(enum vb2_tpm_mode mode_val) -{ - tpm_set_mode_called = 1; - - /* Fail if the TPM is already disabled. */ - if (tpm_mode == VB2_TPM_MODE_DISABLED) - return VB2_ERROR_UNKNOWN; - - tpm_mode = mode_val; - return VB2_SUCCESS; -} - -/* Tests */ - -/* - * Helper function to test VbUserConfirms against a sequence of gpio events. - * caller specifies a sequence of gpio events and the expected confirm vs. - * reboot result. - * - * Non-asserted gpios are used for 5 events, then 'first' for 5 events, - * 'second' for 5 events, and 'third' for 5 events. - * Typically most tests want 5 events of each type (so they'll specify 0 for - * 'first' and use 'second' through 'fourth'), but a few tests want the - * shutdown event to be seen once. - */ -static void VbUserConfirmsTestGpio(uint32_t first, uint32_t second, - uint32_t third, uint32_t confirm, - const char *msg) -{ - ResetMocks(); - mock_gpio[0].gpio_flags = 0; - mock_gpio[0].count = 4; - mock_gpio[1].gpio_flags = first; - mock_gpio[1].count = 4; - mock_gpio[2].gpio_flags = second; - mock_gpio[2].count = 4; - mock_gpio[3].gpio_flags = third; - mock_gpio[3].count = 4; - if (confirm) { - TEST_EQ(VbUserConfirms(ctx, - VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD), - 1, msg); - } else { - TEST_EQ(VbUserConfirms(ctx, - VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD), - -1, msg); - } -} - -static void VbUserConfirmsKeyboardTest(void) -{ - VB2_DEBUG("Testing VbUserConfirms()...\n"); - - ResetMocks(); - MockGpioAfter(1, GPIO_SHUTDOWN); - TEST_EQ(VbUserConfirms(ctx, 0), -1, "Shutdown requested"); - - ResetMocks(); - mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbUserConfirms(ctx, 0), -1, "Shutdown requested"); - - ResetMocks(); - mock_keypress[0] = VB_KEY_ENTER; - TEST_EQ(VbUserConfirms(ctx, 0), 1, "Enter"); - - ResetMocks(); - mock_keypress[0] = VB_KEY_ESC; - TEST_EQ(VbUserConfirms(ctx, 0), 0, "Esc"); - - ResetMocks(); - mock_keypress[0] = ' '; - MockGpioAfter(1, GPIO_SHUTDOWN); - TEST_EQ(VbUserConfirms(ctx, VB_CONFIRM_SPACE_MEANS_NO), 0, - "Space means no"); - - ResetMocks(); - mock_keypress[0] = ' '; - MockGpioAfter(1, GPIO_SHUTDOWN); - TEST_EQ(VbUserConfirms(ctx, 0), -1, "Space ignored"); - - ResetMocks(); - mock_keypress[0] = VB_KEY_ENTER; - mock_keyflags[0] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - TEST_EQ(VbUserConfirms(ctx, VB_CONFIRM_MUST_TRUST_KEYBOARD), - 1, "Enter with trusted keyboard"); - - ResetMocks(); - mock_keypress[0] = VB_KEY_ENTER; /* untrusted */ - mock_keypress[1] = ' '; - TEST_EQ(VbUserConfirms(ctx, - VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD), - 0, "Untrusted keyboard"); - - ResetMocks(); - mock_keypress[0] = VB_KEY_ENTER; - mock_keypress[1] = 'y'; - mock_keypress[2] = 'z'; - mock_keypress[3] = ' '; - mock_gpio[0].gpio_flags = GPIO_PRESENCE; - mock_gpio[0].count = ~0; - TEST_EQ(VbUserConfirms(ctx, - VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD), - 0, "Recovery button stuck"); - - VB2_DEBUG("...done.\n"); -} - -static void VbUserConfirmsPhysicalPresenceTest(void) -{ - ResetMocks(); - MockGpioAfter(0, GPIO_PRESENCE); - TEST_EQ(VbUserConfirms(ctx, - VB_CONFIRM_SPACE_MEANS_NO | - VB_CONFIRM_MUST_TRUST_KEYBOARD), - 1, "Presence button"); - - /* - * List of possiblities for shutdown and physical presence events that - * occur over time. Time advanced from left to right (where each - * represents the gpio[s] that are seen during a given iteration of - * the loop). The meaning of the characters: - * - * _ means no gpio - * s means shutdown gpio - * p means presence gpio - * B means both shutdown and presence gpio - * - * 1: ______ppp______ -> confirm - * 2: ______sss______ -> shutdown - * 3: ___pppsss______ -> confirm - * 4: ___sssppp______ -> shutdown - * 5: ___pppBBB______ -> confirm - * 6: ___pppBBBppp___ -> shutdown - * 7: ___pppBBBsss___ -> confirm - * 8: ___sssBBB______ -> confirm - * 9: ___sssBBBppp___ -> shutdown - * 10: ___sssBBBsss___ -> confirm - * 11: ______BBB______ -> confirm - * 12: ______BBBsss___ -> confirm - * 13: ______BBBppp___ -> shutdown - */ - - /* 1: presence means confirm */ - VbUserConfirmsTestGpio(GPIO_PRESENCE, 0, 0, 1, "presence"); - - /* 2: shutdown means shutdown */ - VbUserConfirmsTestGpio(GPIO_SHUTDOWN, 0, 0, 0, "shutdown"); - - /* 3: presence then shutdown means confirm */ - VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_SHUTDOWN, 0, 1, - "presence then shutdown"); - - /* 4: shutdown then presence means shutdown */ - VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE, 0, 0, - "shutdown then presence"); - - /* 5: presence then shutdown+presence then none mean confirm */ - VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, - 0, 1, "presence, both, none"); - - /* 6: presence then shutdown+presence then presence means shutdown */ - VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_PRESENCE, 0, "presence, both, presence"); - - /* 7: presence then shutdown+presence then shutdown means confirm */ - VbUserConfirmsTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_SHUTDOWN, 1, "presence, both, shutdown"); - - /* 8: shutdown then shutdown+presence then none means confirm */ - VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, - 0, 1, "shutdown, both, none"); - - /* 9: shutdown then shutdown+presence then presence means shutdown */ - VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_PRESENCE, 0, "shutdown, both, presence"); - - /* 10: shutdown then shutdown+presence then shutdown means confirm */ - VbUserConfirmsTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_SHUTDOWN, 1, "shutdown, both, shutdown"); - - /* 11: shutdown+presence then none means confirm */ - VbUserConfirmsTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 0, 1, - "both"); - - /* 12: shutdown+presence then shutdown means confirm */ - VbUserConfirmsTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_SHUTDOWN, 0, 1, "both, shutdown"); - - /* 13: shutdown+presence then presence means shutdown */ - VbUserConfirmsTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_PRESENCE, 0, 0, "both, presence"); - -} - -static void VbBootDevTest(void) -{ - int key; - - VB2_DEBUG("Testing VbBootDeveloperLegacyClamshell()...\n"); - - /* Proceed after timeout */ - ResetMocks(); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, - " warning screen"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - - /* Proceed to legacy after timeout if GBB flag set */ - ResetMocks(); - gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY | - VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - - /* Proceed to legacy after timeout if GBB flag set */ - ResetMocks(); - gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY | - VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - - /* Proceed to legacy after timeout if boot legacy and default boot - legacy are set */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - - /* Proceed to legacy boot mode only if enabled */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Proceed to external disk after timeout if boot external and default - * boot external are set */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vbtlk_retval = VB2_SUCCESS; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U external"); - - /* Proceed to external boot mode only if enabled */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Timeout"); - - /* If no external tries fixed disk */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - vbtlk_expect_fixed = 1; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+U enabled"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Up arrow is uninteresting / passed to VbCheckDisplayKey() */ - ResetMocks(); - mock_keypress[0] = VB_KEY_UP; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Up arrow"); - - /* Shutdown requested in loop */ - ResetMocks(); - mock_gpio[0].gpio_flags = 0; - mock_gpio[0].count = 2; - mock_gpio[1].gpio_flags = GPIO_SHUTDOWN; - mock_gpio[1].count = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - - /* Shutdown requested by keyboard in loop */ - ResetMocks(); - mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested by keyboard"); - - /* Space asks to disable virtual dev switch */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = ' '; - mock_keypress[1] = VB_KEY_ENTER; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Space = tonorm"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, - " tonorm screen"); - TEST_EQ(screens_displayed[2], VB_SCREEN_TO_NORM_CONFIRMED, - " confirm screen"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - - /* Space-space doesn't disable it */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = ' '; - mock_keypress[1] = ' '; - mock_keypress[2] = VB_KEY_ESC; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Space-space"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, - " tonorm screen"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING, - " warning screen"); - - /* Enter doesn't by default */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = VB_KEY_ENTER; - mock_keypress[1] = VB_KEY_ENTER; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter ignored"); - - /* Enter does if GBB flag set */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - gbb.flags |= VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM; - mock_keypress[0] = VB_KEY_ENTER; - mock_keypress[1] = VB_KEY_ENTER; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter = tonorm"); - - /* Tonorm ignored if GBB forces dev switch on */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON; - mock_keypress[0] = ' '; - mock_keypress[1] = VB_KEY_ENTER; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Can't tonorm gbb-dev"); - - /* Shutdown requested at tonorm screen */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = ' '; - MockGpioAfter(3, GPIO_SHUTDOWN); - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested at tonorm"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, - " tonorm screen"); - - /* Shutdown requested by keyboard at tonorm screen */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested by keyboard at nonorm"); - - /* Ctrl+D dismisses warning */ - ResetMocks(); - mock_keypress[0] = VB_KEY_CTRL('D'); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Ctrl+D"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Ctrl+D doesn't boot legacy even if GBB flag is set */ - ResetMocks(); - mock_keypress[0] = VB_KEY_CTRL('D'); - gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, "Ctrl+D"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Ctrl+L tries legacy boot mode only if enabled */ - ResetMocks(); - mock_keypress[0] = VB_KEY_CTRL('L'); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L normal"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Enter altfw menu and time out */ - ResetMocks(); - MockGpioAfter(1000, GPIO_SHUTDOWN); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - mock_keypress[0] = VB_KEY_CTRL('L'); - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_SHUTDOWN, - "Ctrl+L force legacy"); - TEST_EQ(vbexlegacy_called, 0, " try legacy"); - - /* Enter altfw menu and select firmware 0 */ - ResetMocks(); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = '0'; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L force legacy"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - - /* Enter altfw menu and then exit it */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = VB_KEY_ESC; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L nv legacy"); - TEST_EQ(vbexlegacy_called, 0, " try legacy"); - - /* Enter altfw menu and select firmware 0 */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = '0'; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L nv legacy"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - - /* Enter altfw menu and select firmware 0 */ - ResetMocks(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY; - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = '0'; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L fwmp legacy"); - TEST_EQ(vbexlegacy_called, 1, " fwmp legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - - /* Pressing 1-9 boots alternative firmware only if enabled */ - for (key = '1'; key <= '9'; key++) { - ResetMocks(); - mock_keypress[0] = key; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "'1' normal"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - ResetMocks(); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - mock_keypress[0] = key; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L force legacy"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, key - '0', " check altfw_num"); - - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - mock_keypress[0] = key; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L nv legacy"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, key - '0', " check altfw_num"); - - ResetMocks(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY; - mock_keypress[0] = key; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+L fwmp legacy"); - TEST_EQ(vbexlegacy_called, 1, " fwmp legacy"); - TEST_EQ(altfw_num, key - '0', " check altfw_num"); - } - - /* Ctrl+U boots external only if enabled */ - ResetMocks(); - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+U normal"); - - /* Ctrl+U enabled, with good external boot */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_retval = VB2_SUCCESS; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U external"); - - /* Ctrl+U enabled via GBB */ - ResetMocks(); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB; - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_retval = VB2_SUCCESS; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U force external"); - - /* Ctrl+U enabled via FWMP */ - ResetMocks(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL; - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_retval = VB2_SUCCESS; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), 0, "Ctrl+U force external"); - - /* If no external disk, eventually times out and tries internal disk */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_KEY_CTRL('U'); - /* TODO: Currently the test suite has no way of specifying the order in - which the expected VbTryLoadKernel calls occur. */ - vbtlk_expect_fixed = 1; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Ctrl+U enabled"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - - /* If dev mode is disabled, goes to TONORM screen repeatedly */ - ResetMocks(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - mock_keypress[0] = VB_KEY_ESC; /* Just causes TONORM again */ - mock_keypress[1] = VB_KEY_ENTER; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "FWMP dev disabled"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM, - " tonorm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM, - " tonorm screen"); - TEST_EQ(screens_displayed[2], VB_SCREEN_TO_NORM_CONFIRMED, - " confirm screen"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - - /* Shutdown requested when dev disabled */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - MockGpioAfter(1, GPIO_SHUTDOWN); - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested when dev disabled"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM, - " tonorm screen"); - - /* Shutdown requested by keyboard when dev disabled */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_DEV_MODE_ENABLED; - fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested by keyboard when dev disabled"); - - VB2_DEBUG("...done.\n"); -} - -static void VbBootDevVendorDataTest(void) -{ - /* Enter set vendor data and reboot */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '3'; - mock_keypress[3] = '2'; - mock_keypress[4] = '1'; - mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[6] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data, don't confirm, esc"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); - - /* Enter set vendor data; don't confirm and esc */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '3'; - mock_keypress[3] = '2'; - mock_keypress[4] = '1'; - mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[6] = VB_KEY_RIGHT; /* Select NO */ - mock_keypress[7] = VB_KEY_ENTER; /* Do not confirm vendor data */ - mock_keypress[8] = VB_KEY_ESC; /* Escape to boot */ - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter set vendor data, don't confirm, esc"); - TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); - - /* Enter set vendor data; esc, don't confirm, and change last character */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '3'; - mock_keypress[3] = '2'; - mock_keypress[4] = '1'; - mock_keypress[5] = VB_KEY_ENTER; - mock_keypress[6] = VB_KEY_RIGHT; /* Select NO */ - mock_keypress[7] = VB_KEY_ENTER; /* Do not confirm vendor data */ - mock_keypress[8] = VB_KEY_BACKSPACE; /* Remove last character */ - mock_keypress[9] = 'B'; - mock_keypress[10] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[11] = VB_KEY_ENTER; /* Confirm vendor data */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data esc, don't confirm, change last character"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "432B", " Vendor data correct"); - - /* Enter set vendor data; extra keys ignored */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '3'; - mock_keypress[3] = '2'; - mock_keypress[4] = '1'; - mock_keypress[5] = '5'; - mock_keypress[6] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[7] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data extra keys ignored"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); - - /* Enter set vendor data; converts case */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = 'a'; - mock_keypress[2] = 'B'; - mock_keypress[3] = 'Y'; - mock_keypress[4] = 'z'; - mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[6] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data converts case"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "ABYZ", " Vendor data correct"); - - /* Enter set vendor data; backspace works */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = 'A'; - mock_keypress[2] = 'B'; - mock_keypress[3] = 'C'; - mock_keypress[4] = VB_KEY_BACKSPACE; - mock_keypress[5] = VB_KEY_BACKSPACE; - mock_keypress[6] = '3'; - mock_keypress[7] = '2'; - mock_keypress[8] = '1'; - mock_keypress[9] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[10] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data backspace works"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "A321", " Vendor data correct"); - - /* Enter set vendor data; invalid chars don't print */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '-'; - mock_keypress[3] = '^'; - mock_keypress[4] = '&'; - mock_keypress[5] = '$'; - mock_keypress[6] = '.'; - mock_keypress[7] = '3'; - mock_keypress[8] = '2'; - mock_keypress[9] = '1'; - mock_keypress[10] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[11] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data invalid chars don't print"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); - - /* Enter set vendor data; invalid chars don't print with backspace */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '-'; - mock_keypress[3] = VB_KEY_BACKSPACE; /* Should delete 4 */ - mock_keypress[4] = '3'; - mock_keypress[5] = '2'; - mock_keypress[6] = '1'; - mock_keypress[7] = '0'; - mock_keypress[8] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[9] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data invalid chars don't print with backspace"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "3210", " Vendor data correct"); - - /* Enter set vendor data; backspace only doesn't underrun */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = 'A'; - mock_keypress[2] = VB_KEY_BACKSPACE; - mock_keypress[3] = VB_KEY_BACKSPACE; - mock_keypress[4] = '4'; - mock_keypress[5] = '3'; - mock_keypress[6] = '2'; - mock_keypress[7] = '1'; - mock_keypress[8] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[9] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data backspace only doesn't underrun"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "4321", " Vendor data correct"); - - /* Enter set vendor data; vowels not allowed after first char */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = 'A'; - mock_keypress[2] = 'A'; - mock_keypress[3] = 'B'; - mock_keypress[4] = 'E'; - mock_keypress[5] = 'i'; - mock_keypress[6] = 'C'; - mock_keypress[7] = 'O'; - mock_keypress[8] = 'u'; - mock_keypress[9] = 'D'; - mock_keypress[10] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[11] = VB_KEY_ENTER; /* Confirm vendor data (Default YES) */ - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Enter set vendor data vowels not allowed after first char"); - TEST_EQ(set_vendor_data_called, 1, " VbExSetVendorData() called"); - TEST_STR_EQ(set_vendor_data, "ABCD", " Vendor data correct"); - - /* Enter set vendor data; too short */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '1'; - mock_keypress[2] = '2'; - mock_keypress[3] = '3'; - /* Set vendor data (nothing happens) */ - mock_keypress[4] = VB_KEY_ENTER; - /* Confirm vendor data (nothing happens) */ - mock_keypress[5] = VB_KEY_ENTER; - mock_keypress[6] = VB_KEY_ESC; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter set vendor data too short"); - TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); - - /* Enter set vendor data; esc from set screen */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = VB_KEY_ESC; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter set vendor data esc from set screen"); - TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); - - /* Enter set vendor data; esc from set screen with tag */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '3'; - mock_keypress[3] = '2'; - mock_keypress[4] = '1'; - mock_keypress[5] = VB_KEY_ESC; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter set vendor data esc from set screen with tag"); - TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); - - /* Enter set vendor data; esc from confirm screen */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ENTER; /* Enter vendor data setting */ - mock_keypress[1] = '4'; - mock_keypress[2] = '3'; - mock_keypress[3] = '2'; - mock_keypress[4] = '1'; - mock_keypress[5] = VB_KEY_ENTER; /* Set vendor data */ - mock_keypress[6] = VB_KEY_ESC; - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter set vendor data esc from set screen"); - TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); - - /* Escape from vendor data warning screen */ - ResetMocks(); - ctx->flags |= VB2_CONTEXT_VENDOR_DATA_SETTABLE; - mock_keypress[0] = VB_KEY_ESC; /* Enter vendor data setting */ - vbtlk_expect_fixed = 1; - TEST_EQ(VbBootDeveloperLegacyClamshell(ctx), VB2_ERROR_MOCK, - "Enter set vendor data esc, don't confirm, change last character"); - TEST_EQ(set_vendor_data_called, 0, " VbExSetVendorData() not called"); - - VB2_DEBUG("...done.\n"); -} - -/* - * Helper function to test VbBootRecovery against a sequence of gpio events. - * caller specifies a sequence of gpio events and the expected confirm vs. - * reboot result. - * - * Non-asserted gpios are used for 5 events, then 'first' for 5 events, - * 'second' for 5 events, and 'third' for 5 events. - */ -static void VbBootRecTestGpio(uint32_t first, uint32_t second, uint32_t third, - uint32_t confirm, const char *msg) -{ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - trust_ec = 1; - mock_keypress[0] = VB_KEY_CTRL('D'); - mock_gpio[0].gpio_flags = 0; - mock_gpio[0].count = 4; - mock_gpio[1].gpio_flags = first; - mock_gpio[1].count = 4; - mock_gpio[2].gpio_flags = second; - mock_gpio[2].count = 4; - mock_gpio[3].gpio_flags = third; - mock_gpio[3].count = 4; - vbtlk_expect_removable = 1; - - if (confirm) { - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_REBOOT_EC_TO_RO, msg); - TEST_EQ(virtdev_set, 1, " virtual dev mode on"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL), - !!BOOT_EXTERNAL_ON_DEV, - " NV_DEV_BOOT_EXTERNAL enabled"); - } else { - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, msg); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - } -} - -static void VbBootRecTest(void) -{ - VB2_DEBUG("Testing VbBootRecoveryLegacyClamshell()...\n"); - - /* Shutdown requested in loop */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested"); - - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - - /* Shutdown requested by keyboard */ - ResetMocks(); - mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Shutdown requested by keyboard"); - - /* Ignore power button held on boot */ - ResetMocks(); - mock_gpio[0].gpio_flags = GPIO_SHUTDOWN; - mock_gpio[0].count = 10; - mock_gpio[1].gpio_flags = 0; - mock_gpio[1].count = 10; - mock_gpio[2].gpio_flags = GPIO_SHUTDOWN; - mock_gpio[2].count = 10; - mock_gpio[3].gpio_flags = 0; - mock_gpio[3].count = 100; - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - trust_ec = 1; - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ignore power button held on boot"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - /* Shutdown should happen while we're sending the 2nd block of events */ - - /* Broken screen */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_num_disks[0] = 1; - mock_num_disks[1] = 1; - mock_num_disks[2] = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Broken"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - - /* Broken screen even if dev switch is on */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_num_disks[0] = 1; - mock_num_disks[1] = 1; - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Broken (dev)"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - - /* Force insert screen with GBB flag */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - gbb.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Insert (forced by GBB)"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - - /* No removal if recovery button physically pressed */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_num_disks[0] = 1; - mock_num_disks[1] = 1; - sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "No remove in rec"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - - /* Removal if no disk initially found, but found on second attempt */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_num_disks[0] = 0; - mock_num_disks[1] = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Remove"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - - /* Bad disk count doesn't require removal */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_num_disks[0] = -1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Bad disk count"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - - /* Ctrl+D ignored for many reasons... */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_keypress[0] = VB_KEY_CTRL('D'); - trust_ec = 0; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+D ignored if EC not trusted"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, - " todev screen"); - - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY | VB2_SD_FLAG_DEV_MODE_ENABLED; - trust_ec = 1; - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_keypress[0] = VB_KEY_CTRL('D'); - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+D ignored if already in dev mode"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, - " todev screen"); - - ResetMocks(); - trust_ec = 1; - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_keypress[0] = VB_KEY_CTRL('D'); - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+D ignored if recovery not manually triggered"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, - " todev screen"); - - /* Ctrl+D then space means don't enable */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - MockGpioAfter(2, GPIO_SHUTDOWN); - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - trust_ec = 1; - mock_keypress[0] = VB_KEY_CTRL('D'); - mock_keypress[1] = ' '; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+D todev abort"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, - " todev screen"); - TEST_EQ(screens_displayed[2], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - - /* Ctrl+D then enter means enable */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - MockGpioAfter(10, GPIO_SHUTDOWN); - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - trust_ec = 1; - mock_keypress[0] = VB_KEY_CTRL('D'); - mock_keypress[1] = VB_KEY_ENTER; - mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_REBOOT_EC_TO_RO, - "Ctrl+D todev confirm via enter"); - TEST_EQ(virtdev_set, 1, " virtual dev mode on"); - - /* Don't handle TPM error in enabling dev mode */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - MockGpioAfter(10, GPIO_SHUTDOWN); - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - trust_ec = 1; - mock_keypress[0] = VB_KEY_CTRL('D'); - mock_keypress[1] = VB_KEY_ENTER; - mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - virtdev_fail = 1; - vbtlk_expect_removable = 1; - TEST_ABORT(VbBootRecoveryLegacyClamshell(ctx), - "Ctrl+D todev failure"); - TEST_EQ(virtdev_set, 0, " virtual dev mode still off"); - - /* Test Diagnostic Mode via Ctrl-C - display available */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - trust_ec = 1; - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_keypress[0] = VB_KEY_CTRL('C'); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0, - "todiag is zero"); - vbtlk_expect_removable = 1; - if (DIAGNOSTIC_UI) - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_REBOOT, - "Ctrl+C todiag - enabled"); - else - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+C todiag - disabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), DIAGNOSTIC_UI, - " todiag is updated for Ctrl-C"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0, - " todiag doesn't set unneeded DISPLAY_REQUEST"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - - /* Test Diagnostic Mode via F12 - display disabled */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - sd->flags &= ~VB2_SD_FLAG_DISPLAY_AVAILABLE; - trust_ec = 1; - vbtlk_retval = VB2_ERROR_LK_NO_DISK_FOUND; - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_keypress[0] = VB_KEY_F(12); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0, - "todiag is zero"); - vbtlk_expect_removable = 1; - if (DIAGNOSTIC_UI) - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_REBOOT, - "F12 todiag - enabled"); - else - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "F12 todiag - disabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), DIAGNOSTIC_UI, - " todiag is updated for F12"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0, - " todiag doesn't set unneeded DISPLAY_REQUEST"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - - /* Test Diagnostic Mode via Ctrl-C OS broken - display available */ - ResetMocks(); - MockGpioAfter(10, GPIO_SHUTDOWN); - mock_keypress[0] = VB_KEY_CTRL('C'); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), 0, - "todiag is zero"); - if (DIAGNOSTIC_UI) - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_REBOOT, - "Ctrl+C todiag os broken - enabled"); - else - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+C todiag os broken - disabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST), DIAGNOSTIC_UI, - " todiag is updated for Ctrl-C"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST), 0, - " todiag doesn't set unneeded DISPLAY_REQUEST"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " os broken screen"); - - VB2_DEBUG("...done.\n"); -} - -static void VbBootRecPhysicalPresenceTest(void) -{ - - /* Ctrl+D ignored because the physical presence switch is still pressed - and we don't like that. */ - ResetMocks(); - sd->flags = VB2_SD_FLAG_MANUAL_RECOVERY; - trust_ec = 1; - mock_keypress[0] = VB_KEY_CTRL('D'); - mock_gpio[0].gpio_flags = GPIO_PRESENCE; - mock_gpio[0].count = 100; - mock_gpio[1].gpio_flags = GPIO_PRESENCE | GPIO_SHUTDOWN; - mock_gpio[1].count = 100; - vbtlk_expect_removable = 1; - TEST_EQ(VbBootRecoveryLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, - "Ctrl+D ignored if phys pres button is still pressed"); - TEST_NEQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV, - " todev screen"); - - /* - * List of possiblities for shutdown and physical presence events that - * occur over time. Time advanced from left to right (where each - * represents the gpio[s] that are seen during a given iteration of - * the loop). The meaning of the characters: - * - * _ means no gpio - * s means shutdown gpio - * p means presence gpio - * B means both shutdown and presence gpio - * - * 1: ______ppp______ -> confirm - * 2: ______sss______ -> shutdown - * 3: ___pppsss______ -> confirm - * 4: ___sssppp______ -> shutdown - * 5: ___pppBBB______ -> confirm - * 6: ___pppBBBppp___ -> shutdown - * 7: ___pppBBBsss___ -> confirm - * 8: ___sssBBB______ -> confirm - * 9: ___sssBBBppp___ -> shutdown - * 10: ___sssBBBsss___ -> confirm - * 11: ______BBB______ -> confirm - * 12: ______BBBsss___ -> confirm - * 13: ______BBBppp___ -> shutdown - */ - - /* 1: Ctrl+D then presence means enable */ - VbBootRecTestGpio(GPIO_PRESENCE, 0, 0, 1, - "Ctrl+D todev confirm via presence"); - - /* 2: Ctrl+D then shutdown means shutdown */ - VbBootRecTestGpio(GPIO_SHUTDOWN, 0, 0, 0, - "Ctrl+D todev then shutdown"); - - /* 3: Ctrl+D then presence then shutdown means confirm */ - VbBootRecTestGpio(GPIO_PRESENCE, GPIO_SHUTDOWN, 0, 1, - "Ctrl+D todev confirm via presence then shutdown"); - - /* 4: Ctrl+D then 2+ instance shutdown then presence means shutdown */ - VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE, 0, 0, - "Ctrl+D todev then 2+ shutdown then presence"); - - /* 5: Ctrl+D then presence then shutdown+presence then none */ - VbBootRecTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 1, - "Ctrl+D todev confirm via presence, both, none"); - - /* 6: Ctrl+D then presence then shutdown+presence then presence */ - VbBootRecTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_PRESENCE, 0, - "Ctrl+D todev confirm via presence, both, presence"); - - /* 7: Ctrl+D then presence then shutdown+presence then shutdown */ - VbBootRecTestGpio(GPIO_PRESENCE, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_SHUTDOWN, 1, - "Ctrl+D todev confirm via presence, both, shutdown"); - - /* 8: Ctrl+D then shutdown then shutdown+presence then none */ - VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 1, - "Ctrl+D todev then 2+ shutdown, both, none"); - - /* 9: Ctrl+D then shutdown then shutdown+presence then presence */ - VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_PRESENCE, 0, - "Ctrl+D todev then 2+ shutdown, both, presence"); - - /* 10: Ctrl+D then shutdown then shutdown+presence then shutdown */ - VbBootRecTestGpio(GPIO_SHUTDOWN, GPIO_PRESENCE | GPIO_SHUTDOWN, - GPIO_SHUTDOWN, 1, - "Ctrl+D todev then 2+ shutdown, both, shutdown"); - - /* 11: Ctrl+D then shutdown+presence then none */ - VbBootRecTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, 0, 0, 1, - "Ctrl+D todev confirm via both then none"); - - /* 12: Ctrl+D then shutdown+presence then shutdown */ - VbBootRecTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, GPIO_SHUTDOWN, 0, 1, - "Ctrl+D todev confirm via both then shutdown"); - - /* 13: Ctrl+D then shutdown+presence then presence */ - VbBootRecTestGpio(GPIO_PRESENCE | GPIO_SHUTDOWN, GPIO_PRESENCE, 0, 0, - "Ctrl+D todev confirm via both then presence"); -} - -static void VbBootDiagTest(void) -{ - VB2_DEBUG("Testing VbBootDiagnosticLegacyClamshell()...\n"); - - /* No key pressed - timeout. */ - ResetMocks(); - TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Timeout"); - TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG, - " confirm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, - " blank screen"); - TEST_EQ(tpm_set_mode_called, 0, " no tpm call"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(current_ticks, 30 * VB2_MSEC_PER_SEC, - " waited for 30 seconds"); - - /* Esc key pressed. */ - ResetMocks(); - mock_keypress[0] = VB_KEY_ESC; - TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Esc key"); - TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG, - " confirm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, - " blank screen"); - TEST_EQ(tpm_set_mode_called, 0, " no tpm call"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(current_ticks, 0, " didn't wait at all"); - - /* Shutdown requested via lid close */ - ResetMocks(); - MockGpioAfter(10, GPIO_LID_CLOSED); - TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), - VB2_REQUEST_SHUTDOWN, "Shutdown"); - TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG, - " confirm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, - " blank screen"); - TEST_EQ(tpm_set_mode_called, 0, " no tpm call"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_TRUE(current_ticks < VB2_MSEC_PER_SEC, " didn't wait long"); - - /* Power button pressed but not released. */ - ResetMocks(); - mock_gpio[0].gpio_flags = GPIO_PRESENCE; - mock_gpio[0].count = ~0; - TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Power held"); - TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG, - " confirm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, - " blank screen"); - TEST_EQ(tpm_set_mode_called, 0, " no tpm call"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Power button is pressed and released. */ - ResetMocks(); - MockGpioAfter(3, GPIO_PRESENCE); - TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Confirm"); - TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG, - " confirm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, - " blank screen"); - TEST_EQ(tpm_set_mode_called, 1, " tpm call"); - TEST_EQ(tpm_mode, VB2_TPM_MODE_DISABLED, " tpm disabled"); - TEST_EQ(vbexlegacy_called, 1, " legacy"); - TEST_EQ(altfw_num, VB_ALTFW_DIAGNOSTIC, " check altfw_num"); - /* - * Ideally we'd that no recovery request was recorded, but - * VbExLegacy() can only fail or crash the tests. - */ - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), - VB2_RECOVERY_ALTFW_HASH_FAILED, - " recovery request"); - - /* Power button confirm, but now with a TPM failure. */ - ResetMocks(); - tpm_mode = VB2_TPM_MODE_DISABLED; - mock_gpio[0].gpio_flags = 0; - mock_gpio[0].count = 2; - mock_gpio[1].gpio_flags = GPIO_PRESENCE; - mock_gpio[1].count = 2; - TEST_EQ(VbBootDiagnosticLegacyClamshell(ctx), VB2_REQUEST_REBOOT, - "Confirm but tpm fail"); - TEST_EQ(screens_displayed[0], VB_SCREEN_CONFIRM_DIAG, - " confirm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, - " blank screen"); - TEST_EQ(tpm_set_mode_called, 1, " tpm call"); - TEST_EQ(tpm_mode, VB2_TPM_MODE_DISABLED, " tpm disabled"); - TEST_EQ(vbexlegacy_called, 0, " legacy not called"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), - VB2_RECOVERY_TPM_DISABLE_FAILED, - " recovery request"); - - VB2_DEBUG("...done.\n"); -} - - -int main(void) -{ - VbUserConfirmsKeyboardTest(); - if (!PHYSICAL_PRESENCE_KEYBOARD) - VbUserConfirmsPhysicalPresenceTest(); - VbBootDevTest(); - VbBootDevVendorDataTest(); - VbBootRecTest(); - if (!PHYSICAL_PRESENCE_KEYBOARD) - VbBootRecPhysicalPresenceTest(); - if (DIAGNOSTIC_UI) - VbBootDiagTest(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_menu_tests.c vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_menu_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_menu_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_menu_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2349 +0,0 @@ -/* Copyright 2017 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. - * - * Tests legacy menu UI - */ - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2secdata.h" -#include "2secdata_struct.h" -#include "host_common.h" -#include "load_kernel_fw.h" -#include "test_common.h" -#include "tss_constants.h" -#include "vboot_api.h" -#include "vboot_audio.h" -#include "vboot_kernel.h" -#include "vboot_struct.h" -#include "vboot_test.h" -#include "vboot_ui_legacy.h" -#include "vboot_ui_legacy_menu_private.h" - -/* Mock data */ -static LoadKernelParams lkp; -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static struct vb2_gbb_header gbb; -static struct vb2_secdata_fwmp *fwmp; - -static int shutdown_request_calls_left; -static int audio_looping_calls_left; -static vb2_error_t vbtlk_retval[5]; -static vb2_error_t vbtlk_last_retval; -static int vbtlk_retval_count; -static const vb2_error_t vbtlk_retval_fixed = 1002; -static int vbexlegacy_called; -static enum VbAltFwIndex_t altfw_num; -static int debug_info_displayed; -static int trust_ec; -static int virtdev_set; -static uint32_t virtdev_fail; -static uint32_t mock_keypress[64]; -static uint32_t mock_keyflags[64]; -static uint32_t mock_keypress_count; -static uint32_t screens_displayed[64]; -static uint32_t screens_count = 0; -static uint32_t beeps_played[64]; -static uint32_t beeps_count = 0; -static uint32_t mock_altfw_mask; -static int vbexaltfwmask_called; - -/* Reset mock data (for use before each test) */ -static void ResetMocks(void) -{ - memset(&lkp, 0, sizeof(lkp)); - - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - vb2_nv_init(ctx); - - sd = vb2_get_sd(ctx); - - /* CRC will be invalid after here, but nobody's checking */ - sd->status |= VB2_SD_STATUS_SECDATA_FWMP_INIT; - fwmp = (struct vb2_secdata_fwmp *)ctx->secdata_fwmp; - - memset(&gbb, 0, sizeof(gbb)); - - /* In recovery we have 50 keyscans per disk scan, this must be high. */ - shutdown_request_calls_left = 301; - audio_looping_calls_left = 60; - vbexlegacy_called = 0; - altfw_num = -100; - debug_info_displayed = 0; - trust_ec = 0; - virtdev_set = 0; - virtdev_fail = 0; - - vbtlk_last_retval = vbtlk_retval_fixed - VB_DISK_FLAG_FIXED; - memset(vbtlk_retval, 0, sizeof(vbtlk_retval)); - vbtlk_retval_count = 0; - - memset(screens_displayed, 0, sizeof(screens_displayed)); - screens_count = 0; - memset(beeps_played, 0, sizeof(beeps_played)); - beeps_count = 0; - - memset(mock_keypress, 0, sizeof(mock_keypress)); - memset(mock_keyflags, 0, sizeof(mock_keyflags)); - mock_keypress_count = 0; - - mock_altfw_mask = 3 << 1; /* This mask selects 1 and 2 */ - vbexaltfwmask_called = 0; -} - -static void ResetMocksForDeveloper(void) -{ - ResetMocks(); - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - shutdown_request_calls_left = -1; -} - -static void ResetMocksForManualRecovery(void) -{ - ResetMocks(); - sd->flags |= VB2_SD_FLAG_MANUAL_RECOVERY; - trust_ec = 1; -} - -/* Mock functions */ - -struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c) -{ - return &gbb; -} - -uint32_t vb2ex_get_locale_count(void) { - return 1; -} - -uint32_t VbExGetAltFwIdxMask() { - - vbexaltfwmask_called++; - - return mock_altfw_mask; -} - -uint32_t VbExIsShutdownRequested(void) -{ - if (shutdown_request_calls_left == 0) - return 1; - else if (shutdown_request_calls_left > 0) - shutdown_request_calls_left--; - - return 0; -} - -uint32_t VbExKeyboardRead(void) -{ - return VbExKeyboardReadWithFlags(NULL); -} - -uint32_t VbExKeyboardReadWithFlags(uint32_t *key_flags) -{ - if (mock_keypress_count < ARRAY_SIZE(mock_keypress)) { - if (key_flags != NULL) - *key_flags = mock_keyflags[mock_keypress_count]; - return mock_keypress[mock_keypress_count++]; - } else - return 0; -} - -vb2_error_t VbExLegacy(enum VbAltFwIndex_t _altfw_num) -{ - vbexlegacy_called++; - altfw_num = _altfw_num; - - return 0; -} - -int vb2ex_ec_trusted(void) -{ - return trust_ec; -} - -int vb2_audio_looping(void) -{ - if (audio_looping_calls_left == 0) - return 0; - else if (audio_looping_calls_left > 0) - audio_looping_calls_left--; - - return 1; -} - -vb2_error_t VbTryLoadKernel(struct vb2_context *c, uint32_t get_info_flags) -{ - if (vbtlk_retval_count < ARRAY_SIZE(vbtlk_retval) && - vbtlk_retval[vbtlk_retval_count] != 0) - vbtlk_last_retval = vbtlk_retval[vbtlk_retval_count++]; - return vbtlk_last_retval + get_info_flags; -} - -vb2_error_t VbDisplayScreen(struct vb2_context *c, uint32_t screen, int force, - const VbScreenData *data) -{ - if (screens_count < ARRAY_SIZE(screens_displayed)) - screens_displayed[screens_count++] = screen; - VB2_DEBUG("screens_displayed[%d] = %#x\n", - screens_count - 1, screen); - return VB2_SUCCESS; -} - -vb2_error_t VbDisplayMenu(struct vb2_context *c, uint32_t screen, int force, - uint32_t selected_index, uint32_t disabled_idx_mask) -{ - if (screens_count < ARRAY_SIZE(screens_displayed)) - screens_displayed[screens_count++] = screen; - else - VB2_DEBUG("Ran out of screens_displayed entries!\n"); - VB2_DEBUG("screens_displayed[%d] = %#x," - " selected_index = %u, disabled_idx_mask = %#x\n", - screens_count - 1, screen, - selected_index, disabled_idx_mask); - - return VB2_SUCCESS; -} - -vb2_error_t VbDisplayDebugInfo(struct vb2_context *c) -{ - debug_info_displayed = 1; - return VB2_SUCCESS; -} - -void vb2ex_beep(uint32_t msec, uint32_t frequency) -{ - if (beeps_count < ARRAY_SIZE(beeps_played)) - beeps_played[beeps_count++] = frequency; - VB2_DEBUG("beeps_played[%d] = %dHz for %dms\n", - beeps_count - 1, frequency, msec); -} - -void vb2_enable_developer_mode(struct vb2_context *c) -{ - VB2_ASSERT(!virtdev_fail); - virtdev_set = 1; -} - -/* Tests */ - -static void VbBootDevTest(void) -{ - int i; - - VB2_DEBUG("Testing VbBootDeveloperLegacyMenu()...\n"); - - /* Proceed after timeout */ - ResetMocksForDeveloper(); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, "Timeout"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 0, " no beeps on normal boot"); - - /* Proceed to legacy after timeout if GBB flag set */ - ResetMocksForDeveloper(); - gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY | - VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "default legacy GBB"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Proceed to legacy after timeout if boot legacy and default boot - * legacy are set */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "default legacy NV"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Proceed to legacy boot mode only if enabled */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "default legacy not enabled"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 2, " error beeps: legacy boot not enabled"); - TEST_EQ(beeps_played[0], 400, " first error beep"); - TEST_EQ(beeps_played[1], 400, " second error beep"); - - /* Proceed to usb after timeout if boot usb and default boot - * usb are set */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), 0, "Ctrl+U USB"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* Proceed to usb boot mode only if enabled */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "default USB not enabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 2, " error beeps: USB boot not enabled"); - TEST_EQ(beeps_played[0], 400, " first error beep"); - TEST_EQ(beeps_played[1], 400, " second error beep"); - - /* If no USB tries fixed disk */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "default USB with no disk"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 1, " error beep: USB not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Shutdown requested in loop */ - ResetMocksForDeveloper(); - shutdown_request_calls_left = 2; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* - * Pushing power should shut down the DUT because default - * selection is power off - */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "dev warning menu: default to power off"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Selecting Power Off in developer options. */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Power Off in DEVELOPER"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* Pressing ENTER is equivalent to power button. */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_KEY_ENTER; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "dev warning menu: ENTER is power button"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* ENTER functionality is unaffected by GBB flag in detachable UI. */ - ResetMocksForDeveloper(); - gbb.flags |= VB2_GBB_FLAG_ENTER_TRIGGERS_TONORM; - mock_keypress[0] = VB_KEY_ENTER; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "dev warning menu: ENTER unaffected by GBB"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Pressing SPACE or VolUp+Down combo has no effect in dev mode */ - ResetMocksForDeveloper(); - mock_keypress[0] = ' '; - mock_keypress[1] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; // select Power Off - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "SPACE or VolUp+Down have no effect"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Disable developer mode */ - ResetMocksForDeveloper(); - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; - mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_REBOOT, - "disable developer mode"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_TO_NORM_CONFIRMED, - " confirm screen"); - TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 5, " no extra screens"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on reboot"); - - /* Tonorm ignored if GBB forces dev switch on */ - ResetMocksForDeveloper(); - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON; - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; - mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Can't tonorm gbb-dev"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: power off"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_WARNING_MENU, - " wanring screen: enable verification"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen: confirm"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, - " blank (error flash)"); - TEST_EQ(screens_displayed[4], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen: confirm"); - TEST_EQ(screens_displayed[5], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 6, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " audio timeout"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Shutdown requested at tonorm screen */ - ResetMocksForDeveloper(); - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; - mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS; - shutdown_request_calls_left = 2; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested at tonorm"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " developer warning screen: power off"); - TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_WARNING_MENU, - " developer warning screen: enable root verification"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " developer warning screen: power off"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on shutdown"); - - /* Ctrl+D dismisses warning */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_KEY_CTRL('D'); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, "Ctrl+D"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on normal boot"); - - /* Ctrl+D doesn't boot legacy even if GBB flag is set */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_KEY_CTRL('D'); - gbb.flags |= VB2_GBB_FLAG_DEFAULT_DEV_BOOT_LEGACY; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, "Ctrl+D"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - - /* Volume-down long press shortcut acts like Ctrl+D */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_BUTTON_VOL_DOWN_LONG_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "VolDown long press"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, - " recovery reason"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on normal boot"); - - /* Ctrl+L tries legacy boot mode only if enabled */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_KEY_CTRL('L'); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+L normal"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(audio_looping_calls_left, 0, " audio timed out"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Ctrl+L boots legacy if enabled by GBB flag */ - ResetMocksForDeveloper(); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_LEGACY; - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+L force legacy"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(altfw_num, 1, " check altfw_num"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[3], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_count, 5, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Ctrl+L boots legacy if enabled by NVRAM */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+L nv legacy"); - TEST_EQ(vbexlegacy_called, 1, " try legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[3], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_count, 5, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Ctrl+L boots legacy if enabled by FWMP */ - ResetMocksForDeveloper(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_LEGACY; - mock_keypress[0] = VB_KEY_CTRL('L'); - mock_keypress[1] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+L fwmp legacy"); - TEST_EQ(vbexlegacy_called, 1, " fwmp legacy"); - TEST_EQ(altfw_num, 1, " check altfw_num"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[3], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[4], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 5, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* TODO(sjg@chromium.org): Add a test for there being no bootloaders */ - - /* Ctrl+U boots USB only if enabled */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_KEY_CTRL('U'); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+U not enabled"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(audio_looping_calls_left, 0, " audio timed out"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Ctrl+U enabled, with good USB boot */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, "Ctrl+U USB"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* Ctrl+U enabled, without valid USB */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_KEY_CTRL('U'); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+U without valid USB"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 1, " error beep: USB not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Ctrl+U enabled via GBB */ - ResetMocksForDeveloper(); - gbb.flags |= VB2_GBB_FLAG_FORCE_DEV_BOOT_USB; - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, - "Ctrl+U force USB"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* Ctrl+U enabled via FWMP */ - ResetMocksForDeveloper(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL; - mock_keypress[0] = VB_KEY_CTRL('U'); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, - "Ctrl+U force USB"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* If no valid USB, eventually times out and tries fixed disk */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_KEY_CTRL('U'); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Ctrl+U failed - no USB"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: USB not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Now go to USB boot through menus */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, - "Menu selected USB boot"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* If default USB, the option is preselected */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, - "Menu selected USB default boot"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* If invalid USB, we still timeout after selecting it in menu */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Menu selected invalid USB boot"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: USB not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* If USB is disabled, we error flash/beep from the menu option */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Menu selected disabled USB boot"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Boot Legacy via menu and default */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Enter altfw menu - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select first option - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // and again - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, - VB2_DEV_DEFAULT_BOOT_TARGET_LEGACY); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Menu selected legacy boot"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vbexlegacy_called, 2, " tried legacy boot twice"); - TEST_EQ(altfw_num, 0, " check altfw_num"); - TEST_EQ(audio_looping_calls_left, 0, " audio timeout"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: legacy boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 2, " two error beeps: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - TEST_EQ(beeps_played[1], 200, " low-frequency error beep"); - - /* Refuse to boot legacy via menu if not enabled */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot Legacy BIOS - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Menu selected legacy boot when not enabled"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vbexlegacy_called, 0, " did not attempt legacy boot"); - TEST_EQ(audio_looping_calls_left, 0, " audio timeout"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: legacy boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: legacy boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Use volume-up long press shortcut to boot USB */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_BUTTON_VOL_UP_LONG_PRESS; - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, "VolUp USB"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* Can boot a valid USB image after failing to boot invalid image */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_BUTTON_VOL_UP_LONG_PRESS; - mock_keypress[1] = VB_BUTTON_VOL_UP_LONG_PRESS; - vbtlk_retval[0] = VB2_ERROR_MOCK - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, - "VolUp USB valid after invalid"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: first USB invalid"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Volume-up long press only works if USB is enabled */ - ResetMocksForDeveloper(); - mock_keypress[0] = VB_BUTTON_VOL_UP_LONG_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "VolUp not enabled"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(audio_looping_calls_left, 0, " audio timed out"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Volume-up long press without valid USB will still time out */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - mock_keypress[0] = VB_BUTTON_VOL_UP_LONG_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "VolUp without valid USB"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " blank (error flash)"); - TEST_EQ(screens_displayed[2], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(audio_looping_calls_left, 0, " used up audio"); - TEST_EQ(beeps_count, 1, " error beep: USB not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); - - /* Volume-up long press works from other menus, like LANGUAGE */ - ResetMocksForDeveloper(); - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 1); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_LONG_PRESS; - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_SUCCESS, - "VolUp USB from LANGUAGE"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on USB boot"); - - /* Can disable developer mode through TONORM screen */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enable os verification - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // confirm is the default - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_REBOOT, - "TONORM via menu"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning: enable os verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm: confirm"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_TO_NORM_CONFIRMED, - " confirm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps on reboot"); - - /* If dev mode is disabled, goes to TONORM screen repeatedly */ - ResetMocksForDeveloper(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - audio_looping_calls_left = 1; /* Confirm audio doesn't tick down. */ - i = 0; - mock_keypress[i++] = VB_KEY_CTRL('D'); /* Just stays on TONORM and flashes */ - mock_keypress[i++] = VB_KEY_CTRL('U'); /* same */ - mock_keypress[i++] = VB_KEY_CTRL('L'); /* same */ - mock_keypress[i++] = VB_BUTTON_VOL_UP_LONG_PRESS; /* same */ - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_LONG_PRESS; /* same */ - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; /* noop */ - mock_keypress[i++] = VB_KEY_ENTER; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_REBOOT, - "FWMP dev disabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 1, - " disable dev request"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_TO_NORM_CONFIRMED, - " confirm screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 10, " 5 * 2 error beeps: booting not allowed"); - TEST_EQ(beeps_played[0], 400, " first error beep"); - TEST_EQ(beeps_played[1], 400, " second error beep"); - TEST_EQ(beeps_played[2], 400, " first error beep"); - TEST_EQ(beeps_played[3], 400, " second error beep"); - TEST_EQ(beeps_played[4], 400, " first error beep"); - TEST_EQ(beeps_played[5], 400, " second error beep"); - TEST_EQ(beeps_played[6], 400, " first error beep"); - TEST_EQ(beeps_played[7], 400, " second error beep"); - TEST_EQ(beeps_played[8], 400, " first error beep"); - TEST_EQ(beeps_played[9], 400, " second error beep"); - - /* Shutdown requested when dev disabled */ - ResetMocksForDeveloper(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - shutdown_request_calls_left = 1; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested when dev disabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 0, - " did not exit dev mode"); - TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Explicit Power Off when dev disabled */ - ResetMocksForDeveloper(); - fwmp->flags |= VB2_SECDATA_FWMP_DEV_DISABLE_BOOT; - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Power Off when dev disabled"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST), 0, - " did not exit dev mode"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(audio_looping_calls_left, 0, " aborts audio"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen: confirm enabling OS verification"); - /* Cancel option is removed with dev_disable_boot! */ - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " tonorm screen: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps for power off"); - - /* Show Debug Info displays debug info, then times out to boot */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS Verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Show Debug Info"); - TEST_EQ(debug_info_displayed, 1, " debug info displayed"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(audio_looping_calls_left, 0, " audio timed out"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps for debug info"); - - /* Pressing Tab displays debug info, then times out to boot */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = '\t'; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "Show Debug Info (Tab shortcut)"); - TEST_EQ(debug_info_displayed, 1, " debug info displayed"); - TEST_EQ(vbexlegacy_called, 0, " not legacy"); - TEST_EQ(audio_looping_calls_left, 0, " audio timed out"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps for debug info"); - - - VB2_DEBUG("...done.\n"); -} - -static void VbBootRecTest(void) -{ - int i; - - VB2_DEBUG("Testing VbBootRecoveryLegacyMenu()...\n"); - - /* Shutdown requested in BROKEN */ - ResetMocks(); - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested in BROKEN"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - TEST_EQ(vbexaltfwmask_called, 0, " VbExGetAltFwIdxMask not called"); - - /* BROKEN screen with disks inserted */ - ResetMocks(); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[2] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[3] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested in BROKEN with disks"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* BROKEN screen with disks on second attempt */ - ResetMocks(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested in BROKEN with later disk"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* BROKEN screen even if dev switch is on */ - ResetMocks(); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[2] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested in BROKEN with dev switch"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* go to INSERT if recovery button physically pressed and EC trusted */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested in INSERT with manual rec"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* go to INSERT if forced by GBB flag */ - ResetMocks(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - gbb.flags |= VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shutdown requested in INSERT forced by GBB flag"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Stay at BROKEN if recovery button not physically pressed */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - sd->flags &= ~VB2_SD_FLAG_MANUAL_RECOVERY; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Go to BROKEN if recovery not manually requested"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Stay at BROKEN if EC is untrusted */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - trust_ec = 0; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Go to BROKEN if EC is not trusted"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* INSERT boots without screens if we have a valid image on first try */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_ERROR_MOCK - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_SUCCESS, - "INSERT boots without screens if valid on first try"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(screens_displayed[0], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 1, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* INSERT boots eventually if we get a valid image later */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[2] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[3] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[4] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_SUCCESS, - "INSERT boots after valid image appears"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* invalid image, then remove, then valid image */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_MOCK - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[2] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[3] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[4] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_SUCCESS, - "INSERT boots after valid image appears"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 3, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep on shutdown"); - - /* Shortcuts that are always ignored in BROKEN for detachables. */ - ResetMocks(); - i = 0; - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_KEY_CTRL('D'); - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_KEY_CTRL('U'); - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_KEY_CTRL('L'); - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_LONG_PRESS; - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_LONG_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shortcuts ignored in BROKEN"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from invalid keys"); - - /* Shortcuts that are always ignored in INSERT for detachables. */ - ResetMocksForManualRecovery(); - i = 0; - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_KEY_CTRL('D'); - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_KEY_CTRL('U'); - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_KEY_CTRL('L'); - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_LONG_PRESS; - mock_keypress[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_LONG_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Shortcuts ignored in INSERT"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from invalid keys"); - - /* Power Off BROKEN through OPTIONS menu */ - ResetMocks(); - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter options - mock_keypress[1] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Power Off BROKEN through OPTIONS"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_OPTIONS_MENU, - " options: cancel"); - TEST_EQ(screens_displayed[2], VB_SCREEN_OPTIONS_MENU, - " options: power off"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from power off"); - - /* Power Off NOGOOD through OPTIONS menu */ - ResetMocksForManualRecovery(); - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter options - mock_keypress[1] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Power Off NOGOOD through OPTIONS"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_OPTIONS_MENU, - " options: cancel"); - TEST_EQ(screens_displayed[2], VB_SCREEN_OPTIONS_MENU, - " options: power off"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from power off"); - - /* Power Off INSERT through TO_DEV menu */ - ResetMocksForManualRecovery(); - mock_keyflags[0] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[0] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter to_dev - mock_keyflags[1] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[1] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Power Off INSERT through TO_DEV"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to_dev: cancel"); - TEST_EQ(screens_displayed[2], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to_dev: power off"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from power off"); - - /* Show Debug Info from BROKEN through OPTIONS menu */ - ResetMocks(); - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter options - mock_keypress[1] = VB_BUTTON_VOL_UP_SHORT_PRESS; // show debug info - mock_keypress[2] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Show Debug info from BROKEN through OPTIONS"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 1, " no debug info"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - TEST_EQ(screens_displayed[0], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_OPTIONS_MENU, - " options: cancel"); - TEST_EQ(screens_displayed[2], VB_SCREEN_OPTIONS_MENU, - " options: show debug info"); - TEST_EQ(screens_displayed[3], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 4, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from power off"); - - /* Show Debug Info on NOGOOD with Tab */ - ResetMocksForManualRecovery(); - mock_keypress[0] = '\t'; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Show Debug info on NOGOOD with Tab"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 1, " no debug info"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 2, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beep from power off"); - - /* Navigate to confirm dev mode selection and then cancel */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - i = 0; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter TO_DEV - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // confirm disabling - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // power off - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "go to TO_DEV screen and cancel"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: confirm disabling"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_INSERT, - " back to insert screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Navigate to confirm dev mode selection and then confirm */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - i = 0; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter to_dev - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_REBOOT_EC_TO_RO, - "go to TO_DEV screen and confirm"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(virtdev_set, 1, " virtual dev mode on"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: confirm disabling os verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Untrusted keyboard cannot enter TO_DEV (must be malicious anyway) */ - ResetMocksForManualRecovery(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // try to_dev - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // try confirm - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Untrusted keyboard cannot enter TO_DEV"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Untrusted keyboard cannot navigate in TO_DEV menu if already there */ - ResetMocksForManualRecovery(); - i = 0; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter to_dev - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // try to confirm... - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Untrusted keyboard cannot navigate in TO_DEV"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Don't handle TPM error in enabling dev mode */ - ResetMocksForManualRecovery(); - i = 0; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter to_dev - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // confirm enabling - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - virtdev_fail = 1; - TEST_ABORT(VbBootRecoveryLegacyMenu(ctx), "todev TPM failure"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " aborted explicitly"); - TEST_EQ(virtdev_set, 0, " virtual dev mode still off"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " recovery to_dev menu: confirm disabling os verification"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Cannot enable dev mode if already enabled. */ - ResetMocksForManualRecovery(); - sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED; - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - i = 0; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter to_dev - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Ctrl+D ignored if already in dev mode"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - TEST_EQ(virtdev_set, 0, " virtual dev mode wasn't enabled again"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 2, " played error beeps"); - TEST_EQ(beeps_played[0], 400, " first beep"); - TEST_EQ(beeps_played[1], 400, " second beep"); - - /* Removing invalid USB drops back to INSERT from TO_DEV menu. */ - ResetMocksForManualRecovery(); - mock_keyflags[0] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[0] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter TO_DEV - /* asynchronous transition to INSERT before keypress[50] */ - mock_keypress[55] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - mock_keypress[56] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[57] = VB_BUTTON_POWER_SHORT_PRESS; - vbtlk_retval[0] = VB2_ERROR_MOCK - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Drop back to INSERT from TO_DEV when removing invalid USB"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev menu"); - TEST_EQ(screens_displayed[2], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[3], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[4], VB_SCREEN_OPTIONS_MENU, - " options menu: power off"); - TEST_EQ(screens_displayed[5], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 6, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Plugging in invalid USB drops back to NOGOOD from LANGUAGE. */ - ResetMocksForManualRecovery(); - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - mock_keypress[1] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[2] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[3] = VB_BUTTON_POWER_SHORT_PRESS; - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[2] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[3] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[4] = VB2_ERROR_MOCK - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "Drop back to NOGOOD from LANGUAGE when inserting invalid USB"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[2], VB_SCREEN_OPTIONS_MENU, - " options menu: power off"); - TEST_EQ(screens_displayed[3], VB_SCREEN_OPTIONS_MENU, - " options menu: language"); - TEST_EQ(screens_displayed[4], VB_SCREEN_LANGUAGES_MENU, - " languages menu"); - TEST_EQ(screens_displayed[5], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[6], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 7, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Plugging in valid USB boots straight from OPTIONS menu. */ - ResetMocksForManualRecovery(); - mock_keypress[0] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - vbtlk_retval[1] = VB2_SUCCESS - VB_DISK_FLAG_REMOVABLE; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_SUCCESS, - "Boot by plugging in USB straight from OPTIONS menu"); - TEST_NEQ(shutdown_request_calls_left, 0, " booted explicitly"); - TEST_EQ(virtdev_set, 0, " virtual dev mode off"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_EQ(screens_displayed[0], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[1], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[2], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, 3, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - VB2_DEBUG("...done.\n"); -} - -static void VbTestLanguageMenu(void) -{ - int i; - - VB2_DEBUG("Testing VbTestLanguageMenu()...\n"); - - /* Navigate to language menu from BROKEN */ - ResetMocks(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // languages - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // enter languages - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // cancel -> BROKEN - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // power off - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "go to language menu from BROKEN"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OS_BROKEN, - " broken screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Navigate to all language menus from recovery */ - ResetMocksForManualRecovery(); - vbtlk_retval[0] = VB2_ERROR_LK_NO_DISK_FOUND - - VB_DISK_FLAG_REMOVABLE; - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // languages - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter TO_DEV - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // confirm disabling - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "go to language menus from INSERT"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_INSERT, - " insert screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: confirm disabling os verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: power_off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " to dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* Navigate to all language menus from developer menu */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enable OS verif - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // return to dev_warn - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enable OS verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // show debug info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // developer options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - " scroll through all language menus in developer options"); - TEST_EQ(debug_info_displayed, 0, " no debug info"); - TEST_NEQ(shutdown_request_calls_left, 0, " powered down explicitly"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu: select current language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: cancel "); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to norm screen: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to norm screen: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to norm screen: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to norm screen: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu: select current language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to norm screen: confirm enabling os verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to norm screen: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " warning screen: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " select developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: boot developer image"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " language menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: boot from disk"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " developer menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - VB2_DEBUG("...done.\n"); -} - -static void VbNavigationTest(void) -{ - int i; - - VB2_DEBUG("Testing long navigation sequences..."); - - /* - * NOGOOD, OPTIONS, LANGUAGE, TODEV, LANGUAGE, TODEV, - * LANGUAGE, select, Cancel, OPTIONS, LANGUAGE - */ - ResetMocksForManualRecovery(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter TO_DEV - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // confirm enabling - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu) - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_DOWN_COMBO_PRESS; // enter TO_DEV - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // select current lang - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // power off - mock_keyflags[i] = VB_KEY_FLAG_TRUSTED_KEYBOARD; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // enter OPTIONS - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // show debug info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // power off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // language - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - TEST_EQ(VbBootRecoveryLegacyMenu(ctx), VB2_REQUEST_SHUTDOWN, - "recovery mode long navigation"); - TEST_EQ(debug_info_displayed, 1, " showed debug info"); - TEST_EQ(shutdown_request_calls_left, 0, " timed out"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " languages menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: confirm enabling"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: confirm enabling"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " languages menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " languages menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_TO_DEV_MENU, - " todev: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_RECOVERY_NO_GOOD, - " nogood screen"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_OPTIONS_MENU, - " options: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_LANGUAGES_MENU, - " languages menu"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 0, " no beeps"); - - /* DEVELOPER, Cancel, Show Debug, TO_NORM, Cancel, Boot Legacy */ - ResetMocksForDeveloper(); - i = 0; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot Legacy - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Boot From Disk - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Enable OS verif - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Language - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Enable OS verif - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Show Debug Info - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Developer Options - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Language - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Power Off - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From Disk - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot Legacy - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select altfw menu - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Second altfw - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Cancel - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // (end of menu) - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Back to dev options - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From Disk - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot From USB - mock_keypress[i++] = VB_BUTTON_VOL_UP_SHORT_PRESS; // Boot Legacy - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select altfw menu - mock_keypress[i++] = VB_BUTTON_VOL_DOWN_SHORT_PRESS; // Second altfw - mock_keypress[i++] = VB_BUTTON_POWER_SHORT_PRESS; // Select 2nd altfw - vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 1); - TEST_EQ(VbBootDeveloperLegacyMenu(ctx), vbtlk_retval_fixed, - "developer mode long navigation"); - TEST_EQ(debug_info_displayed, 1, " showed debug info"); - TEST_EQ(vbexlegacy_called, 1, " tried legacy"); - TEST_EQ(altfw_num, 2, " check altfw_num"); - TEST_EQ(audio_looping_calls_left, 0, " audio timeout"); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST), 0, " no recovery"); - i = 0; - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: Legacy boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: Legacy boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: USB boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: disk boot"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: confirm enabling"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_TO_NORM_MENU, - " to dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: enable root verification"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: show debug info"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_WARNING_MENU, - " dev warning menu: developer options"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot from disk"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: language"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: power off"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot from disk"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot from USB"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot legacy"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot legacy"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw 1"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw 2"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, - " altfw cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, - " altfw end"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: cancel"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot from disk"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot from USB"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_DEVELOPER_MENU, - " dev menu: boot legacy"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK, " blank (flash)"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_ALT_FW_MENU, " altfw"); - TEST_EQ(screens_displayed[i++], VB_SCREEN_BLANK," final blank screen"); - TEST_EQ(screens_count, i, " no extra screens"); - TEST_EQ(beeps_count, 1, " error beep: legacy BIOS not found"); - TEST_EQ(beeps_played[0], 200, " low-frequency error beep"); -} - -int main(void) -{ - VbBootDevTest(); - VbBootRecTest(); - VbTestLanguageMenu(); - VbNavigationTest(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_tests.c vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_tests.c --- vboot-utils-0~R88-13597.B/tests/vboot_ui_legacy_tests.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/vboot_ui_legacy_tests.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,124 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Tests for firmware display library. - */ - -#include -#include -#include -#include - -#include "2common.h" -#include "2misc.h" -#include "2nvstorage.h" -#include "2struct.h" -#include "2sysincludes.h" -#include "host_common.h" -#include "test_common.h" -#include "vboot_kernel.h" -#include "vboot_ui_legacy.h" - -/* Mock data */ -static char debug_info[4096]; -static struct vb2_context *ctx; -static struct vb2_shared_data *sd; -static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] - __attribute__((aligned(VB2_WORKBUF_ALIGN))); -static uint32_t mock_localization_count; -static uint32_t mock_altfw_mask; - -/* Reset mock data (for use before each test) */ -static void ResetMocks(void) -{ - mock_localization_count = 3; - mock_altfw_mask = 3 << 1; /* This mask selects 1 and 2 */ - - TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx), - "vb2api_init failed"); - vb2_nv_init(ctx); - - sd = vb2_get_sd(ctx); - - *debug_info = 0; -} - -/* Mocks */ -uint32_t vb2ex_get_locale_count(void) { - - return mock_localization_count; -} - -uint32_t VbExGetAltFwIdxMask() { - return mock_altfw_mask; -} - -vb2_error_t VbExDisplayDebugInfo(const char *info_str, int full_info) -{ - strncpy(debug_info, info_str, sizeof(debug_info)); - debug_info[sizeof(debug_info) - 1] = '\0'; - return VB2_SUCCESS; -} - -vb2_error_t vb2ex_commit_data(struct vb2_context *c) -{ - return VB2_SUCCESS; -} - -/* Test displaying debug info */ -static void DebugInfoTest(void) -{ - /* Display debug info */ - ResetMocks(); - TEST_SUCC(VbDisplayDebugInfo(ctx), - "Display debug info"); - TEST_NEQ(*debug_info, '\0', " Some debug info was displayed"); -} - -/* Test display key checking */ -static void DisplayKeyTest(void) -{ - ResetMocks(); - VbCheckDisplayKey(ctx, 'q', 0, NULL); - TEST_EQ(*debug_info, '\0', "DisplayKey q = does nothing"); - - ResetMocks(); - VbCheckDisplayKey(ctx, '\t', 0, NULL); - TEST_NEQ(*debug_info, '\0', "DisplayKey tab = display"); - - /* Toggle localization */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, 0); - VbCheckDisplayKey(ctx, VB_KEY_DOWN, 0, NULL); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 2, - "DisplayKey up"); - VbCheckDisplayKey(ctx, VB_KEY_LEFT, 0, NULL); - vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 1, - "DisplayKey left"); - VbCheckDisplayKey(ctx, VB_KEY_RIGHT, 0, NULL); - vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 2, - "DisplayKey right"); - VbCheckDisplayKey(ctx, VB_KEY_UP, 0, NULL); - vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 0, - "DisplayKey up"); - - /* Reset localization if localization count is invalid */ - ResetMocks(); - vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, 1); - mock_localization_count = 0; - VbCheckDisplayKey(ctx, VB_KEY_UP, 0, NULL); - TEST_EQ(vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX), 0, - "DisplayKey invalid"); -} - -int main(void) -{ - DebugInfoTest(); - DisplayKeyTest(); - - return gTestSuccess ? 0 : 255; -} diff -Nru vboot-utils-0~R88-13597.B/tests/verify_kernel.c vboot-utils-0~R99-14469.B/tests/verify_kernel.c --- vboot-utils-0~R88-13597.B/tests/verify_kernel.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/tests/verify_kernel.c 2022-02-11 14:46:24.000000000 +0000 @@ -10,10 +10,11 @@ #include "2common.h" #include "2misc.h" #include "2nvstorage.h" +#include "2secdata.h" #include "host_common.h" #include "util_misc.h" #include "vboot_api.h" -#include "vboot_kernel.h" +#include "load_kernel_fw.h" static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE] __attribute__((aligned(VB2_WORKBUF_ALIGN))); @@ -22,16 +23,17 @@ static uint8_t *diskbuf; -static LoadKernelParams params; +static VbSelectAndLoadKernelParams params; +static VbDiskInfo disk_info; vb2_error_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, uint64_t lba_count, void *buffer) { if (handle != (VbExDiskHandle_t)1) return VB2_ERROR_UNKNOWN; - if (lba_start >= params.streaming_lba_count) + if (lba_start >= disk_info.streaming_lba_count) return VB2_ERROR_UNKNOWN; - if (lba_start + lba_count > params.streaming_lba_count) + if (lba_start + lba_count > disk_info.streaming_lba_count) return VB2_ERROR_UNKNOWN; memcpy(buffer, diskbuf + lba_start * 512, lba_count * 512); @@ -43,9 +45,9 @@ { if (handle != (VbExDiskHandle_t)1) return VB2_ERROR_UNKNOWN; - if (lba_start >= params.streaming_lba_count) + if (lba_start >= disk_info.streaming_lba_count) return VB2_ERROR_UNKNOWN; - if (lba_start + lba_count > params.streaming_lba_count) + if (lba_start + lba_count > disk_info.streaming_lba_count) return VB2_ERROR_UNKNOWN; memcpy(diskbuf + lba_start * 512, buffer, lba_count * 512); @@ -86,9 +88,10 @@ /* Set up params */ params.disk_handle = (VbExDiskHandle_t)1; - params.bytes_per_lba = 512; - params.streaming_lba_count = disk_bytes / 512; - params.gpt_lba_count = params.streaming_lba_count; + disk_info.handle = (VbExDiskHandle_t)1; + disk_info.bytes_per_lba = 512; + disk_info.streaming_lba_count = disk_bytes / 512; + disk_info.lba_count = disk_info.streaming_lba_count; params.kernel_buffer_size = 16 * 1024 * 1024; params.kernel_buffer = malloc(params.kernel_buffer_size); @@ -98,7 +101,7 @@ } /* TODO(chromium:441893): support dev-mode flag and external gpt flag */ - params.boot_flags = 0; + disk_info.flags = 0; if (vb2api_init(&workbuf, sizeof(workbuf), &ctx)) { fprintf(stderr, "Can't initialize workbuf\n"); @@ -124,9 +127,14 @@ * dev mode. So just use defaults for nv storage. */ vb2_nv_init(ctx); + /* We need to init kernel secdata for + * VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED. + */ + vb2api_secdata_kernel_create(ctx); + vb2_secdata_kernel_init(ctx); /* Try loading kernel */ - rv = LoadKernel(ctx, ¶ms); + rv = LoadKernel(ctx, ¶ms, &disk_info); if (rv != VB2_SUCCESS) { fprintf(stderr, "LoadKernel() failed with code %d\n", rv); return 1; diff -Nru vboot-utils-0~R88-13597.B/unblocked_terms.txt vboot-utils-0~R99-14469.B/unblocked_terms.txt --- vboot-utils-0~R88-13597.B/unblocked_terms.txt 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/unblocked_terms.txt 2022-02-11 14:46:24.000000000 +0000 @@ -1,3 +1,2 @@ dummy -master -slave \ No newline at end of file +master \ No newline at end of file diff -Nru vboot-utils-0~R88-13597.B/utility/chromeos-tpm-recovery vboot-utils-0~R99-14469.B/utility/chromeos-tpm-recovery --- vboot-utils-0~R88-13597.B/utility/chromeos-tpm-recovery 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/utility/chromeos-tpm-recovery 2022-02-11 14:46:24.000000000 +0000 @@ -30,9 +30,9 @@ } use_v0_secdata_kernel() { - local fwid=$(crossystem ro_fwid) - local major=$(printf "$fwid" | cut -d. -f2) - local minor=$(printf "$fwid" | cut -d. -f3) + local fwid="$(crossystem ro_fwid)" + local major="$(printf "$fwid" | cut -d. -f2)" + local minor="$(printf "$fwid" | cut -d. -f3)" # TPM1 firmware never supports the v1 kernel space format. if ! tpm2_target; then diff -Nru vboot-utils-0~R88-13597.B/utility/crossystem.c vboot-utils-0~R99-14469.B/utility/crossystem.c --- vboot-utils-0~R88-13597.B/utility/crossystem.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/utility/crossystem.c 2022-02-11 14:46:24.000000000 +0000 @@ -37,13 +37,13 @@ {"cros_debug", 0, "OS should allow debug features"}, {"dbg_reset", CAN_WRITE, "Debug reset mode request"}, {"debug_build", 0, "OS image built for debug features"}, - {"dev_boot_legacy", CAN_WRITE, "Enable developer mode boot Legacy OSes"}, + {"dev_boot_altfw", CAN_WRITE, "Enable developer mode alternate bootloader"}, {"dev_boot_signed_only", CAN_WRITE, "Enable developer mode boot only from official kernels"}, {"dev_boot_usb", CAN_WRITE, "Enable developer mode boot from external disk (USB/SD)"}, {"dev_default_boot", IS_STRING|CAN_WRITE, - "Default boot from disk, legacy or usb"}, + "Default boot from disk, altfw or usb"}, {"dev_enable_udc", CAN_WRITE, "Enable USB Device Controller"}, {"devsw_boot", 0, "Developer switch position at boot"}, {"devsw_cur", 0, "Developer switch current position"}, @@ -52,12 +52,12 @@ {"ecfw_act", IS_STRING, "Active EC firmware"}, {"post_ec_sync_delay", CAN_WRITE, "Short delay after EC software sync (persistent, writable, eve only)"}, - {"fw_prev_result", IS_STRING, "Firmware result of previous boot (vboot2)"}, - {"fw_prev_tried", IS_STRING, "Firmware tried on previous boot (vboot2)"}, - {"fw_result", IS_STRING|CAN_WRITE, "Firmware result this boot (vboot2)"}, - {"fw_tried", IS_STRING, "Firmware tried this boot (vboot2)"}, + {"fw_prev_result", IS_STRING, "Firmware result of previous boot"}, + {"fw_prev_tried", IS_STRING, "Firmware tried on previous boot (A or B)"}, + {"fw_result", IS_STRING|CAN_WRITE, "Firmware result this boot"}, + {"fw_tried", IS_STRING, "Firmware tried this boot (A or B)"}, {"fw_try_count", CAN_WRITE, "Number of times to try fw_try_next"}, - {"fw_try_next", IS_STRING|CAN_WRITE, "Firmware to try next (vboot2)"}, + {"fw_try_next", IS_STRING|CAN_WRITE, "Firmware to try next (A or B)"}, {"fw_vboot2", 0, "1 if firmware was selected by vboot2 or 0 otherwise"}, {"fwb_tries", CAN_WRITE, "Try firmware B count"}, {"fwid", IS_STRING, "Active firmware ID"}, @@ -72,6 +72,8 @@ {"loc_idx", CAN_WRITE, "Localization index for firmware screens"}, {"mainfw_act", IS_STRING, "Active main firmware"}, {"mainfw_type", IS_STRING, "Active main firmware type"}, + {"minios_priority", IS_STRING|CAN_WRITE, + "miniOS image to try first (A or B)"}, {"nvram_cleared", CAN_WRITE, "Have NV settings been lost? Write 0 to clear"}, {"display_request", CAN_WRITE, "Should we initialize the display at boot?"}, {"phase_enforcement", 0, @@ -86,7 +88,7 @@ {"tpm_attack", CAN_WRITE, "TPM was interrupted since this flag was cleared"}, {"tpm_fwver", 0, "Firmware version stored in TPM", "0x%08x"}, {"tpm_kernver", 0, "Kernel version stored in TPM", "0x%08x"}, - {"tpm_rebooted", 0, "TPM requesting repeated reboot (vboot2)"}, + {"tpm_rebooted", 0, "TPM requesting repeated reboot"}, {"tried_fwb", 0, "Tried firmware B before A this boot"}, {"try_ro_sync", 0, "try read only software sync"}, {"vdat_flags", 0, "Flags from VbSharedData", "0x%08x"}, @@ -106,7 +108,7 @@ static void PrintHelp(const char *progname) { const Param *p; - printf("\nUsage:\n" + printf("Usage:\n" " %s [--all]\n" " Prints all parameters with descriptions and current values.\n" " If --all is specified, prints even normally hidden fields.\n" @@ -116,7 +118,7 @@ " Sets the parameter(s) to the specified value(s).\n" " %s [param1?value1] [param2?value2 [...]]]\n" " Checks if the parameter(s) all contain the specified value(s).\n" - "Stops at the first error." + " Stops at the first error.\n" "\n" "Valid parameters:\n", progname, progname, progname, progname); for (p = sys_param_list; p->name; p++) { @@ -125,6 +127,10 @@ (p->flags & IS_STRING) ? "str" : "int", p->desc); } + printf("\n" + "For more information, please see:\n" + "https://chromium.googlesource.com/chromiumos/docs/+/HEAD/" + "os_config.md#crossystem\n"); } @@ -135,6 +141,14 @@ const Param* p; if (!name) return NULL; + /* "legacy" term deprecated in favour of "altfw" (see: b/179458327) */ + if (!strcasecmp(name, "dev_boot_legacy")) { + fprintf(stderr, + "!!!\n" + "!!! PLEASE USE 'dev_boot_altfw' INSTEAD OF 'dev_boot_legacy'\n" + "!!!\n"); + name = "dev_boot_altfw"; + } for (p = sys_param_list; p->name; p++) { if (!strcasecmp(p->name, name)) return p; @@ -308,13 +322,13 @@ case PARAM_SUCCESS: break; case PARAM_ERROR_READ_ONLY: - fprintf(stderr, "Parameter %s is read-only\n", name); + fprintf(stderr, "Parameter %s is read-only\n", p->name); break; case PARAM_ERROR_INVALID_INT: fprintf(stderr, "Value %s is not a valid integer\n", value); break; default: - fprintf(stderr, "Failed to set parameter %s\n", name); + fprintf(stderr, "Failed to set parameter %s\n", p->name); break; } } else if (has_expect) diff -Nru vboot-utils-0~R88-13597.B/utility/load_kernel_test.c vboot-utils-0~R99-14469.B/utility/load_kernel_test.c --- vboot-utils-0~R88-13597.B/utility/load_kernel_test.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/utility/load_kernel_test.c 2022-02-11 14:46:24.000000000 +0000 @@ -16,7 +16,6 @@ #include "2sysincludes.h" #include "host_common.h" #include "load_kernel_fw.h" -#include "vboot_kernel.h" #define LBA_BYTES 512 #define KERNEL_BUFFER_SIZE 0xA00000 @@ -26,7 +25,8 @@ static struct vb2_shared_data *sd; /* Global variables for stub functions */ -static LoadKernelParams lkp; +static VbSelectAndLoadKernelParams lkp; +static VbDiskInfo disk_info; static FILE *image_file = NULL; @@ -36,17 +36,19 @@ { printf("Read(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count); - if (lba_start >= lkp.streaming_lba_count || - lba_start + lba_count > lkp.streaming_lba_count) { + if (lba_start >= disk_info.streaming_lba_count || + lba_start + lba_count > disk_info.streaming_lba_count) { fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n", lba_start, - lba_count, lkp.streaming_lba_count); + lba_count, disk_info.streaming_lba_count); return 1; } - if (0 != fseek(image_file, lba_start * lkp.bytes_per_lba, SEEK_SET) || - 1 != fread(buffer, lba_count * lkp.bytes_per_lba, 1, image_file)) { + if (0 != fseek(image_file, lba_start * disk_info.bytes_per_lba, + SEEK_SET) || + 1 != fread(buffer, lba_count * disk_info.bytes_per_lba, 1, + image_file)) { fprintf(stderr, "Read error."); return 1; } @@ -59,12 +61,12 @@ { printf("Write(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count); - if (lba_start >= lkp.streaming_lba_count || - lba_start + lba_count > lkp.streaming_lba_count) { + if (lba_start >= disk_info.streaming_lba_count || + lba_start + lba_count > disk_info.streaming_lba_count) { fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n", lba_start, lba_count, - lkp.streaming_lba_count); + disk_info.streaming_lba_count); return 1; } @@ -72,8 +74,9 @@ our example file */ return VB2_SUCCESS; - fseek(image_file, lba_start * lkp.bytes_per_lba, SEEK_SET); - if (1 != fwrite(buffer, lba_count * lkp.bytes_per_lba, 1, image_file)) { + fseek(image_file, lba_start * disk_info.bytes_per_lba, SEEK_SET); + if (1 != fwrite(buffer, lba_count * disk_info.bytes_per_lba, 1, + image_file)) { fprintf(stderr, "Read error."); return 1; } @@ -96,8 +99,8 @@ int errorcnt = 0; char *e = 0; - memset(&lkp, 0, sizeof(LoadKernelParams)); - lkp.bytes_per_lba = LBA_BYTES; + memset(&lkp, 0, sizeof(VbSelectAndLoadKernelParams)); + disk_info.bytes_per_lba = LBA_BYTES; int boot_flags = BOOT_FLAG_RECOVERY; /* Parse options */ @@ -186,7 +189,6 @@ } printf("bootflags = %d\n", boot_flags); - lkp.boot_flags = boot_flags; /* Get image size */ printf("Reading from image: %s\n", image_name); @@ -196,10 +198,11 @@ return 1; } fseek(image_file, 0, SEEK_END); - lkp.streaming_lba_count = (ftell(image_file) / LBA_BYTES); - lkp.gpt_lba_count = lkp.streaming_lba_count; + disk_info.streaming_lba_count = (ftell(image_file) / LBA_BYTES); + disk_info.lba_count = disk_info.streaming_lba_count; rewind(image_file); - printf("Streaming LBA count: %" PRIu64 "\n", lkp.streaming_lba_count); + printf("Streaming LBA count: %" PRIu64 "\n", + disk_info.streaming_lba_count); /* Allocate a buffer for the kernel */ lkp.kernel_buffer = malloc(KERNEL_BUFFER_SIZE); @@ -241,7 +244,7 @@ ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE; /* Call LoadKernel() */ - rv = LoadKernel(ctx, &lkp); + rv = LoadKernel(ctx, &lkp, &disk_info); printf("LoadKernel() returned %d\n", rv); if (VB2_SUCCESS == rv) { diff -Nru vboot-utils-0~R88-13597.B/utility/tpmc.c vboot-utils-0~R99-14469.B/utility/tpmc.c --- vboot-utils-0~R88-13597.B/utility/tpmc.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/utility/tpmc.c 2022-02-11 14:46:24.000000000 +0000 @@ -66,10 +66,10 @@ * success, non-zero for failure. */ static int HexStringToUint32(const char* string, uint32_t* value) { - char tail[1]; + char tail; /* strtoul is not as good because it overflows silently */ - const char* format = strncmp(string, "0x", 2) ? "%8x%s" : "0x%8x%s"; - int n = sscanf(string, format, value, tail); + const char* format = strncmp(string, "0x", 2) ? "%8x%c" : "0x%8x%c"; + int n = sscanf(string, format, value, &tail); return n != 1; } diff -Nru vboot-utils-0~R88-13597.B/utility/verify_data.c vboot-utils-0~R99-14469.B/utility/verify_data.c --- vboot-utils-0~R88-13597.B/utility/verify_data.c 2020-12-01 09:49:40.000000000 +0000 +++ vboot-utils-0~R99-14469.B/utility/verify_data.c 2022-02-11 14:46:24.000000000 +0000 @@ -21,7 +21,6 @@ #include "2sysincludes.h" #include "file_keys.h" #include "host_common.h" -#include "vb2_common.h" /* ANSI Color coding sequences. */ #define COL_GREEN "\e[1;32m"