diff options
author | Steve McIntyre <steve@einval.com> | 2021-03-23 23:49:46 +0000 |
---|---|---|
committer | Steve McIntyre <steve@einval.com> | 2021-03-23 23:49:46 +0000 |
commit | 031e5cce385d3f96b1caa1d53495332a7eb03749 (patch) | |
tree | b4988dfbd191b2242b9294e24075b39a608b1155 /include | |
parent | 7bf7a6d0852382bb645119b18df3ff461aaba247 (diff) | |
download | efi-boot-shim-upstream/15.3.tar.gz efi-boot-shim-upstream/15.3.zip |
New upstream version 15.3upstream/15.3
Diffstat (limited to 'include')
46 files changed, 1806 insertions, 320 deletions
diff --git a/include/asm.h b/include/asm.h new file mode 100644 index 00000000..8458d5d2 --- /dev/null +++ b/include/asm.h @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + +#ifndef SHIM_ASM_H_ +#define SHIM_ASM_H_ + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +static inline uint64_t read_counter(void) +{ + uint64_t val; +#if defined (__x86_64__) + unsigned long low, high; + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)); + val = (low) | (high) << 32; +#elif defined(__i386__) || defined(__i686__) + __asm__ __volatile__("rdtsc" : "=A" (val)); +#elif defined(__aarch64__) + __asm__ __volatile__ ("mrs %0, pmccntr_el0" : "=r" (val)); +#elif defined(__arm__) + __asm__ __volatile__ ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); +#else +#error unsupported arch +#endif + return val; +} + +#if defined(__x86_64__) || defined(__i386__) || defined(__i686__) +static inline void pause(void) +{ + __asm__ __volatile__("pause"); +} +#elif defined(__aarch64__) +static inline void pause(void) +{ + __asm__ __volatile__("wfi"); +} +#else +static inline void pause(void) +{ + uint64_t a, b; + int x; + extern void msleep(unsigned long msecs); + + a = read_counter(); + for (x = 0; x < 1000; x++) { + msleep(1000); + b = read_counter(); + if (a != b) + break; + } +} +#endif + +#endif /* !SHIM_ASM_H_ */ +// vim:fenc=utf-8:tw=75:et diff --git a/include/compiler.h b/include/compiler.h new file mode 100644 index 00000000..18576724 --- /dev/null +++ b/include/compiler.h @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + +#ifndef COMPILER_H_ +#define COMPILER_H_ + +/* + * These are special ones that get our unit tests in trouble with the + * compiler optimizer dropping out tests... + */ +#ifdef NONNULL +# undef NONNULL +#endif +#ifdef RETURNS_NONNULL +# undef RETURNS_NONNULL +#endif +#ifdef SHIM_UNIT_TEST +# define NONNULL(first, args...) +# define RETURNS_NONNULL +#else +# define NONNULL(first, args...) __attribute__((__nonnull__(first, ## args))) +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) +# define RETURNS_NONNULL __attribute__((__returns_nonnull__)) +#else +# define RETURNS_NONNULL +#endif +#endif + +#ifndef UNUSED +#define UNUSED __attribute__((__unused__)) +#endif +#ifndef HIDDEN +#define HIDDEN __attribute__((__visibility__ ("hidden"))) +#endif +#ifndef PUBLIC +#define PUBLIC __attribute__((__visibility__ ("default"))) +#endif +#ifndef DEPRECATED +#define DEPRECATED __attribute__((__deprecated__)) +#endif +#ifndef DESTRUCTOR +#define DESTRUCTOR __attribute__((destructor)) +#endif +#ifndef CONSTRUCTOR +#define CONSTRUCTOR __attribute__((constructor)) +#endif +#ifndef ALIAS +#define ALIAS(x) __attribute__((weak, alias (#x))) +#endif +#ifndef ALLOCFUNC +#define ALLOCFUNC(dealloc, dealloc_arg) __attribute__((__malloc__(dealloc, dealloc_arg))) +#endif +#ifndef PRINTF +#define PRINTF(first, args...) __attribute__((__format__(printf, first, ## args))) +#endif +#ifndef PURE +#define PURE __attribute__((__pure__)) +#endif +#ifndef FLATTEN +#define FLATTEN __attribute__((__flatten__)) +#endif +#ifndef PACKED +#define PACKED __attribute__((__packed__)) +#endif +#ifndef VERSION +#define VERSION(sym, ver) __asm__(".symver " # sym "," # ver) +#endif +#ifndef NORETURN +#define NORETURN __attribute__((__noreturn__)) +#endif +#ifndef ALIGNED +#define ALIGNED(n) __attribute__((__aligned__(n))) +#endif +#ifndef CLEANUP_FUNC +#define CLEANUP_FUNC(x) __attribute__((__cleanup__(x))) +#endif +#ifndef USED +#define USED __attribute__((__used__)) +#endif +#ifndef SECTION +#define SECTION(x) __attribute__((__section__(x))) +#endif +#ifndef OPTIMIZE +#define OPTIMIZE(x) __attribute__((__optimize__(x))) +#endif + +#ifndef __CONCAT +#define __CONCAT(a, b) a ## b +#endif +#ifndef __CONCAT3 +#define __CONCAT3(a, b, c) a ## b ## c +#endif +#ifndef CAT +#define CAT(a, b) __CONCAT(a, b) +#endif +#ifndef CAT3 +#define CAT3(a, b, c) __CONCAT3(a, b, c) +#endif +#ifndef STRING +#define STRING(x) __STRING(x) +#endif + +#ifndef WRITE_ONCE +#define WRITE_ONCE(var, val) \ + (*((volatile typeof(val) *)(&(var))) = (val)) +#endif + +#ifndef READ_ONCE +#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) +#endif + +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif + +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif + +/* Are two types/vars the same type (ignoring qualifiers)? */ +#ifndef __same_type +#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +#endif + +/* Compile time object size, -1 for unknown */ +#ifndef __compiletime_object_size +# define __compiletime_object_size(obj) -1 +#endif +#ifndef __compiletime_warning +# define __compiletime_warning(message) +#endif +#ifndef __compiletime_error +# define __compiletime_error(message) +#endif + +#ifndef __compiletime_assert +#define __compiletime_assert(condition, msg, prefix, suffix) \ + do { \ + extern void prefix ## suffix(void) __compiletime_error(msg); \ + if (!(condition)) \ + prefix ## suffix(); \ + } while (0) +#endif + +#ifndef _compiletime_assert +#define _compiletime_assert(condition, msg, prefix, suffix) \ + __compiletime_assert(condition, msg, prefix, suffix) +#endif + +/** + * compiletime_assert - break build and emit msg if condition is false + * @condition: a compile-time constant condition to check + * @msg: a message to emit if condition is false + * + * In tradition of POSIX assert, this macro will break the build if the + * supplied condition is *false*, emitting the supplied error message if the + * compiler has support to do so. + */ +#ifndef compiletime_assert +#define compiletime_assert(condition, msg) \ + _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1) +#endif + +/** + * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied + * error message. + * @condition: the condition which the compiler should know is false. + * + * See BUILD_BUG_ON for description. + */ +#ifndef BUILD_BUG_ON_MSG +#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) +#endif + +#ifndef ALIGN +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) +#define ALIGN(x, a) __ALIGN((x), (a)) +#endif +#ifndef ALIGN_DOWN +#define ALIGN_DOWN(x, a) __ALIGN((x) - ((a) - 1), (a)) +#endif + +#define MIN(a, b) ({(a) < (b) ? (a) : (b);}) +#define MAX(a, b) ({(a) <= (b) ? (b) : (a);}) + +/** + * Builtins that don't go in string.h + */ +#define unreachable() __builtin_unreachable() + +#endif /* !COMPILER_H_ */ +// vim:fenc=utf-8:tw=75:et diff --git a/include/configtable.h b/include/configtable.h index 0c9dfdca..e44bbbae 100644 --- a/include/configtable.h +++ b/include/configtable.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_CONFIGTABLE_H #define SHIM_CONFIGTABLE_H @@ -5,7 +7,7 @@ typedef UINT32 EFI_IMAGE_EXECUTION_ACTION; -#define EFI_IMAGE_EXECUTION_AUTHENTICATION 0x00000007 +#define EFI_IMAGE_EXECUTION_AUTHENTICATION 0x00000007 #define EFI_IMAGE_EXECUTION_AUTH_UNTESTED 0x00000000 #define EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED 0x00000001 #define EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED 0x00000002 @@ -24,24 +26,24 @@ typedef struct { /// UINT32 InfoSize; /// - /// If this image was a UEFI device driver (for option ROM, for example) this is the - /// null-terminated, user-friendly name for the device. If the image was for an application, - /// then this is the name of the application. If this cannot be determined, then a simple + /// If this image was a UEFI device driver (for option ROM, for example) this is the + /// null-terminated, user-friendly name for the device. If the image was for an application, + /// then this is the name of the application. If this cannot be determined, then a simple /// NULL character should be put in this position. /// CHAR16 Name[]; /// /// - /// For device drivers, this is the device path of the device for which this device driver - /// was intended. In some cases, the driver itself may be stored as part of the system - /// firmware, but this field should record the device's path, not the firmware path. For - /// applications, this is the device path of the application. If this cannot be determined, + /// For device drivers, this is the device path of the device for which this device driver + /// was intended. In some cases, the driver itself may be stored as part of the system + /// firmware, but this field should record the device's path, not the firmware path. For + /// applications, this is the device path of the application. If this cannot be determined, /// a simple end-of-path device node should be put in this position. /// EFI_DEVICE_PATH_PROTOCOL DevicePath; /// /// - /// Zero or more image signatures. If the image contained no signatures, + /// Zero or more image signatures. If the image contained no signatures, /// then this field is empty. /// ///EFI_SIGNATURE_LIST Signature; @@ -52,14 +54,13 @@ typedef struct { /// /// Number of EFI_IMAGE_EXECUTION_INFO structures. /// - UINTN NumberOfImages; + UINTN NumberOfImages; /// /// Number of image instances of EFI_IMAGE_EXECUTION_INFO structures. /// EFI_IMAGE_EXECUTION_INFO InformationInfo[]; } EFI_IMAGE_EXECUTION_INFO_TABLE; - void * configtable_get_table(EFI_GUID *guid); EFI_IMAGE_EXECUTION_INFO_TABLE * diff --git a/include/console.h b/include/console.h index deb4fa3d..f56b1231 100644 --- a/include/console.h +++ b/include/console.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_CONSOLE_H #define SHIM_CONSOLE_H @@ -7,11 +9,17 @@ #define PrintAt(fmt, ...) \ ({"Do not directly call PrintAt() use console_print_at() instead" = 1;}); +#if !defined(EFI_WARN_UNKNOWN_GLYPH) && defined(EFI_WARN_UNKOWN_GLYPH) +#define EFI_WARN_UNKNOWN_GLYPH EFI_WARN_UNKOWN_GLYPH +#elif !defined(EFI_WARN_UNKNOWN_GLYPH) +#define EFI_WARN_UNKNOWN_GLYPH EFIWARN(1) +#endif + EFI_STATUS console_get_keystroke(EFI_INPUT_KEY *key); -UINTN +UINTN EFIAPI console_print(const CHAR16 *fmt, ...); -UINTN +UINTN EFIAPI console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...); void console_print_box_at(CHAR16 *str_arr[], int highlight, @@ -33,7 +41,15 @@ console_alertbox(CHAR16 **title); void console_notify(CHAR16 *string); void +console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode); +void +console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode); +int +console_countdown(CHAR16* title, const CHAR16* message, int timeout); +void console_reset(void); +void +console_mode_handle(void); #define NOSEL 0x7fffffff typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; @@ -76,12 +92,25 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL { extern VOID console_fini(VOID); extern VOID setup_verbosity(VOID); extern UINT32 verbose; -#define dprint(fmt, ...) ({ \ +#ifndef SHIM_UNIT_TEST +#define dprint_(fmt, ...) ({ \ UINTN __dprint_ret = 0; \ if (verbose) \ __dprint_ret = console_print((fmt), ##__VA_ARGS__); \ __dprint_ret; \ }) +#define dprint(fmt, ...) \ + dprint_(L"%a:%d:%a() " fmt, __FILE__, __LINE__ - 1, __func__, \ + ##__VA_ARGS__) +#else +#define dprint_(...) +#define dprint(fmt, ...) +#endif + +extern EFI_STATUS EFIAPI vdprint_(const CHAR16 *fmt, const char *file, int line, + const char *func, ms_va_list args); +#define vdprint(fmt, ...) \ + vdprint_(fmt, __FILE__, __LINE__ - 1, __func__, ##__VA_ARGS__) extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line); #define crypterr(rc) print_crypto_errors((rc), __FILE__, __func__, __LINE__) diff --git a/include/coverity.mk b/include/coverity.mk new file mode 100644 index 00000000..93d83853 --- /dev/null +++ b/include/coverity.mk @@ -0,0 +1,64 @@ +COV_EMAIL=$(call get-config,coverity.email) +COV_TOKEN=$(call get-config,coverity.token) +COV_URL=$(call get-config,coverity.url) +COV_FILE=$(NAME)-coverity-$(VERSION)-$(COMMIT_ID).tar.bz2 + +include $(TOPDIR)/Make.rules + +define prop +$(if $(findstring undefined,$(origin $(1))),,$(1)="$($1)") +endef + +PROPOGATE_MAKE_FLAGS = ARCH ARCH_SUFFIX COLOR CC COMPILER CROSS_COMPILE + +MAKEARGS = $(foreach x,$(PROPOGATE_MAKE_FLAGS),$(call prop,$(x))) + +cov-clean : + @rm -vf $(NAME)-coverity-*.tar.* + @if [ -d cov-int ]; then rm -rf cov-int && echo "removed 'cov-int'"; fi + +cov-file : | $(COV_FILE) + +$(COV_FILE) : | cov-int + tar caf $@ cov-int + +cov-upload : | cov-file + @if [ -n "$(COV_URL)" ] && \ + [ -n "$(COV_TOKEN)" ] && \ + [ -n "$(COV_EMAIL)" ] ; \ + then \ + echo curl --form token=$(COV_TOKEN) --form email="$(COV_EMAIL)" --form file=@"$(COV_FILE)" --form version=$(VERSION).1 --form description="$(COMMIT_ID)" "$(COV_URL)" ; \ + curl --form token=$(COV_TOKEN) --form email="$(COV_EMAIL)" --form file=@"$(COV_FILE)" --form version=$(VERSION).1 --form description="$(COMMIT_ID)" "$(COV_URL)" ; \ + else \ + echo Coverity output is in $(COV_FILE) ; \ + fi + +cov-build-unchecked-cryptlib : | clean-cryptlib-objs +cov-build-unchecked-cryptlib : Cryptlib/libcryptlib.a + +cov-build-unchecked-openssl : | clean-openssl-objs +cov-build-unchecked-openssl : Cryptlib/OpenSSL/libopenssl.a + +cov-build-all : CCACHE_DISABLE=1 +cov-build-all : | clean clean-shim-objs clean-cryptlib-objs clean-openssl-objs + +cov-build --dir cov-int $(MAKE) $(MAKEARGS) CCACHE_DISABLE=1 all + +coverity-no-openssl : | cov-test +coverity-no-openssl : clean-shim-objs clean-cryptlib-objs cov-build-unchecked-openssl cov-build-all cov-file cov-upload + +coverity-no-cryptlib : | cov-test +coverity-no-cryptlib : clean-shim-objs cov-build-unchecked-openssl cov-build-unchecked-cryptlib cov-build-all cov-file cov-upload + +coverity : | cov-test +coverity : coverity-no-openssl cov-file cov-upload + +coverity-all : | cov-test +coverity-all : clean cov-build-all cov-file cov-upload + +clean : | cov-clean + +COV_BUILD ?= $(shell x=$$(which --skip-alias --skip-functions cov-build 2>/dev/null) ; [ -n "$$x" ] && echo "$$x") + +cov-test : ; $(if $(findstring /,$(COV_BUILD)),,$(error cov-build not found)) + +.PHONY : coverity cov-upload cov-clean cov-file cov-test diff --git a/include/crypt_blowfish.h b/include/crypt_blowfish.h index 8d4dd4da..f89ec700 100644 --- a/include/crypt_blowfish.h +++ b/include/crypt_blowfish.h @@ -1,4 +1,13 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* + * The crypt_blowfish homepage is: + * + * http://www.openwall.com/crypt/ + * + * This code comes from John the Ripper password cracker, with reentrant + * and crypt(3) interfaces added, but optimizations specific to password + * cracking removed. + * * Written by Solar Designer <solar at openwall.com> in 2000-2011. * No copyright is claimed, and the software is hereby placed in the public * domain. In case this attempt to disclaim copyright and place the software diff --git a/include/efiauthenticated.h b/include/efiauthenticated.h index 7157ffd2..f2bcefdb 100644 --- a/include/efiauthenticated.h +++ b/include/efiauthenticated.h @@ -1,7 +1,9 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_EFIAUTHENTICATED_H #define SHIM_EFIAUTHENTICATED_H -#include <wincert.h> +#include "wincert.h" /*********************************************************************** * Signature Database diff --git a/include/endian.h b/include/endian.h new file mode 100644 index 00000000..1c4a21de --- /dev/null +++ b/include/endian.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * endian.h - bswap decls that can't go in compiler.h + * Copyright Peter Jones <pjones@redhat.com> + */ +#ifdef SHIM_UNIT_TEST +#include_next <endian.h> +#endif +#ifndef SHIM_ENDIAN_H_ +#define SHIM_ENDIAN_H_ + +#include <stdint.h> + +#include "system/builtins_begin_.h" +mkbi1_(uint16_t, bswap16, uint16_t, x) +mkbi1_(uint32_t, bswap32, uint32_t, x) +mkbi1_(uint64_t, bswap64, uint64_t, x) +#include "system/builtins_end_.h" + +#endif /* !SHIM_ENDIAN_H_ */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/errors.h b/include/errors.h index 21978bd8..67d821e0 100644 --- a/include/errors.h +++ b/include/errors.h @@ -1,8 +1,8 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_ERRORS_H #define SHIM_ERRORS_H -#include <efierr.h> - #ifndef EFI_INCOMPATIBLE_VERSION #define EFI_INCOMPATIBLE_VERSION EFIERR(25) #endif diff --git a/include/execute.h b/include/execute.h index 18d2fa29..23d17728 100644 --- a/include/execute.h +++ b/include/execute.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_LIB_EXECUTE_H #define SHIM_LIB_EXECUTE_H diff --git a/include/fanalyzer.mk b/include/fanalyzer.mk new file mode 100644 index 00000000..e0bf4d75 --- /dev/null +++ b/include/fanalyzer.mk @@ -0,0 +1,35 @@ +GCC_BINARY ?= $(shell x=$$(which --skip-alias --skip-functions gcc 2>/dev/null) ; [ -n "$$x" ] && echo "$$x") + +fanalyzer-test : ; $(if $(findstring /,$(GCC_BINARY)),,$(error gcc not found)) + +define prop +$(if $(findstring undefined,$(origin $(1))),,$(eval export $(1))) +endef + +PROPOGATE_MAKE_FLAGS = ARCH ARCH_SUFFIX COLOR CC COMPILER CROSS_COMPILE DASHJ + +MAKEARGS = $(foreach x,$(PROPOGATE_MAKE_FLAGS),$(call prop,$(x))) + +fanalyzer : | fanalyzer-test +fanalyzer : fanalyzer-no-openssl + +fanalyzer-build-unchecked-cryptlib : Cryptlib/libcryptlib.a + +fanalyzer-build-unchecked-openssl : Cryptlib/OpenSSL/libopenssl.a + +fanalyzer-build-all : COMPILER=gcc +fanalyzer-build-all : CCACHE_DISABLE=1 +fanalyzer-build-all : FEATUREFLAGS+=-fanalyzer +fanalyzer-build-all : WERRFLAGS=-Werror=analyzer-null-dereference +fanalyzer-build-all : all + +fanalyzer-no-openssl : | fanalyzer-test +fanalyzer-no-openssl : clean-shim-objs clean-cryptlib-objs fanalyzer-build-unchecked-openssl fanalyzer-build-all + +fanalyzer-no-cryptlib : | fanalyzer-test +fanalyzer-no-cryptlib : clean-shim-objs fanalyzer-build-unchecked-openssl fanalyzer-build-unchecked-cryptlib fanalyzer-build-all + +fanalyzer-all : | fanalyzer-test +fanalyzer-all : clean fanalyzer-build-all + +.PHONY : fanalyzer fanalyzer-build fanalyzer-all fanalyzer-build-all fanalyzer-clean diff --git a/include/guid.h b/include/guid.h index 81689d6c..07a19a91 100644 --- a/include/guid.h +++ b/include/guid.h @@ -1,8 +1,8 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_GUID_H #define SHIM_GUID_H -#include <efi.h> - extern EFI_GUID BDS_GUID; extern EFI_GUID GV_GUID; extern EFI_GUID SIG_DB; @@ -35,4 +35,6 @@ extern EFI_GUID SECURITY_PROTOCOL_GUID; extern EFI_GUID SECURITY2_PROTOCOL_GUID; extern EFI_GUID SHIM_LOCK_GUID; +extern EFI_GUID MOK_VARIABLE_STORE; + #endif /* SHIM_GUID_H */ diff --git a/include/hexdump.h b/include/hexdump.h index d337b571..381e1a68 100644 --- a/include/hexdump.h +++ b/include/hexdump.h @@ -1,104 +1,148 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef STATIC_HEXDUMP_H #define STATIC_HEXDUMP_H -static int -__attribute__((__unused__)) -isprint(char c) -{ - if (c < 0x20) - return 0; - if (c > 0x7e) - return 0; - return 1; -} +#include "shim.h" +#include "include/console.h" -static UINTN -__attribute__((__unused__)) -format_hex(UINT8 *data, UINTN size, CHAR16 *buf) +static inline unsigned long UNUSED +prepare_hex(const void *data, size_t size, char *buf, unsigned int position) { - UINTN sz = (UINTN)data % 16; - CHAR16 hexchars[] = L"0123456789abcdef"; + char hexchars[] = "0123456789abcdef"; int offset = 0; - UINTN i; - UINTN j; + unsigned long i; + unsigned long j; + unsigned long ret; - for (i = 0; i < sz; i++) { - buf[offset++] = L' '; - buf[offset++] = L' '; - buf[offset++] = L' '; + unsigned long before = (position % 16); + unsigned long after = (before+size >= 16) ? 0 : 16 - (before+size); + + for (i = 0; i < before; i++) { + buf[offset++] = 'X'; + buf[offset++] = 'X'; + buf[offset++] = ' '; if (i == 7) - buf[offset++] = L' '; + buf[offset++] = ' '; } - for (j = sz; j < 16 && j < size; j++) { - UINT8 d = data[j-sz]; + for (j = 0; j < 16 - after - before; j++) { + uint8_t d = ((uint8_t *)data)[j]; buf[offset++] = hexchars[(d & 0xf0) >> 4]; buf[offset++] = hexchars[(d & 0x0f)]; - if (j != 15) - buf[offset++] = L' '; - if (j == 7) - buf[offset++] = L' '; + if (i+j != 15) + buf[offset++] = ' '; + if (i+j == 7) + buf[offset++] = ' '; } - for (i = j; i < 16; i++) { - buf[offset++] = L' '; - buf[offset++] = L' '; - if (i != 15) - buf[offset++] = L' '; - if (i == 7) - buf[offset++] = L' '; + ret = 16 - after - before; + j += i; + for (i = 0; i < after; i++) { + buf[offset++] = 'X'; + buf[offset++] = 'X'; + if (i+j != 15) + buf[offset++] = ' '; + if (i+j == 7) + buf[offset++] = ' '; } - buf[offset] = L'\0'; - return j - sz; + buf[offset] = '\0'; + return ret; } -static void -__attribute__((__unused__)) -format_text(UINT8 *data, UINTN size, CHAR16 *buf) +static inline void UNUSED +prepare_text(const void *data, size_t size, char *buf, unsigned int position) { - UINTN sz = (UINTN)data % 16; int offset = 0; - UINTN i; - UINTN j; - - for (i = 0; i < sz; i++) - buf[offset++] = L' '; - buf[offset++] = L'|'; - for (j = sz; j < 16 && j < size; j++) { - if (isprint(data[j-sz])) - buf[offset++] = data[j-sz]; + unsigned long i; + unsigned long j; + + unsigned long before = position % 16; + unsigned long after = (before+size > 16) ? 0 : 16 - (before+size); + + if (size == 0) { + buf[0] = '\0'; + return; + } + for (i = 0; i < before; i++) + buf[offset++] = 'X'; + buf[offset++] = '|'; + for (j = 0; j < 16 - after - before; j++) { + if (isprint(((uint8_t *)data)[j])) + buf[offset++] = ((uint8_t *)data)[j]; else - buf[offset++] = L'.'; + buf[offset++] = '.'; } - buf[offset++] = L'|'; - for (i = j; i < 16; i++) - buf[offset++] = L' '; - buf[offset] = L'\0'; + buf[offset++] = size > 0 ? '|' : 'X'; + buf[offset] = '\0'; } -static void -__attribute__((__unused__)) -hexdump(UINT8 *data, UINTN size) +/* + * variadic hexdump formatted + * think of it as: printf("%s%s\n", vformat(fmt, ap), hexdump(data,size)); + */ +static inline void UNUSED EFIAPI +vhexdumpf(const char *file, int line, const char *func, const CHAR16 *const fmt, + const void *data, unsigned long size, size_t at, ms_va_list ap) { - UINTN display_offset = (UINTN)data & 0xffffffff; - UINTN offset = 0; - //console_print(L"hexdump: data=0x%016x size=0x%x\n", data, size); + unsigned long display_offset = at; + unsigned long offset = 0; + + if (verbose == 0) + return; while (offset < size) { - CHAR16 hexbuf[49]; - CHAR16 txtbuf[19]; - UINTN sz; + char hexbuf[49]; + char txtbuf[19]; + unsigned long sz; - sz = format_hex(data+offset, size-offset, hexbuf); + sz = prepare_hex(data+offset, size-offset, hexbuf, + (unsigned long)data+offset); if (sz == 0) return; - msleep(200000); - format_text(data+offset, size-offset, txtbuf); - console_print(L"%08x %s %s\n", display_offset, hexbuf, txtbuf); - msleep(200000); + prepare_text(data+offset, size-offset, txtbuf, + (unsigned long)data+offset); + if (fmt && fmt[0] != 0) + vdprint_(fmt, file, line, func, ap); + dprint_(L"%a:%d:%a() %08lx %a %a\n", file, line, func, display_offset, hexbuf, txtbuf); display_offset += sz; offset += sz; } } +/* + * hexdump formatted + * think of it as: printf("%s%s", format(fmt, ...), hexdump(data,size)[lineN]); + */ +static inline void UNUSED EFIAPI +hexdumpf(const char *file, int line, const char *func, const CHAR16 *const fmt, + const void *data, unsigned long size, size_t at, ...) +{ + ms_va_list ap; + + ms_va_start(ap, at); + vhexdumpf(file, line, func, fmt, data, size, at, ap); + ms_va_end(ap); +} + +static inline void UNUSED +hexdump(const char *file, int line, const char *func, const void *data, unsigned long size) +{ + hexdumpf(file, line, func, L"", data, size, (intptr_t)data); +} + +static inline void UNUSED +hexdumpat(const char *file, int line, const char *func, const void *data, unsigned long size, size_t at) +{ + hexdumpf(file, line, func, L"", data, size, at); +} + +#define LogHexdump(data, sz) LogHexdump_(__FILE__, __LINE__, __func__, data, sz) +#define dhexdump(data, sz) hexdump(__FILE__, __LINE__, __func__, data, sz) +#define dhexdumpat(data, sz, at) \ + hexdumpat(__FILE__, __LINE__ - 1, __func__, data, sz, at) +#define dhexdumpf(fmt, data, sz, at, ...) \ + hexdumpf(__FILE__, __LINE__ - 1, __func__, fmt, data, sz, at, ##__VA_ARGS__) + #endif /* STATIC_HEXDUMP_H */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/Http.h b/include/http.h index 4b3746a7..c89047db 100644 --- a/include/Http.h +++ b/include/http.h @@ -1,23 +1,14 @@ -/** @file - This file defines the EFI HTTP Protocol interface. It is split into - the following two main sections: - HTTP Service Binding Protocol (HTTPSB) - HTTP Protocol (HTTP) - - Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> - (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> - This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - - @par Revision Reference: - This Protocol is introduced in UEFI Specification 2.5 - -**/ +// SPDX-License-Identifier: BSD-2-Clause-Patent + +/* + * This file defines the EFI HTTP Protocol interface. It is split into + * the following two main sections: + * HTTP Service Binding Protocol (HTTPSB) + * HTTP Protocol (HTTP) + * + * Copyright (c) 2016, Intel Corporation. All rights reserved. + * Copyright 2015 Hewlett Packard Enterprise Development LP + */ #ifndef SHIM_HTTP_H #define SHIM_HTTP_H diff --git a/include/httpboot.h b/include/httpboot.h index b47f6a9d..ea9c57fe 100644 --- a/include/httpboot.h +++ b/include/httpboot.h @@ -1,31 +1,7 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2015 SUSE LINUX GmbH <glin@suse.com> * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * * Significant portions of this code are derived from Tianocore * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel * Corporation. diff --git a/include/Ip4Config2.h b/include/ip4config2.h index efacaf83..8fd8dfcb 100644 --- a/include/Ip4Config2.h +++ b/include/ip4config2.h @@ -1,25 +1,14 @@ -/** @file - This file provides a definition of the EFI IPv4 Configuration II - Protocol. +// SPDX-License-Identifier: BSD-2-Clause-Patent -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at<BR> -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -@par Revision Reference: -This Protocol is introduced in UEFI Specification 2.5 - -**/ +/* + * This file provides a definition of the EFI IPv4 Configuration II + * Protocol. + * + * Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved. + */ #ifndef SHIM_IP4CONFIG2_H #define SHIM_IP4CONFIG2_H -#include <efiip.h> - typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL; diff --git a/include/Ip6Config.h b/include/ip6config.h index f99ce013..58cef532 100644 --- a/include/Ip6Config.h +++ b/include/ip6config.h @@ -1,22 +1,13 @@ -/** @file - This file provides a definition of the EFI IPv6 Configuration - Protocol. - -Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR> -This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at<BR> -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * This file provides a definition of the EFI IPv6 Configuration + * Protocol. + * + * Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved. + */ #ifndef SHIM_IP6CONFIG_H #define SHIM_IP6CONFIG_H -#include <efiip.h> - typedef struct _EFI_IP6_CONFIG_PROTOCOL EFI_IP6_CONFIG_PROTOCOL; /// diff --git a/include/list.h b/include/list.h new file mode 100644 index 00000000..1d36e163 --- /dev/null +++ b/include/list.h @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * list.h - simple list primitives + */ + +#ifndef LIST_H_ +#define LIST_H_ + +#define container_of(ptr, type, member) \ + ({ \ + void *__mptr = (void *)(ptr); \ + ((type *)(__mptr - offsetof(type, member))); \ + }) + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +typedef struct list_head list_t; + +#define LIST_HEAD_INIT(name) \ + { \ + .next = &(name), .prev = &(name) \ + } + +#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) \ + ({ \ + (ptr)->next = (ptr); \ + (ptr)->prev = (ptr); \ + }) + +static inline int +list_empty(const struct list_head *head) +{ + return head->next == head; +} + +static inline void +__list_add(struct list_head *new, struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +static inline void +list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +static inline void +list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +static inline void +__list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void +__list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static inline void +list_del(struct list_head *entry) +{ + __list_del_entry(entry); + entry->next = NULL; + entry->prev = NULL; +} + +#define list_entry(ptr, type, member) container_of(ptr, type, member) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member) + +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; pos != (head); \ + pos = n, n = pos->prev) + +static inline size_t +list_size(struct list_head *entry) +{ + list_t *pos; + size_t i = 0; + list_for_each(pos, entry) { + i++; + } + return i; +} + +#endif /* !LIST_H_ */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/netboot.h b/include/netboot.h index d1ad1257..98b174a3 100644 --- a/include/netboot.h +++ b/include/netboot.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_NETBOOT_H #define SHIM_NETBOOT_H diff --git a/include/PasswordCrypt.h b/include/passwordcrypt.h index cadad727..4c0e3607 100644 --- a/include/PasswordCrypt.h +++ b/include/passwordcrypt.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_PASSWORDCRYPT_H #define SHIM_PASSWORDCRYPT_H diff --git a/include/pe.h b/include/pe.h new file mode 100644 index 00000000..79bf440c --- /dev/null +++ b/include/pe.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * pe.h - helper functions for pe binaries. + * Copyright Peter Jones <pjones@redhat.com> + */ + +#ifndef PE_H_ +#define PE_H_ + +void * +ImageAddress (void *image, uint64_t size, uint64_t address); + +EFI_STATUS +read_header(void *data, unsigned int datasize, + PE_COFF_LOADER_IMAGE_CONTEXT *context); + +EFI_STATUS +handle_sbat(char *SBATBase, size_t SBATSize); + +EFI_STATUS +handle_image (void *data, unsigned int datasize, + EFI_LOADED_IMAGE *li, + EFI_IMAGE_ENTRY_POINT *entry_point, + EFI_PHYSICAL_ADDRESS *alloc_address, + UINTN *alloc_pages); + +EFI_STATUS +generate_hash (char *data, unsigned int datasize_in, + PE_COFF_LOADER_IMAGE_CONTEXT *context, + UINT8 *sha256hash, UINT8 *sha1hash); + +EFI_STATUS +relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, + EFI_IMAGE_SECTION_HEADER *Section, + void *orig, void *data); + +#endif /* !PE_H_ */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/PeImage.h b/include/peimage.h index a606e8b2..3b3f01a7 100644 --- a/include/PeImage.h +++ b/include/peimage.h @@ -1,28 +1,21 @@ -/** @file
- EFI image format for PE32, PE32+ and TE. Please note some data structures are
- different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
- EFI_IMAGE_NT_HEADERS64 is for PE32+.
-
- This file is coded to the Visual Studio, Microsoft Portable Executable and
- Common Object File Format Specification, Revision 8.0 - May 16, 2006.
- This file also includes some definitions in PI Specification, Revision 1.0.
-
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
-Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php.
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+/*
+ * EFI image format for PE32, PE32+ and TE. Please note some data structures
+ * are different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
+ * EFI_IMAGE_NT_HEADERS64 is for PE32+.
+ *
+ * This file is coded to the Visual Studio, Microsoft Portable Executable and
+ * Common Object File Format Specification, Revision 8.0 - May 16, 2006. This
+ * file also includes some definitions in PI Specification, Revision 1.0.
+ *
+ * Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ * Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ */
#ifndef SHIM_PEIMAGE_H
#define SHIM_PEIMAGE_H
-#include <wincert.h>
+#include "wincert.h"
#define SIGNATURE_16(A, B) ((A) | (B << 8))
#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
@@ -768,7 +761,8 @@ typedef struct { UINT8 CertData[1];
} WIN_CERTIFICATE_EFI_PKCS;
-#define SHA256_DIGEST_SIZE 32
+#define SHA1_DIGEST_SIZE 20
+#define SHA256_DIGEST_SIZE 32
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
typedef struct {
diff --git a/include/replacements.h b/include/replacements.h index ab2a5a58..8b35c857 100644 --- a/include/replacements.h +++ b/include/replacements.h @@ -1,30 +1,8 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + /* - * Copyright 2013 Red Hat, Inc <pjones@redhat.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright Red Hat, Inc + * Copyright Peter Jones <pjones@redhat.com> */ #ifndef SHIM_REPLACEMENTS_H #define SHIM_REPLACEMENTS_H diff --git a/include/sbat.h b/include/sbat.h new file mode 100644 index 00000000..5db82379 --- /dev/null +++ b/include/sbat.h @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * sbat.c - parse SBAT data from the .sbat section data + */ + +#ifndef SBAT_H_ +#define SBAT_H_ + +#define SBAT_VAR_SIG "sbat," +#define SBAT_VAR_VERSION "1," +#define SBAT_VAR_DATE "2021030218" +#define SBAT_VAR SBAT_VAR_SIG SBAT_VAR_VERSION SBAT_VAR_DATE "\n" + +#define UEFI_VAR_NV_BS \ + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS) +#define UEFI_VAR_NV_BS_RT \ + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS) +#define UEFI_VAR_NV_BS_TIMEAUTH \ + (UEFI_VAR_NV_BS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + +#if defined(ENABLE_SHIM_DEVEL) +#define SBAT_VAR_NAME L"SBAT_DEVEL" +#define SBAT_VAR_NAME8 "SBAT_DEVEL" +#define SBAT_RT_VAR_NAME L"SbatRT_DEVEL" +#define SBAT_RT_VAR_NAME8 "SbatRT_DEVEL" +#define SBAT_VAR_ATTRS UEFI_VAR_NV_BS_RT +#else +#define SBAT_VAR_NAME L"SBAT" +#define SBAT_VAR_NAME8 "SBAT" +#define SBAT_RT_VAR_NAME L"SbatRT" +#define SBAT_RT_VAR_NAME8 "SbatRT" +#define SBAT_VAR_ATTRS UEFI_VAR_NV_BS +#endif + +extern UINTN _sbat, _esbat; + +struct sbat_var_entry { + const CHAR8 *component_name; + const CHAR8 *component_generation; + /* + * This column is only actually on the "sbat" version entry + */ + const CHAR8 *sbat_datestamp; + list_t list; +}; +extern list_t sbat_var; +#define SBAT_VAR_COLUMNS ((sizeof (struct sbat_var_entry) - sizeof(list_t)) / sizeof(CHAR8 *)) +#define SBAT_VAR_REQUIRED_COLUMNS (SBAT_VAR_COLUMNS - 1) + +EFI_STATUS parse_sbat_var(list_t *entries); +void cleanup_sbat_var(list_t *entries); +EFI_STATUS set_sbat_uefi_variable(void); + +struct sbat_section_entry { + const CHAR8 *component_name; + const CHAR8 *component_generation; + const CHAR8 *vendor_name; + const CHAR8 *vendor_package_name; + const CHAR8 *vendor_version; + const CHAR8 *vendor_url; +}; +#define SBAT_SECTION_COLUMNS (sizeof (struct sbat_section_entry) / sizeof(CHAR8 *)) + +EFI_STATUS +parse_sbat_section(char *section_base, size_t section_size, size_t *n, + struct sbat_section_entry ***entriesp); +void cleanup_sbat_section_entries(size_t n, struct sbat_section_entry **entries); + +EFI_STATUS verify_sbat(size_t n, struct sbat_section_entry **entries); + +#ifdef SHIM_UNIT_TEST +EFI_STATUS parse_sbat_var_data(list_t *entries, UINT8 *data, UINTN datasize); +EFI_STATUS verify_sbat_helper(list_t *sbat_var, size_t n, + struct sbat_section_entry **entries); +#endif /* !SHIM_UNIT_TEST */ +#endif /* !SBAT_H_ */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/scan-build.mk b/include/scan-build.mk new file mode 100644 index 00000000..3ed7660e --- /dev/null +++ b/include/scan-build.mk @@ -0,0 +1,38 @@ +SCAN_BUILD ?= $(shell x=$$(which --skip-alias --skip-functions scan-build 2>/dev/null) ; [ -n "$$x" ] && echo "$$x") + +scan-test : ; $(if $(findstring /,$(SCAN_BUILD)),,$(error scan-build not found)) + +define prop +$(if $(findstring undefined,$(origin $(1))),,$(1)="$($1)") +endef + +PROPOGATE_MAKE_FLAGS = ARCH ARCH_SUFFIX COLOR CC COMPILER CROSS_COMPILE DASHJ + +MAKEARGS = $(foreach x,$(PROPOGATE_MAKE_FLAGS),$(call prop,$(x))) + +scan-clean : + @if [[ -d scan-results ]]; then rm -rf scan-results && echo "removed 'scan-results'"; fi + +scan : | scan-test +scan : clean-shim-objs clean-cryptlib-objs scan-build-no-openssl + +scan-build-unchecked-cryptlib : Cryptlib/libcryptlib.a + +scan-build-unchecked-openssl : Cryptlib/OpenSSL/libopenssl.a + +scan-build-all : CCACHE_DISABLE=1 +scan-build-all : COMPILER=clang +scan-build-all : | scan-test +scan-build-all : + +scan-build -o scan-results make $(MAKEARGS) $(DASHJ) CCACHE_DISABLE=1 all + +scan-build-no-openssl : | scan-test +scan-build-no-openssl : clean-shim-objs clean-cryptlib-objs scan-build-unchecked-openssl scan-build-all + +scan-build-no-cryptlib : | scan-test +scan-build-no-cryptlib : clean-shim-objs scan-build-unchecked-cryptlib scan-build-unchecked-openssl scan-build-all + +scan-all : | scan-test +scan-all : clean scan-build-all + +.PHONY : scan-build scan-clean diff --git a/include/security_policy.h b/include/security_policy.h index 7cfbfd03..e03653d2 100644 --- a/include/security_policy.h +++ b/include/security_policy.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_SECURITY_POLICY_H #define SHIM_SECURITY_POLICY_H diff --git a/include/shell.h b/include/shell.h index fec50137..579a92f5 100644 --- a/include/shell.h +++ b/include/shell.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_SHELL_H #define SHIM_SHELL_H diff --git a/include/simple_file.h b/include/simple_file.h index 7b019654..b3976626 100644 --- a/include/simple_file.h +++ b/include/simple_file.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_SIMPLE_FILE_H #define SHIM_SIMPLE_FILE_H diff --git a/include/str.h b/include/str.h index 9a748366..d433e6ec 100644 --- a/include/str.h +++ b/include/str.h @@ -1,65 +1,152 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_STR_H #define SHIM_STR_H -static inline -__attribute__((unused)) -unsigned long strnlena(const CHAR8 *s, unsigned long n) -{ - unsigned long i; - for (i = 0; i <= n; i++) - if (s[i] == '\0') - break; - return i; -} +#if __GNUC__ > 6 +#ifdef SHIM_UNIT_TEST +#pragma GCC diagnostic error "-Wnonnull-compare" +#else +#pragma GCC diagnostic ignored "-Wnonnull-compare" +#endif +#endif -static inline -__attribute__((unused)) -CHAR8 * -strncpya(CHAR8 *dest, const CHAR8 *src, unsigned long n) +static inline UNUSED RETURNS_NONNULL NONNULL(1) +char * +strnchrnul(const char *s, size_t max, int c) { - unsigned long i; + unsigned int i; + + if (!s || !max) + return (char *)s; + + for (i = 0; i < max && s[i] != '\0' && s[i] != c; i++) + ; - for (i = 0; i < n && src[i] != '\0'; i++) - dest[i] = src[i]; - for (; i < n; i++) - dest[i] = '\0'; + if (i == max) + i--; - return dest; + return (char *)&s[i]; } -static inline -__attribute__((unused)) -CHAR8 * -strcata(CHAR8 *dest, const CHAR8 *src) +/** + * strntoken: tokenize a string, with a limit + * str: your string (will be modified) + * max: maximum number of bytes to ever touch + * delims: string of one character delimeters, any of which will tokenize + * *token: the token we're passing back (must be a pointer to NULL initially) + * state: a pointer to one char of state for between calls + * + * Ensure that both token and state are preserved across calls. Do: + * char state = 0; + * char *token = NULL; + * for (...) { + * valid = strntoken(...) + * not: + * char state = 0; + * for (...) { + * char *token = NULL; + * valid = strntoken(...) + * + * - it will not test bytes beyond str[max-1] + * - it will not set *token to an address beyond &str[max-1] + * - it will set *token to &str[max-1] without testing &str[max-2] for + * &str[max-1] == str + * - sequences of multiple delimeters will result in empty (pointer to '\0') + * tokens. + * - it expects you to update str and max on successive calls. + * + * return: + * true means it hasn't tested str[max-1] yet and token is valid + * false means it got to a NUL or str[max-1] and token is invalid + */ +static inline UNUSED NONNULL(1, 3, 4) int +strntoken(char *str, size_t max, const char *delims, char **token, char *state) { - unsigned long dest_len = strlena(dest); - unsigned long i; + char *tokend; + const char *delim; + int isdelim = 0; + int state_is_delim = 0; - for (i = 0; src[i] != '\0'; i++) - dest[dest_len + i] = src[i]; - dest[dest_len + i] = '\0'; + if (!str || !max || !delims || !token || !state) + return 0; - return dest; + tokend = &str[max-1]; + if (!str || max == 0 || !delims || !token) + return 0; + + /* + * the very special case of "" with max=1, where we have no prior + * state to let us know this is the same as right after a delim + */ + if (*token == NULL && max == 1 && *str == '\0') { + state_is_delim = 1; + } + + for (delim = delims; *delim; delim++) { + char *tmp = NULL; + if (*token && *delim == *state) + state_is_delim = 1; + tmp = strnchrnul(str, max, *delim); + if (tmp < tokend) + tokend = tmp; + if (*tokend == *delim) + isdelim = 1; + } + *token = str; + if (isdelim) { + *state = *tokend; + *tokend = '\0'; + return 1; + } + return state_is_delim; } -static inline -__attribute__((unused)) -CHAR8 * -translate_slashes(char *str) +#define UTF8_BOM { 0xef, 0xbb, 0xbf } +#define UTF8_BOM_SIZE 3 + +static inline UNUSED NONNULL(1) BOOLEAN +is_utf8_bom(CHAR8 *buf, size_t bufsize) { - int i; - int j; - if (str == NULL) - return (CHAR8 *)str; - - for (i = 0, j = 0; str[i] != '\0'; i++, j++) { - if (str[i] == '\\') { - str[j] = '/'; - if (str[i+1] == '\\') - i++; - } - } - return (CHAR8 *)str; + unsigned char bom[] = UTF8_BOM; + + return CompareMem(buf, bom, MIN(UTF8_BOM_SIZE, bufsize)) == 0; } +/** + * parse CSV data from data to end. + * *data points to the first byte of the data + * end points to a NUL byte at the end of the data + * n_columns number of columns per entry + * list the list head we're adding to + * + * On success, list will be populated with individually allocate a list of + * struct csv_list objects, with one column per entry of the "columns" array, + * filled left to right with up to n_columns elements, or NULL when a csv line + * does not have enough elements. + * + * Note that the data will be modified; all comma, linefeed, and newline + * characters will be set to '\000'. Additionally, consecutive linefeed and + * newline characters will not result in rows in the results. + * + * On failure, list will be empty and all entries on it will have been freed, + * using free_csv_list(), whether they were there before calling + * parse_csv_data or not. + */ + +struct csv_row { + list_t list; /* this is a linked list */ + size_t n_columns; /* this is how many columns are actually populated */ + char *columns[0]; /* these are pointers to columns */ +}; + +EFI_STATUS parse_csv_data(char *data, char *end, size_t n_columns, + list_t *list); +void free_csv_list(list_t *list); + +#ifdef SHIM_UNIT_TEST +void NONNULL(1, 3, 4) +parse_csv_line(char * line, size_t max, size_t *n_columns, const char *columns[]); +#endif + #endif /* SHIM_STR_H */ diff --git a/include/system/alloca.h b/include/system/alloca.h new file mode 100644 index 00000000..a9d1aab1 --- /dev/null +++ b/include/system/alloca.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +#ifdef SHIM_UNIT_TEST +#include_next <alloca.h> +#else +#ifndef _ALLOCA_H +#define _ALLOCA_H + +#include <builtins_begin_.h> +mkbi1_(void *, alloca, size_t, size) +#define alloca_with_align(size, alignment) __builtin_alloca_with_align(size, alignment) +#define alloca_with_align_and_max(size, alignment, max) __builtin_alloca_with_align_and_max(size, alignment, max) +#include <builtins_end_.h> + +#endif /* !_ALLOCA_H */ +#endif +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/builtins_begin_.h b/include/system/builtins_begin_.h new file mode 100644 index 00000000..2686c41c --- /dev/null +++ b/include/system/builtins_begin_.h @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/** + * macros to build function declarations with the same types as builtins + * that we apparently really cannot depend on. + */ + +/* + * Clang's __builtin_whatever and __typeof__ are broken thusly: + * In file included from MokManager.c:2: + * In file included from shim.h:47: + * include/system/string.h:29:1: error: builtin functions must be directly called + * mkbi1_(long int, ffsl, long int, x) + * ^ + */ +#if defined(__clang__) + +#ifndef mkbi1_ +#define mkbi1_(rtype, x, typea, a) rtype x(typea a); +#endif + +#ifndef mkbi2_ +#define mkbi2_(rtype, x, typea, a, typeb, b) rtype x(typea a, typeb b); +#endif + +#ifndef mkbi3_ +#define mkbi3_(rtype, x, typea, a, typeb, b, typec, c) rtype x(typea a, typeb b, typec c); +#endif + +#ifndef mkdepbi1_ +#define mkdepbi1_(rtype, x, typea, a) rtype x(typea a); +#endif + +#ifndef mkdepbi2_ +#define mkdepbi2_(rtype, x, typea, a, typeb, b) rtype x(typea a, typeb b); +#endif + +#else /* !__clang__ */ + +#ifndef mkbi_cat_ +#define mkbi_cat_(a, b) a##b +#endif + +#ifndef mkbi1_ +#define mkbi1_(rtype, x, typea, a) __typeof__(mkbi_cat_(__builtin_, x)) x; +#endif + +#ifndef mkbi2_ +#define mkbi2_(rtype, x, typea, a, typeb, b) __typeof__(mkbi_cat_(__builtin_, x)) x; +#endif + +#ifndef mkbi3_ +#define mkbi3_(rtype, x, typea, a, typeb, b, typec, c) __typeof__(mkbi_cat_(__builtin_, x)) x; +#endif + +#ifndef mkdepbi1_ +#define mkdepbi1_(rtype, x, typea, a) __typeof__(mkbi_cat_(__builtin_, x)) x; +#endif + +#ifndef mkdepbi2_ +#define mkdepbi2_(rtype, x, typea, a, typeb, b) __typeof__(mkbi_cat_(__builtin_, x)) x; +#endif + +#endif /* !__clang__ */ + +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/builtins_end_.h b/include/system/builtins_end_.h new file mode 100644 index 00000000..0bcd7661 --- /dev/null +++ b/include/system/builtins_end_.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + +#ifdef mkbi1_ +#undef mkbi1_ +#endif + +#ifdef mkbi2_ +#undef mkbi2_ +#endif + +#ifdef mkbi3_ +#undef mkbi3_ +#endif + +#ifdef mkdepbi1_ +#undef mkdepbi1_ +#endif + +#ifdef mkdepbi2_ +#undef mkdepbi2_ +#endif + +#ifdef mkbi_cat_ +#undef mkbi_cat_ +#endif + +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/ctype.h b/include/system/ctype.h new file mode 100644 index 00000000..65e7348f --- /dev/null +++ b/include/system/ctype.h @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * ctype.h - standard ctype functions + */ +#ifdef SHIM_UNIT_TEST +#include_next <ctype.h> +#else +#ifndef _CTYPE_H +#define _CTYPE_H + +#define isprint(c) ((c) >= 0x20 && (c) <= 0x7e) + +/* Determines if a particular character is a decimal-digit character */ +static inline __attribute__((__unused__)) int +isdigit(int c) +{ + // + // <digit> ::= [0-9] + // + return (('0' <= (c)) && ((c) <= '9')); +} + +/* Determine if an integer represents character that is a hex digit */ +static inline __attribute__((__unused__)) int +isxdigit(int c) +{ + // + // <hexdigit> ::= [0-9] | [a-f] | [A-F] + // + return ((('0' <= (c)) && ((c) <= '9')) || + (('a' <= (c)) && ((c) <= 'f')) || + (('A' <= (c)) && ((c) <= 'F'))); +} + +/* Determines if a particular character represents a space character */ +static inline __attribute__((__unused__)) int +isspace(int c) +{ + // + // <space> ::= [ ] + // + return ((c) == ' '); +} + +/* Determine if a particular character is an alphanumeric character */ +static inline __attribute__((__unused__)) int +isalnum(int c) +{ + // + // <alnum> ::= [0-9] | [a-z] | [A-Z] + // + return ((('0' <= (c)) && ((c) <= '9')) || + (('a' <= (c)) && ((c) <= 'z')) || + (('A' <= (c)) && ((c) <= 'Z'))); +} + +/* Determines if a particular character is in upper case */ +static inline __attribute__((__unused__)) int +isupper(int c) +{ + // + // <uppercase letter> := [A-Z] + // + return (('A' <= (c)) && ((c) <= 'Z')); +} + +/* Convert character to lowercase */ +static inline __attribute__((__unused__)) int +tolower(int c) +{ + if (('A' <= (c)) && ((c) <= 'Z')) { + return (c - ('A' - 'a')); + } + return (c); +} + +static inline __attribute__((__unused__)) int +toupper(int c) +{ + return ((c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c); +} + +#endif /* !_CTYPE_H */ +#endif /* !SHIM_UNIT_TEST */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/efistdarg.h b/include/system/efistdarg.h new file mode 100644 index 00000000..034977cc --- /dev/null +++ b/include/system/efistdarg.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * efistdarg.h - AAAARGGGG + * Copyright Peter Jones <pjones@redhat.com> + */ + +#ifndef SHIM_UNIT_TEST +#ifndef _EFISTDARG_H_ +#define _EFISTDARG_H_ + +#ifndef GNU_EFI_USE_EXTERNAL_STDARG +#define GNU_EFI_USE_EXTERNAL_STDARG +#endif + +#include <stdarg.h> + +#endif /* !_EFISTDARG_H_ */ +#endif +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/inttypes.h b/include/system/inttypes.h new file mode 100644 index 00000000..a35b0090 --- /dev/null +++ b/include/system/inttypes.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +#ifdef SHIM_UNIT_TEST +#include_next <inttypes.h> +#else +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include <stddef.h> +#include <stdint.h> + +#endif /* !INTTYPES_H_ */ +#endif +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/stdarg.h b/include/system/stdarg.h new file mode 100644 index 00000000..4c956f70 --- /dev/null +++ b/include/system/stdarg.h @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * stdarg.h - try to make consistent va_* handling for EFI + */ +#ifndef _STDARG_H + +/* + * clang doesn't know about __builtin_sysv_va_list, apparently. + */ +#ifdef __clang__ +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wcpp" +typedef __builtin_va_list __builtin_sysv_va_list; +#warning clang builds may not work at all for anything other than scan-build +#pragma GCC diagnostic pop +#endif + +#ifndef GNU_EFI_USE_EXTERNAL_STDARG +#define GNU_EFI_USE_EXTERNAL_STDARG +#endif + +#ifdef SHIM_UNIT_TEST +#include_next <stdarg.h> +#endif + +#if defined(__aarch64__) || defined(__arm__) || defined(__i386__) || \ + defined(__i486__) || defined(__i686__) + +typedef __builtin_va_list ms_va_list; +typedef __builtin_va_list __builtin_ms_va_list; +#define ms_va_copy(dest, start) __builtin_va_copy(dest, start) +#define ms_va_start(marker, arg) __builtin_va_start(marker, arg) +#define ms_va_arg(marker, type) __builtin_va_arg(marker, type) +#define ms_va_end(marker) __builtin_va_end(marker) + +typedef __builtin_va_list sysv_va_list; +#define sysv_va_copy(dest, start) __builtin_va_copy(dest, start) +#define sysv_va_start(marker, arg) __builtin_va_start(marker, arg) +#define sysv_va_arg(marker, type) __builtin_va_arg(marker, type) +#define sysv_va_end(marker) __builtin_va_end(marker) +/* + * OpenSSL's X509ConstructCertificateStack needs this. + */ +typedef __builtin_va_list VA_LIST; +#define VA_COPY(dest, start) __builtin_va_copy(dest, start) +#define VA_START(marker, arg) __builtin_va_start(marker, arg) +#define VA_END(marker) __builtin_va_end(marker) +#define VA_ARG(marker, type) __builtin_va_arg(marker, type) + +#elif defined(__x86_64__) + +typedef __builtin_ms_va_list ms_va_list; +#define ms_va_copy(dest, start) __builtin_ms_va_copy(dest, start) +#define ms_va_start(marker, arg) __builtin_ms_va_start(marker, arg) +#define ms_va_arg(marker, type) __builtin_va_arg(marker, type) +#define ms_va_end(marker) __builtin_ms_va_end(marker) +typedef __builtin_sysv_va_list sysv_va_list; +#define sysv_va_copy(dest, start) __builtin_sysv_va_copy(dest, start) +#define sysv_va_start(marker, arg) __builtin_sysv_va_start(marker, arg) +#define sysv_va_arg(marker, type) __builtin_va_arg(marker, type) +#define sysv_va_end(marker) __builtin_sysv_va_end(marker) +/* + * OpenSSL's X509ConstructCertificateStack needs this. + */ +typedef __builtin_ms_va_list VA_LIST; +#define VA_COPY(dest, start) __builtin_ms_va_copy(dest, start) +#define VA_START(marker, arg) __builtin_ms_va_start(marker, arg) +#define VA_END(marker) __builtin_ms_va_end(marker) +#define VA_ARG(marker, type) __builtin_va_arg(marker, type) + +#else +#error what arch is this +#endif + +#ifndef _STDARG_H +#define _STDARG_H +#endif /* !_STDARG_H #2 */ + +#endif /* !_STDARG_H */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/stdio.h b/include/system/stdio.h new file mode 100644 index 00000000..6ea60d71 --- /dev/null +++ b/include/system/stdio.h @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * stdio.h - sigh + */ +#ifdef SHIM_UNIT_TEST +#include_next <stdio.h> +#else +#ifndef _STDIO_H +#define _STDIO_H + +#endif /* !_STDIO_H */ +#endif +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/stdlib.h b/include/system/stdlib.h new file mode 100644 index 00000000..da7d3af9 --- /dev/null +++ b/include/system/stdlib.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +#ifdef SHIM_UNIT_TEST +#include_next <stdlib.h> +#else +#ifndef _STDLIB_H +#define _STDLIB_H + +/* + * I don't know why, but openssl expects to get size_t from stdlib.h + * instead of stddef.h, so... whatever. + */ +#include <stddef.h> + +static inline void abort(void) { } + +#include <builtins_begin_.h> +mkbi1_(int, abs, int, j) +mkbi1_(long int, labs, long int, j) +mkbi1_(long long int, llabs, long long int, j) + +#ifdef _INTTYPES_H +mkbi1_(intmax_t, imaxabs, intmax_t, j) +#endif /* _INTTYPES_H */ +#include <builtins_end_.h> + +#endif /* !_STDLIB_H */ +#endif +// vim:fenc=utf-8:tw=75:noet diff --git a/include/system/string.h b/include/system/string.h new file mode 100644 index 00000000..2b366df7 --- /dev/null +++ b/include/system/string.h @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +#ifdef SHIM_UNIT_TEST +#include_next <string.h> + +__typeof__(strlen) shim_strlen; +__typeof__(strcmp) shim_strcmp; +__typeof__(strncmp) shim_strncmp; +__typeof__(strncasecmp) shim_strncasecmp; +__typeof__(strcasecmp) shim_strcasecmp; +__typeof__(strrchr) shim_strrchr; +__typeof__(strrchr) shim_strrchr; +__typeof__(strnlen) shim_strnlen; +__typeof__(strcpy) shim_strcpy; +__typeof__(strncpy) shim_strncpy; +__typeof__(strdup) shim_strdup; +__typeof__(strndup) shim_strndup; +__typeof__(stpcpy) shim_stpcpy; +__typeof__(strchrnul) shim_strchrnul; +__typeof__(strchr) shim_strchr; + +#else +#ifndef _STRING_H +#define _STRING_H + +#include <stddef.h> + +#include <builtins_begin_.h> + +mkbi1_(long int, ffsl, long int, x) +mkbi1_(long int, clzl, long int, x) +mkbi1_(long int, ctzl, long int, x) +mkbi1_(long int, clrsbl, long int, x) +mkbi1_(long int, popcountl, long int, x) +mkbi1_(long int, parityl, long int, x) +mkbi1_(long long int, ffsll, long long int, x) +mkbi1_(long long int, clzll, long long int, x) +mkbi1_(long long int, ctzll, long long int, x) +mkbi1_(long long int, clrsbll, long long int, x) +mkbi1_(long long int, popcountll, long long int, x) +mkbi1_(long long int, parityll, long long int, x) + +mkbi3_(int, bcmp, const void *, s1, const void *, s2, size_t, n) +mkbi3_(void, bcopy, const void *, src, void *, dest, size_t, n) +mkbi2_(void, bzero, void *, s, size_t, n) +mkdepbi2_(char *, index, const char *, s, int, c) +mkbi3_(void *, memchr, const void *, s, int, c, size_t, n) +mkbi3_(int, memcmp, const void *, s1, const void *, s2, size_t, n) +mkbi3_(void *, memcpy, void *, dest, const void *, src, size_t, n) +mkbi3_(void *, memmove, void *, dest, const void *, src, size_t, n) +mkbi3_(void *, mempcpy, void *, dest, const void *, src, size_t, n) +mkdepbi2_(char *, rindex, const char *, s, int, c) +mkdepbi2_(char *, stpcpy, char *, dest, const char *, src) +mkbi3_(char *, stpncpy, char *, dest, const char *, src, size_t, n) +mkdepbi2_(int, strcasecmp, const char *, s1, const char *, s2) +mkdepbi2_(char *, strcat, char *, dest, const char *, src) +mkdepbi2_(char *, strchr, const char *, s, int, c) +mkdepbi2_(int, strcmp, const char *, s1, const char *, s2) +mkdepbi2_(char *, strcpy, char *, dest, const char *, src) +mkdepbi2_(size_t, strcspn, const char *, s, const char *, reject) +mkdepbi1_(char *, strdup, const char *, s) +mkbi2_(char *, strndup, const char *, s, size_t, n) +mkdepbi1_(size_t, strlen, const char *, s) +mkbi3_(int, strncasecmp, const char *, s1, const char *, s2, size_t, n) +mkbi3_(char *, strncat, char *, dest, const char *, src, size_t, n) +mkbi3_(int, strncmp, const char *, s1, const char *, s2, size_t, n) +mkbi3_(char *, strncpy, char *, dest, const char *, src, size_t, n) +#if defined(__GNUC__) && __GNUC__ >= 9 +mkbi2_(size_t, strnlen, const char *, s1, size_t, n) +#else +size_t strnlen(const char * s1, size_t n); +#endif +mkdepbi2_(char *, strpbrk, const char *, s, const char *, accept) +mkdepbi2_(char *, strrchr, const char *, s, int, c) +mkdepbi2_(size_t, strspn, const char *, s, const char *, accept) +mkdepbi2_(char *, strstr, const char *, haystack, const char *, needle) + +mkbi3_(void *, memset, void *, s, int, c, size_t, n); + +#include <builtins_end_.h> + +#endif /* _STRING_H */ +#endif diff --git a/include/system/strings.h b/include/system/strings.h new file mode 100644 index 00000000..99bc05f2 --- /dev/null +++ b/include/system/strings.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +#ifdef SHIM_UNIT_TEST +#include_next <strings.h> +#else +#ifndef _STRINGS_H +#define _STRINGS_H + +#include <builtins_begin_.h> +mkbi1_(int, ffs, int, x) +mkbi1_(int, clz, int, x) +mkbi1_(int, ctz, int, x) +mkbi1_(int, clrsb, int, x) +mkbi1_(int, popcount, int, x) +mkbi1_(int, parity, int, x) +#include <builtins_end_.h> + +#endif /* !_STRINGS_H */ +#endif +// vim:fenc=utf-8:tw=75:noet diff --git a/include/test.h b/include/test.h new file mode 100644 index 00000000..012ffc51 --- /dev/null +++ b/include/test.h @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * test.h - fake a bunch of EFI types so we can build test harnesses with libc + * Copyright Peter Jones <pjones@redhat.com> + */ + +#ifdef SHIM_UNIT_TEST +#ifndef TEST_H_ +#define TEST_H_ + +#include <stdarg.h> + +#if defined(__aarch64__) +#include <aarch64/efibind.h> +#elif defined(__arm__) +#include <arm/efibind.h> +#elif defined(__i386__) || defined(__i486__) || defined(__i686__) +#include <ia32/efibind.h> +#elif defined(__x86_64__) +#include <x86_64/efibind.h> +#else +#error what arch is this +#endif + +#include <efidef.h> + +#include <efidevp.h> +#include <efiprot.h> +#include <eficon.h> +#include <efiapi.h> +#include <efierr.h> + +#include <efipxebc.h> +#include <efinet.h> +#include <efiip.h> + +#include <stdlib.h> + +#define ZeroMem(buf, sz) memset(buf, 0, sz) +#define SetMem(buf, sz, value) memset(buf, value, sz) +#define CopyMem(dest, src, len) memcpy(dest, src, len) +#define CompareMem(dest, src, len) memcmp(dest, src, len) + +#include <assert.h> + +#define AllocateZeroPool(x) calloc(1, (x)) +#define AllocatePool(x) malloc(x) +#define FreePool(x) free(x) +#define ReallocatePool(old, oldsz, newsz) realloc(old, newsz) + +extern int debug; +#ifdef dprint +#undef dprint +#define dprint(fmt, ...) {( if (debug) printf("%s:%d:" fmt, __func__, __LINE__, ##__VA_ARGS__); }) +#endif + +#define eassert(cond, fmt, ...) \ + ({ \ + if (!(cond)) { \ + printf("%s:%d:" fmt, __func__, __LINE__, \ + ##__VA_ARGS__); \ + } \ + assert(cond); \ + }) + +#define assert_true_as_expr(a, status, fmt, ...) \ + ({ \ + int rc_ = 0; \ + if (!(a)) { \ + printf("%s:%d:got %lld, expected nonzero " fmt, \ + __func__, __LINE__, (long long)(a), \ + ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify(!(a))); \ + rc_ = status; \ + } \ + rc_; \ + }) +#define assert_nonzero_as_expr(a, ...) assert_true_as_expr(a, ##__VA_ARGS__) + +#define assert_false_as_expr(a, status, fmt, ...) \ + ({ \ + int rc_ = 0; \ + if (a) { \ + printf("%s:%d:got %lld, expected zero " fmt, __func__, \ + __LINE__, (long long)(a), ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify(a)); \ + rc_ = status; \ + } \ + rc_; \ + }) +#define assert_zero_as_expr(a, ...) assert_false_as_expr(a, ##__VA_ARGS__) + +#define assert_positive_as_expr(a, status, fmt, ...) \ + ({ \ + int rc_ = 0; \ + if ((a) <= 0) { \ + printf("%s:%d:got %lld, expected > 0 " fmt, __func__, \ + __LINE__, (long long)(a), ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify((a) <= 0)); \ + rc_ = status; \ + } \ + rc_; \ + }) + +#define assert_negative_as_expr(a, status, fmt, ...) \ + ({ \ + int rc_ = 0; \ + if ((a) >= 0) { \ + printf("%s:%d:got %lld, expected < 0 " fmt, __func__, \ + __LINE__, (long long)(a), ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify((a) >= 0)); \ + rc_ = status; \ + } \ + rc_; \ + }) + +#define assert_equal_as_expr(a, b, status, fmt, ...) \ + ({ \ + int rc_ = 0; \ + if (!((a) == (b))) { \ + printf("%s:%d:" fmt, __func__, __LINE__, (a), (b), \ + ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify(a == b)); \ + rc_ = status; \ + } \ + rc_; \ + }) + +#define assert_as_expr(cond, status, fmt, ...) \ + ({ \ + int rc_ = 0; \ + if (!(cond)) { \ + printf("%s:%d:" fmt, __func__, __LINE__, \ + ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify(cond)); \ + rc_ = status; \ + } \ + rc_; \ + }) + +#define assert_true_return(a, status, fmt, ...) \ + ({ \ + int rc_ = assert_true_as_expr(a, status, fmt, ##__VA_ARGS__); \ + if (rc_ != 0) \ + return rc_; \ + }) +#define assert_nonzero_return(a, ...) assert_true_return(a, ##__VA_ARGS__) + +#define assert_false_return(a, status, fmt, ...) \ + ({ \ + int rc_ = assert_false_as_expr(a, status, fmt, ##__VA_ARGS__); \ + if (rc_ != 0) \ + return rc_; \ + }) +#define assert_zero_return(a, ...) assert_false_return(a, ##__VA_ARGS__) + +#define assert_positive_return(a, status, fmt, ...) \ + ({ \ + int rc_ = assert_positive_as_expr(a, status, fmt, \ + ##__VA_ARGS__); \ + if (rc_ != 0) \ + return rc_; \ + }) + +#define assert_negative_return(a, status, fmt, ...) \ + ({ \ + int rc_ = assert_negative_as_expr(a, status, fmt, \ + ##__VA_ARGS__); \ + if (rc_ != 0) \ + return rc_; \ + }) + +#define assert_equal_return(a, b, status, fmt, ...) \ + ({ \ + int rc_ = assert_equal_as_expr(a, b, status, fmt, \ + ##__VA_ARGS__); \ + if (rc_ != 0) \ + return rc_; \ + }) + +#define assert_return(cond, status, fmt, ...) \ + ({ \ + int rc_ = assert_as_expr(cond, status, fmt, ##__VA_ARGS__); \ + if (rc_ != 0) \ + return rc_; \ + }) + +#define assert_goto(cond, label, fmt, ...) \ + ({ \ + if (!(cond)) { \ + printf("%s:%d:" fmt, __func__, __LINE__, \ + ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify(cond)); \ + goto label; \ + } \ + }) + +#define assert_equal_goto(a, b, label, fmt, ...) \ + ({ \ + if (!((a) == (b))) { \ + printf("%s:%d:" fmt, __func__, __LINE__, (a), (b), \ + ##__VA_ARGS__); \ + printf("%s:%d:Assertion `%s' failed.\n", __func__, \ + __LINE__, __stringify(a == b)); \ + goto label; \ + } \ + }) + +#define assert_negative_goto(a, label, fmt, ...) \ + ({ \ + int rc_ = assert_negative_as_expr(a, -1, fmt, ##__VA_ARGS__); \ + if (rc_ != 0) \ + goto label; \ + }) + +#define assert_positive_goto(a, label, fmt, ...) \ + ({ \ + int rc_ = assert_positive_as_expr(a, -1, fmt, ##__VA_ARGS__); \ + if (rc_ != 0) \ + goto label; \ + }) + +#define test(x, ...) \ + ({ \ + int rc; \ + printf("running %s\n", __stringify(x)); \ + rc = x(__VA_ARGS__); \ + if (rc < 0) \ + status = 1; \ + printf("%s: %s\n", __stringify(x), \ + rc < 0 ? "failed" : "passed"); \ + }) + +#endif /* !TEST_H_ */ +#endif /* SHIM_UNIT_TEST */ +// vim:fenc=utf-8:tw=75:noet diff --git a/include/test.mk b/include/test.mk new file mode 100644 index 00000000..62cf983a --- /dev/null +++ b/include/test.mk @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# test.mk - makefile to make local test programs +# + +.SUFFIXES: + +CC = gcc +VALGRIND ?= +DEBUG_PRINTS ?= 0 +CFLAGS = -O2 -ggdb -std=gnu11 \ + -isystem $(TOPDIR)/include/system \ + $(EFI_INCLUDES) \ + -Iinclude -iquote . \ + -fshort-wchar -flto -fno-builtin \ + -Wall \ + -Wextra \ + -Wsign-compare \ + -Wno-deprecated-declarations \ + -Wno-pointer-sign \ + -Wno-unused \ + -Werror \ + -Werror=nonnull \ + $(shell $(CC) -Werror=nonnull-compare -E -x c /dev/null >/dev/null 2>&1 && echo -Werror=nonnull-compare) \ + $(ARCH_DEFINES) \ + -DEFI_FUNCTION_WRAPPER \ + -DGNU_EFI_USE_MS_ABI -DPAGE_SIZE=4096 \ + -DSHIM_UNIT_TEST \ + "-DDEFAULT_DEBUG_PRINT_STATE=$(DEBUG_PRINTS)" + +$(wildcard test-*.c) :: %.c : test-random.h +$(patsubst %.c,%,$(wildcard test-*.c)) :: | test-random.h +$(patsubst %.c,%.o,$(wildcard test-*.c)) : | test-random.h + +test-random.h: + dd if=/dev/urandom bs=512 count=17 of=random.bin + xxd -i random.bin test-random.h + +test-sbat_FILES = csv.c +test-str_FILES = lib/string.c + +tests := $(patsubst %.c,%,$(wildcard test-*.c)) + +$(tests) :: test-% : test.c test-%.c $(test-%_FILES) + $(CC) $(CFLAGS) -o $@ $^ $(wildcard $*.c) $(test-$*_FILES) + $(VALGRIND) ./$@ + +test : $(tests) + +clean : + @rm -vf test-random.h random.bin + +all : clean test + +.PHONY: $(tests) all test clean +.SECONDARY: random.bin + +# vim:ft=make diff --git a/include/tpm.h b/include/tpm.h index 746e871f..877d4f93 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -1,17 +1,17 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_TPM_H #define SHIM_TPM_H -#include <efilib.h> - #define TPM_ALG_SHA 0x00000004 -#define EV_IPL 0x0000000d EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, const CHAR8 *description); EFI_STATUS fallback_should_prefer_reset(void); -EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash, - UINT8 pcr); +EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, + EFI_PHYSICAL_ADDRESS addr, EFI_DEVICE_PATH *path, + UINT8 *sha1hash, UINT8 pcr); EFI_STATUS tpm_measure_variable(CHAR16 *dbname, EFI_GUID guid, UINTN size, void *data); @@ -44,7 +44,7 @@ typedef struct _EFI_IMAGE_LOAD_EVENT { UINTN ImageLengthInMemory; UINTN ImageLinkTimeAddress; UINTN LengthOfDevicePath; - EFI_DEVICE_PATH DevicePath[1]; + EFI_DEVICE_PATH DevicePath[0]; } EFI_IMAGE_LOAD_EVENT; struct efi_tpm_protocol @@ -173,6 +173,7 @@ typedef struct efi_tpm2_protocol efi_tpm2_protocol_t; typedef UINT32 TCG_EVENTTYPE; +#define EV_IPL 0x0000000d #define EV_EFI_EVENT_BASE ((TCG_EVENTTYPE) 0x80000000) #define EV_EFI_VARIABLE_DRIVER_CONFIG (EV_EFI_EVENT_BASE + 1) #define EV_EFI_VARIABLE_BOOT (EV_EFI_EVENT_BASE + 2) diff --git a/include/ucs2.h b/include/ucs2.h index 806774c7..e43c341f 100644 --- a/include/ucs2.h +++ b/include/ucs2.h @@ -1,36 +1,8 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* - * shim - trivial UEFI first-stage bootloader - * - * Copyright 2013 Red Hat, Inc <pjones@redhat.com> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Significant portions of this code are derived from Tianocore - * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel - * Corporation. + * ucs2.h - UCS-2 string functions + * Copyright Red Hat, Inc + * Copyright Peter Jones <pjones@redhat.com> */ #ifndef SHIM_UCS2_H diff --git a/include/variables.h b/include/variables.h index 8566a1a4..493f433f 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1,8 +1,10 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_VARIABLES_H #define SHIM_VARIABLES_H -#include <efiauthenticated.h> -#include <PeImage.h> /* for SHA256_DIGEST_SIZE */ +#include "efiauthenticated.h" +#include "peimage.h" /* for SHA256_DIGEST_SIZE */ #define certlist_for_each_certentry(cl, cl_init, s, s_init) \ for (cl = (EFI_SIGNATURE_LIST *)(cl_init), s = (s_init); \ @@ -24,7 +26,7 @@ CreatePkX509SignatureList ( IN UINT8 *X509Data, IN UINTN X509DataSize, IN EFI_GUID owner, - OUT EFI_SIGNATURE_LIST **PkCert + OUT EFI_SIGNATURE_LIST **PkCert ); EFI_STATUS CreateTimeBasedPayload ( @@ -32,16 +34,21 @@ CreateTimeBasedPayload ( IN OUT UINT8 **Data ); EFI_STATUS -SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, UINT32 options, int createtimebased); +SetSecureVariable(const CHAR16 * const var, UINT8 *Data, UINTN len, EFI_GUID owner, UINT32 options, int createtimebased); +EFI_STATUS +get_variable(const CHAR16 * const var, UINT8 **data, UINTN *len, EFI_GUID owner); +EFI_STATUS +get_variable_attr(const CHAR16 * const var, UINT8 **data, UINTN *len, EFI_GUID owner, UINT32 *attributes); +EFI_STATUS +get_variable_size(const CHAR16 * const var, EFI_GUID owner, UINTN *lenp); EFI_STATUS -get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner); +set_variable(CHAR16 *var, EFI_GUID owner, UINT32 attributes, UINTN datasize, void *data); EFI_STATUS -get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, - UINT32 *attributes); +del_variable(CHAR16 *var, EFI_GUID owner); EFI_STATUS find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen); EFI_STATUS -find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen); +find_in_variable_esl(const CHAR16 * const var, EFI_GUID owner, UINT8 *key, UINTN keylen); #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 @@ -54,10 +61,23 @@ variable_is_secureboot(void); int variable_is_setupmode(int default_return); EFI_STATUS -variable_enroll_hash(CHAR16 *var, EFI_GUID owner, +variable_enroll_hash(const CHAR16 * const var, EFI_GUID owner, UINT8 hash[SHA256_DIGEST_SIZE]); EFI_STATUS -variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, - void **out, int *outlen); +variable_create_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany, + const EFI_GUID *type, const UINT32 sig_size, + uint8_t **out, size_t *outlen); +EFI_STATUS +variable_create_esl_with_one_signature(const uint8_t* data, const size_t data_len, + const EFI_GUID *type, const EFI_GUID *owner, + uint8_t **out, size_t *outlen); +EFI_STATUS +fill_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany, + const EFI_GUID *type, const UINT32 sig_size, + uint8_t *out, size_t *outlen); +EFI_STATUS +fill_esl_with_one_signature(const uint8_t *data, const uint32_t data_len, + const EFI_GUID *type, const EFI_GUID *owner, + uint8_t *out, size_t *outlen); #endif /* SHIM_VARIABLES_H */ diff --git a/include/wincert.h b/include/wincert.h index a3ce12a2..9a5953a5 100644 --- a/include/wincert.h +++ b/include/wincert.h @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent + #ifndef SHIM_WINCERT_H #define SHIM_WINCERT_H @@ -6,28 +8,27 @@ /// typedef struct { /// - /// The length of the entire certificate, - /// including the length of the header, in bytes. + /// The length of the entire certificate, + /// including the length of the header, in bytes. /// UINT32 dwLength; /// - /// The revision level of the WIN_CERTIFICATE - /// structure. The current revision level is 0x0200. + /// The revision level of the WIN_CERTIFICATE + /// structure. The current revision level is 0x0200. /// UINT16 wRevision; /// - /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI - /// certificate types. The UEFI specification reserves the range of - /// certificate type values from 0x0EF0 to 0x0EFF. + /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI + /// certificate types. The UEFI specification reserves the range of + /// certificate type values from 0x0EF0 to 0x0EFF. /// UINT16 wCertificateType; /// - /// The following is the actual certificate. The format of + /// The following is the actual certificate. The format of /// the certificate depends on wCertificateType. /// /// UINT8 bCertificate[ANYSIZE_ARRAY]; /// } WIN_CERTIFICATE; - #endif /* SHIM_WINCERT_H */ |