New upstream version 15+1531942534.dd3230d

This commit is contained in:
Mathieu Trudel-Lapierre 2018-07-24 16:24:23 -04:00
parent 6215e920e7
commit f892ac6608
65 changed files with 3375 additions and 3090 deletions

2
.gitignore vendored
View File

@ -25,3 +25,5 @@ shim_cert.h
*.srl.old
*.tar.*
version.c
cov-int/
scan-results/

View File

@ -1,16 +1,3 @@
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/..
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/../Include/
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto
-I/usr/lib/gcc/x86_64-redhat-linux/7/include
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/../Include
-I/usr/include/efi
-I/usr/include/efi/x86_64
-I/usr/include/efi/protocol
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/asn1
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/evp
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/modes
-I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/include
-DL_ENDIAN
-D_CRT_SECURE_NO_DEPRECATE
-D_CRT_NONSTDC_NO_DEPRECATE
@ -29,18 +16,22 @@
-Werror=sign-compare
-ffreestanding
-std=gnu89
-I/usr/lib/gcc/x86_64-redhat-linux/7/include
-nostdinc
-I/home/pjones/devel/github.com/shim/master/Cryptlib
-I/home/pjones/devel/github.com/shim/master/Cryptlib/Include
-I/usr/include/efi
-I/usr/include/efi/x86_64
-I/usr/include/efi/protocol
-I/home/pjones/devel/github.com/shim/master/include
-I/usr/lib/gcc/x86_64-redhat-linux/7/include
-Iinclude
-ICryptlib/
-ICryptlib/Include/
-ICryptlib/OpenSSL/
-ICryptlib/OpenSSL/crypto/
-I/usr/include/efi/
-I/usr/include/efi/x86_64/
-I/usr/include/efi/protocol/
-ICryptlib/OpenSSL/crypto/asn1/
-ICryptlib/OpenSSL/crypto/evp/
-ICryptlib/OpenSSL/crypto/modes/
-ICryptlib/OpenSSL/crypto/include/
-iquote
/home/pjones/devel/github.com/shim/master
-iquote
/home/pjones/devel/github.com/shim/master
.
-mno-mmx
-mno-sse
-mno-red-zone

17
.travis.yml Normal file
View File

@ -0,0 +1,17 @@
language: c
cache: ccache
branches:
except:
- travis
matrix:
include:
- os: linux
dist: trusty
services: docker
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull vathpela/efi-ci-rawhide:v0 ; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run vathpela/efi-ci-rawhide:v0 /bin/sh -c "cd /root/ && ./build.sh --branch \"$TRAVIS_BRANCH\" --commit \"$TRAVIS_COMMIT\" --commit-range \"$TRAVIS_COMMIT_RANGE\" --event-type \"$TRAVIS_EVENT_TYPE\" --pull-request \"$TRAVIS_PULL_REQUEST\" --pr-branch \"$TRAVIS_PULL_REQUEST_BRANCH\" --pr-sha \"$TRAVIS_PULL_REQUEST_SHA\" --remote \"$TRAVIS_PULL_REQUEST_SLUG\" --repo \"$TRAVIS_REPO_SLUG\" --test-subject shim" ; fi

View File

@ -27,12 +27,14 @@ Variables you should set to customize the build:
Variables you could set to customize the build:
- ENABLE_SHIM_CERT
if this variable is defined one the make command line, shim will
if this variable is defined on the make command line, shim will
generate keys during the build and sign MokManager and fallback with
them, and the signed version will be what gets installed with the
install targets
- ENABLE_HTTPBOOT
build support for http booting
- REQUIRE_TPM
if tpm logging or extends return an error code, treat that as a fatal error.
- ARCH
This allows you to do a build for a different arch that we support. For
instance, on x86_64 you could do "setarch linux32 make ARCH=ia32" to get

View File

@ -17,11 +17,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <efi.h>
#include <efilib.h>
#include <Base.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include "Base.h"
#include "Library/BaseLib.h"
#include "Library/BaseMemoryLib.h"
#include "Library/MemoryAllocationLib.h"
#include "Library/DebugLib.h"
/*
* Include stddef.h to avoid redefining "offsetof"
@ -380,5 +380,6 @@ extern FILE *stdout;
#define atoi(nptr) AsciiStrDecimalToUintn(nptr)
#define gettimeofday(tvp,tz) do { (tvp)->tv_sec = time(NULL); (tvp)->tv_usec = 0; } while (0)
#define gmtime_r(timer,result) (result = NULL)
#define abort()
#endif

View File

@ -15,11 +15,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#ifndef __INTERNAL_CRYPT_LIB_H__
#define __INTERNAL_CRYPT_LIB_H__
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseCryptLib.h>
#include "Library/BaseLib.h"
#include "Library/BaseMemoryLib.h"
#include "Library/MemoryAllocationLib.h"
#include "Library/DebugLib.h"
#include "Library/BaseCryptLib.h"
#include "OpenSslSupport.h"

View File

@ -5,4 +5,5 @@ UINT32 WriteUnaligned32 (UINT32 *Buffer, UINT32 Value);
UINTN AsciiStrSize (CHAR8 *string);
char *AsciiStrnCpy(char *Destination, char *Source, UINTN count);
char *AsciiStrCat(char *Destination, char *Source);
CHAR8 *AsciiStrCpy(CHAR8 *Destination, CHAR8 *Source);
UINTN AsciiStrDecimalToUintn(const char *String);

View File

@ -5,14 +5,16 @@ CFLAGS = -ggdb -O0 -I$(TOPDIR) -iquote $(TOPDIR) -fno-stack-protector -fno-stri
-Wall $(EFI_INCLUDES) -std=gnu89 \
-ffreestanding -I$(shell $(CC) -print-file-name=include)
CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,)
ifeq ($(ARCH),x86_64)
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args \
-DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DNO_BUILTIN_VA_FUNCS \
-DMDE_CPU_X64
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc $(CLANG_BUGS) \
-m64 -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
-DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64
endif
ifeq ($(ARCH),ia32)
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args -m32 \
-DMDE_CPU_IA32
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \
$(CLANG_BUGS) -m32 -DMDE_CPU_IA32
endif
ifeq ($(ARCH),aarch64)
CFLAGS += -DMDE_CPU_AARCH64
@ -40,7 +42,7 @@ OBJS = Hash/CryptMd4Null.o \
Pk/CryptTs.o \
Pk/CryptX509.o \
Pk/CryptAuthenticode.o \
Pem/CryptPem.o \
Pem/CryptPemNull.o \
SysCall/CrtWrapper.o \
SysCall/TimerWrapper.o \
SysCall/BaseMemAllocation.o \

View File

@ -8,14 +8,16 @@ CFLAGS = -ggdb -O0 -I$(TOPDIR) -I$(TOPDIR)/.. -I$(TOPDIR)/../Include/ -I$(TOPDI
-ffreestanding -std=gnu89 -I$(shell $(CC) -print-file-name=include) \
-Wall $(EFI_INCLUDES) -DL_ENDIAN -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC
CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,)
ifeq ($(ARCH),x86_64)
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \
-DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
CFLAGS += -mno-mmx -mno-sse -mno-red-zone $(CLANG_BUGS) \
-m64 -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
-UNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64
endif
ifeq ($(ARCH),ia32)
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \
-m32 -DMDE_CPU_IA32
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \
$(CLANG_BUGS) -m32 -DMDE_CPU_IA32
endif
ifeq ($(ARCH),aarch64)
CFLAGS += -O2 -DMDE_CPU_AARCH64

View File

@ -1,135 +0,0 @@
/** @file
PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over OpenSSL.
Copyright (c) 2010 - 2013, 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
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.
**/
#include "InternalCryptLib.h"
#include <openssl/pem.h>
/**
Callback function for password phrase conversion used for retrieving the encrypted PEM.
@param[out] Buf Pointer to the buffer to write the passphrase to.
@param[in] Size Maximum length of the passphrase (i.e. the size of Buf).
@param[in] Flag A flag which is set to 0 when reading and 1 when writing.
@param[in] Key Key data to be passed to the callback routine.
@retval The number of characters in the passphrase or 0 if an error occurred.
**/
INTN
PasswordCallback (
OUT CHAR8 *Buf,
IN INTN Size,
IN INTN Flag,
IN VOID *Key
)
{
INTN KeyLength;
ZeroMem ((VOID *) Buf, (UINTN) Size);
if (Key != NULL) {
//
// Duplicate key phrase directly.
//
KeyLength = (INTN) AsciiStrLen ((CHAR8 *)Key);
KeyLength = (KeyLength > Size ) ? Size : KeyLength;
CopyMem (Buf, Key, (UINTN) KeyLength);
return KeyLength;
} else {
return 0;
}
}
/**
Retrieve the RSA Private Key from the password-protected PEM key data.
@param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
@param[in] PemSize Size of the PEM key data in bytes.
@param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
@param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
RSA private key component. Use RsaFree() function to free the
resource.
If PemData is NULL, then return FALSE.
If RsaContext is NULL, then return FALSE.
@retval TRUE RSA Private Key was retrieved successfully.
@retval FALSE Invalid PEM key data or incorrect password.
**/
BOOLEAN
EFIAPI
RsaGetPrivateKeyFromPem (
IN CONST UINT8 *PemData,
IN UINTN PemSize,
IN CONST CHAR8 *Password,
OUT VOID **RsaContext
)
{
BOOLEAN Status;
BIO *PemBio;
//
// Check input parameters.
//
if (PemData == NULL || RsaContext == NULL || PemSize > INT_MAX) {
return FALSE;
}
//
// Add possible block-cipher descriptor for PEM data decryption.
// NOTE: Only support most popular ciphers (3DES, AES) for the encrypted PEM.
//
if (EVP_add_cipher (EVP_des_ede3_cbc ()) == 0) {
return FALSE;
}
if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) {
return FALSE;
}
if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) {
return FALSE;
}
if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) {
return FALSE;
}
Status = FALSE;
//
// Read encrypted PEM Data.
//
PemBio = BIO_new (BIO_s_mem ());
if (PemBio == NULL) {
goto _Exit;
}
if (BIO_write (PemBio, PemData, (int) PemSize) <= 0) {
goto _Exit;
}
//
// Retrieve RSA Private Key from encrypted PEM data.
//
*RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *) &PasswordCallback, (void *) Password);
if (*RsaContext != NULL) {
Status = TRUE;
}
_Exit:
//
// Release Resources.
//
BIO_free (PemBio);
return Status;
}

View File

@ -0,0 +1,44 @@
/** @file
PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation which does
not provide real capabilities.
Copyright (c) 2012, 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
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.
**/
#include "InternalCryptLib.h"
/**
Retrieve the RSA Private Key from the password-protected PEM key data.
Return FALSE to indicate this interface is not supported.
@param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
@param[in] PemSize Size of the PEM key data in bytes.
@param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
@param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
RSA private key component. Use RsaFree() function to free the
resource.
@retval FALSE This interface is not supported.
**/
BOOLEAN
EFIAPI
RsaGetPrivateKeyFromPem (
IN CONST UINT8 *PemData,
IN UINTN PemSize,
IN CONST CHAR8 *Password,
OUT VOID **RsaContext
)
{
ASSERT (FALSE);
return FALSE;
}

48
Make.coverity Normal file
View File

@ -0,0 +1,48 @@
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
cov-int : clean-shim-objs
make $(DASHJ) Cryptlib/OpenSSL/libopenssl.a Cryptlib/libcryptlib.a
cov-build --dir cov-int make $(DASHJ) all
cov-int-all : clean
cov-build --dir cov-int make $(DASHJ) all
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 :
@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
coverity : | cov-test
coverity : cov-int cov-file cov-upload
coverity-all : | cov-test
coverity-all : cov-int-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 1)
ifeq ($(COV_BUILD),)
COV_BUILD_ERROR = $(error cov-build not found)
endif
cov-test : ; $(COV_BUILD_ERROR)
.PHONY : coverity cov-upload cov-clean cov-file cov-test

131
Make.defaults Normal file
View File

@ -0,0 +1,131 @@
COMPILER ?= gcc
CC = $(CROSS_COMPILE)$(COMPILER)
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
OPENSSL ?= openssl
HEXDUMP ?= hexdump
INSTALL ?= install
PK12UTIL ?= pk12util
CERTUTIL ?= certutil
PESIGN ?= pesign
SBSIGN ?= sbsign
prefix ?= /usr
prefix := $(abspath $(prefix))
datadir ?= $(prefix)/share/
PKGNAME ?= shim
ESPROOTDIR ?= boot/efi/
EFIBOOTDIR ?= $(ESPROOTDIR)EFI/BOOT/
TARGETDIR ?= $(ESPROOTDIR)EFI/$(EFIDIR)/
DATATARGETDIR ?= $(datadir)/$(PKGNAME)/$(VERSION)$(DASHRELEASE)/$(ARCH_SUFFIX)/
DEBUGINFO ?= $(prefix)/lib/debug/
DEBUGSOURCE ?= $(prefix)/src/debug/
OSLABEL ?= $(EFIDIR)
DEFAULT_LOADER ?= \\\\grub$(ARCH_SUFFIX).efi
DASHJ ?= -j$(shell echo $$(($$(grep -c "^model name" /proc/cpuinfo) + 1)))
ARCH ?= $(shell $(CC) -dumpmachine | cut -f1 -d- | sed s,i[3456789]86,ia32,)
OBJCOPY_GTE224 = $(shell expr `$(OBJCOPY) --version |grep ^"GNU objcopy" | sed 's/^.*\((.*)\|version\) //g' | cut -f1-2 -d.` \>= 2.24)
SUBDIRS = $(TOPDIR)/Cryptlib $(TOPDIR)/lib
EFI_INCLUDE ?= /usr/include/efi
EFI_INCLUDES = -nostdinc -I$(TOPDIR)/Cryptlib -I$(TOPDIR)/Cryptlib/Include \
-I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol \
-I$(TOPDIR)/include -iquote $(TOPDIR) -iquote $(shell pwd)
EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o
EFI_LDS = $(TOPDIR)/elf_$(ARCH)_efi.lds
CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,)
COMMIT_ID ?= $(shell if [ -e .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo master; fi)
ifeq ($(ARCH),x86_64)
ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
$(CLANG_BUGS) -m64 \
-DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
-DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 \
-DPAGE_SIZE=4096
LIBDIR ?= $(prefix)/lib64
ARCH_SUFFIX ?= x64
ARCH_SUFFIX_UPPER ?= X64
ARCH_LDFLAGS ?=
endif
ifeq ($(ARCH),ia32)
ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \
$(CLANG_BUGS) -m32 \
-DMDE_CPU_IA32 -DPAGE_SIZE=4096
LIBDIR ?= $(prefix)/lib
ARCH_SUFFIX ?= ia32
ARCH_SUFFIX_UPPER ?= IA32
ARCH_LDFLAGS ?=
ARCH_CFLAGS ?= -m32
endif
ifeq ($(ARCH),aarch64)
ARCH_CFLAGS ?= -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align
LIBDIR ?= $(prefix)/lib64
ARCH_SUFFIX ?= aa64
ARCH_SUFFIX_UPPER ?= AA64
FORMAT := -O binary
SUBSYSTEM := 0xa
ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
ARCH_CFLAGS ?=
endif
ifeq ($(ARCH),arm)
ARCH_CFLAGS ?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align
LIBDIR ?= $(prefix)/lib
ARCH_SUFFIX ?= arm
ARCH_SUFFIX_UPPER ?= ARM
FORMAT := -O binary
SUBSYSTEM := 0xa
ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
endif
CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
-fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \
-Werror=sign-compare -ffreestanding -std=gnu89 \
-I$(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include) \
"-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \
"-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \
$(EFI_INCLUDES) $(ARCH_CFLAGS)
ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
CFLAGS += -DOVERRIDE_SECURITY_POLICY
endif
ifneq ($(origin ENABLE_HTTPBOOT), undefined)
CFLAGS += -DENABLE_HTTPBOOT
endif
ifneq ($(origin REQUIRE_TPM), undefined)
CFLAGS += -DREQUIRE_TPM
endif
LIB_GCC = $(shell $(CC) $(ARCH_CFLAGS) -print-libgcc-file-name)
EFI_LIBS = -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC)
FORMAT ?= --target efi-app-$(ARCH)
EFI_PATH ?= $(LIBDIR)/gnuefi
MMSTEM ?= mm$(ARCH_SUFFIX)
MMNAME = $(MMSTEM).efi
MMSONAME = $(MMSTEM).so
FBSTEM ?= fb$(ARCH_SUFFIX)
FBNAME = $(FBSTEM).efi
FBSONAME = $(FBSTEM).so
SHIMSTEM ?= shim$(ARCH_SUFFIX)
SHIMNAME = $(SHIMSTEM).efi
SHIMSONAME = $(SHIMSTEM).so
SHIMHASHNAME = $(SHIMSTEM).hash
BOOTEFINAME ?= BOOT$(ARCH_SUFFIX_UPPER).EFI
BOOTCSVNAME ?= BOOT$(ARCH_SUFFIX_UPPER).CSV
CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/share/shim/$(ARCH_SUFFIX)-$(VERSION)$(DASHRELEASE)/\""
ifneq ($(origin VENDOR_CERT_FILE), undefined)
CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\"
endif
ifneq ($(origin VENDOR_DBX_FILE), undefined)
CFLAGS += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\"
endif
LDFLAGS = --hash-style=sysv -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIBDIR) -LCryptlib -LCryptlib/OpenSSL $(EFI_CRT_OBJS) --build-id=sha1 $(ARCH_LDFLAGS) --no-undefined

3
Make.rules Normal file
View File

@ -0,0 +1,3 @@
define get-config
$(shell git config --local --get "shim.$(1)")
endef

20
Make.scan-build Normal file
View File

@ -0,0 +1,20 @@
SCAN_BUILD ?= $(shell x=$$(which --skip-alias --skip-functions scan-build 2>/dev/null) ; [ -n "$$x" ] && echo 1)
ifeq ($(SCAN_BUILD),)
SCAN_BUILD_ERROR = $(error scan-build not found)
endif
scan-test : ; $(SCAN_BUILD_ERROR)
scan-clean :
@if [[ -d scan-results ]]; then rm -rf scan-results && echo "removed 'scan-results'"; fi
scan-build : | scan-test
scan-build : clean-shim-objs
make $(DASHJ) Cryptlib/OpenSSL/libopenssl.a Cryptlib/libcryptlib.a
scan-build -o scan-results make $(DASHJ) CC=clang all
scan-build-all : | scan-test
scan-build-all : clean
scan-build -o scan-results make $(DASHJ) CC=clang all
.PHONY : scan-build scan-clean

164
Makefile
View File

@ -1,4 +1,7 @@
VERSION = 13
default : all
NAME = shim
VERSION = 15
ifneq ($(origin RELEASE),undefined)
DASHRELEASE ?= -$(RELEASE)
else
@ -8,130 +11,16 @@ endif
ifeq ($(MAKELEVEL),0)
TOPDIR ?= $(shell pwd)
endif
ifeq ($(TOPDIR),)
override TOPDIR := $(shell pwd)
endif
override TOPDIR := $(abspath $(TOPDIR))
VPATH = $(TOPDIR)
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
OBJCOPY = $(CROSS_COMPILE)objcopy
OPENSSL ?= openssl
HEXDUMP ?= hexdump
INSTALL ?= install
PK12UTIL ?= pk12util
CERTUTIL ?= certutil
PESIGN ?= pesign
SBSIGN ?= sbsign
prefix ?= /usr
prefix := $(abspath $(prefix))
datadir ?= $(prefix)/share/
PKGNAME ?= shim
ESPROOTDIR ?= boot/efi/
EFIBOOTDIR ?= $(ESPROOTDIR)EFI/BOOT/
TARGETDIR ?= $(ESPROOTDIR)EFI/$(EFIDIR)/
DATATARGETDIR ?= $(datadir)/$(PKGNAME)/$(VERSION)$(DASHRELEASE)/$(ARCH_SUFFIX)/
DEBUGINFO ?= $(prefix)/lib/debug/
DEBUGSOURCE ?= $(prefix)/src/debug/
OSLABEL ?= $(EFIDIR)
DEFAULT_LOADER ?= \\\\grub$(ARCH_SUFFIX).efi
ARCH ?= $(shell $(CC) -dumpmachine | cut -f1 -d- | sed s,i[3456789]86,ia32,)
OBJCOPY_GTE224 = $(shell expr `$(OBJCOPY) --version |grep ^"GNU objcopy" | sed 's/^.*\((.*)\|version\) //g' | cut -f1-2 -d.` \>= 2.24)
SUBDIRS = $(TOPDIR)/Cryptlib $(TOPDIR)/lib
EFI_INCLUDE := /usr/include/efi
EFI_INCLUDES = -nostdinc -I$(TOPDIR)/Cryptlib -I$(TOPDIR)/Cryptlib/Include \
-I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol \
-I$(TOPDIR)/include -iquote $(TOPDIR) -iquote $(shell pwd)
LIB_GCC = $(shell $(CC) -print-libgcc-file-name)
EFI_LIBS = -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC)
EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o
EFI_LDS = $(TOPDIR)/elf_$(ARCH)_efi.lds
CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
-fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \
-Werror=sign-compare -ffreestanding -std=gnu89 \
-I$(shell $(CC) -print-file-name=include) \
"-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \
"-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \
$(EFI_INCLUDES)
COMMITID ?= $(shell if [ -d .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo commit id not available; fi)
ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined)
CFLAGS += -DOVERRIDE_SECURITY_POLICY
endif
ifneq ($(origin ENABLE_HTTPBOOT), undefined)
CFLAGS += -DENABLE_HTTPBOOT
endif
ifeq ($(ARCH),x86_64)
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \
-maccumulate-outgoing-args \
-DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \
-DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 -DPAGE_SIZE=4096
LIBDIR ?= $(prefix)/lib64
ARCH_SUFFIX ?= x64
ARCH_SUFFIX_UPPER ?= X64
ARCH_LDFLAGS ?=
endif
ifeq ($(ARCH),ia32)
CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \
-maccumulate-outgoing-args -m32 \
-DMDE_CPU_IA32 -DPAGE_SIZE=4096
LIBDIR ?= $(prefix)/lib
ARCH_SUFFIX ?= ia32
ARCH_SUFFIX_UPPER ?= IA32
ARCH_LDFLAGS ?=
endif
ifeq ($(ARCH),aarch64)
CFLAGS += -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align
LIBDIR ?= $(prefix)/lib64
ARCH_SUFFIX ?= aa64
ARCH_SUFFIX_UPPER ?= AA64
FORMAT := -O binary
SUBSYSTEM := 0xa
ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
endif
ifeq ($(ARCH),arm)
CFLAGS += -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align
LIBDIR ?= $(prefix)/lib
ARCH_SUFFIX ?= arm
ARCH_SUFFIX_UPPER ?= ARM
FORMAT := -O binary
SUBSYSTEM := 0xa
ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM)
endif
FORMAT ?= --target efi-app-$(ARCH)
EFI_PATH ?= $(LIBDIR)/gnuefi
MMSTEM ?= mm$(ARCH_SUFFIX)
MMNAME = $(MMSTEM).efi
MMSONAME = $(MMSTEM).so
FBSTEM ?= fb$(ARCH_SUFFIX)
FBNAME = $(FBSTEM).efi
FBSONAME = $(FBSTEM).so
SHIMSTEM ?= shim$(ARCH_SUFFIX)
SHIMNAME = $(SHIMSTEM).efi
SHIMSONAME = $(SHIMSTEM).so
SHIMHASHNAME = $(SHIMSTEM).hash
BOOTEFINAME ?= BOOT$(ARCH_SUFFIX_UPPER).EFI
BOOTCSVNAME ?= BOOT$(ARCH_SUFFIX_UPPER).CSV
CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/share/shim/$(ARCH_SUFFIX)-$(VERSION)$(DASHRELEASE)/\""
ifneq ($(origin VENDOR_CERT_FILE), undefined)
CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\"
endif
ifneq ($(origin VENDOR_DBX_FILE), undefined)
CFLAGS += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\"
endif
LDFLAGS = --hash-style=sysv -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIBDIR) -LCryptlib -LCryptlib/OpenSSL $(EFI_CRT_OBJS) --build-id=sha1 $(ARCH_LDFLAGS)
include $(TOPDIR)/Make.defaults
include $(TOPDIR)/Make.rules
include $(TOPDIR)/Make.coverity
include $(TOPDIR)/Make.scan-build
TARGETS = $(SHIMNAME)
TARGETS += $(SHIMNAME).debug $(MMNAME).debug $(FBNAME).debug
@ -144,17 +33,17 @@ CFLAGS += -DENABLE_SHIM_CERT
else
TARGETS += $(MMNAME) $(FBNAME)
endif
OBJS = shim.o netboot.o cert.o replacements.o tpm.o version.o errlog.o
OBJS = shim.o mok.o netboot.o cert.o replacements.o tpm.o version.o errlog.o
KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer
ORIG_SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h tpm.c tpm.h version.h errlog.c
ORIG_SOURCES = shim.c mok.c netboot.c replacements.c tpm.c errlog.c shim.h version.h $(wildcard include/*.h)
MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o
ORIG_MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h
FALLBACK_OBJS = fallback.o tpm.o
ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h)
FALLBACK_OBJS = fallback.o tpm.o errlog.o
ORIG_FALLBACK_SRCS = fallback.c
ifneq ($(origin ENABLE_HTTPBOOT), undefined)
OBJS += httpboot.o
SOURCES += httpboot.c httpboot.h
SOURCES += httpboot.c include/httpboot.h
endif
SOURCES = $(foreach source,$(ORIG_SOURCES),$(TOPDIR)/$(source)) version.c
@ -177,8 +66,8 @@ shim_cert.h: shim.cer
version.c : $(TOPDIR)/version.c.in
sed -e "s,@@VERSION@@,$(VERSION)," \
-e "s,@@UNAME@@,$(shell uname -a)," \
-e "s,@@COMMIT@@,$(COMMITID)," \
-e "s,@@UNAME@@,$(shell uname -s -m -p -i -o)," \
-e "s,@@COMMIT@@,$(COMMIT_ID)," \
< $< > $@
certdb/secmod.db: shim.crt
@ -220,9 +109,9 @@ Cryptlib/OpenSSL/libopenssl.a:
mkdir -p Cryptlib/OpenSSL/crypto/{x509v3,x509,txt_db,stack,sha,rsa,rc4,rand,pkcs7,pkcs12,pem,ocsp,objects,modes,md5,lhash,kdf,hmac,evp,err,dso,dh,conf,comp,cmac,buffer,bn,bio,async{,/arch},asn1,aes}/
$(MAKE) VPATH=$(TOPDIR)/Cryptlib/OpenSSL TOPDIR=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile
lib/lib.a:
lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch])
if [ ! -d lib ]; then mkdir lib ; fi
$(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) CFLAGS="$(CFLAGS)" -C lib -f $(TOPDIR)/lib/Makefile
$(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) CFLAGS="$(CFLAGS)" -C lib -f $(TOPDIR)/lib/Makefile lib.a
buildid : $(TOPDIR)/buildid.c
$(CC) -Og -g3 -Wall -Werror -Wextra -o $@ $< -lelf
@ -331,13 +220,16 @@ else
$(PESIGN) -n certdb -i $< -c "shim" -s -o $@ -f
endif
clean: OBJS=$(wildcard *.o)
clean:
clean-shim-objs:
$(MAKE) -C lib -f $(TOPDIR)/lib/Makefile clean
@rm -rvf $(TARGET) *.o $(SHIM_OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME)
@rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid
@rm -vf Cryptlib/*.[oa] Cryptlib/*/*.[oa]
@git clean -f -d -e 'Cryptlib/OpenSSL/*'
clean: clean-shim-objs
$(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean
$(MAKE) -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile clean
$(MAKE) -C lib -f $(TOPDIR)/lib/Makefile clean
rm -rf $(TARGET) $(OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME)
rm -f *.debug *.so *.efi *.efi.* *.tar.* version.c buildid
GITTAG = $(VERSION)

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,8 @@
#include <Library/BaseCryptLib.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include "PasswordCrypt.h"
#include "crypt_blowfish.h"
#include "shim.h"
#define TRAD_DES_HASH_SIZE 13 /* (64/6+1) + (12/6) */
#define BSDI_DES_HASH_SIZE 20 /* (64/6+1) + (24/6) + 4 + 1 */
@ -286,7 +286,7 @@ static EFI_STATUS blowfish_crypt (const char *key, const char *salt, UINT8 *hash
EFI_STATUS password_crypt (const char *password, UINT32 pw_length,
const PASSWORD_CRYPT *pw_crypt, UINT8 *hash)
{
EFI_STATUS status;
EFI_STATUS efi_status;
if (!pw_crypt)
return EFI_INVALID_PARAMETER;
@ -294,32 +294,36 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length,
switch (pw_crypt->method) {
case TRADITIONAL_DES:
case EXTEND_BSDI_DES:
status = EFI_UNSUPPORTED;
efi_status = EFI_UNSUPPORTED;
break;
case MD5_BASED:
status = md5_crypt (password, pw_length, (char *)pw_crypt->salt,
pw_crypt->salt_size, hash);
efi_status = md5_crypt (password, pw_length,
(char *)pw_crypt->salt,
pw_crypt->salt_size, hash);
break;
case SHA256_BASED:
status = sha256_crypt(password, pw_length, (char *)pw_crypt->salt,
pw_crypt->salt_size, pw_crypt->iter_count,
hash);
efi_status = sha256_crypt(password, pw_length,
(char *)pw_crypt->salt,
pw_crypt->salt_size,
pw_crypt->iter_count, hash);
break;
case SHA512_BASED:
status = sha512_crypt(password, pw_length, (char *)pw_crypt->salt,
pw_crypt->salt_size, pw_crypt->iter_count,
hash);
efi_status = sha512_crypt(password, pw_length,
(char *)pw_crypt->salt,
pw_crypt->salt_size,
pw_crypt->iter_count, hash);
break;
case BLOWFISH_BASED:
if (pw_crypt->salt_size != (7 + 22 + 1)) {
status = EFI_INVALID_PARAMETER;
efi_status = EFI_INVALID_PARAMETER;
break;
}
status = blowfish_crypt(password, (char *)pw_crypt->salt, hash);
efi_status = blowfish_crypt(password, (char *)pw_crypt->salt,
hash);
break;
default:
return EFI_INVALID_PARAMETER;
}
return status;
return efi_status;
}

4
README
View File

@ -9,8 +9,8 @@ will relocate and execute the binary.
shim will also install a protocol which permits the second-stage bootloader
to perform similar binary validation. This protocol has a GUID as described
in the shim.h header file and provides a single entry point. On 64-bit systems
this entry point expects to be called with SysV ABI rather than MSABI, and
so calls to it should not be wrapped.
this entry point expects to be called with SysV ABI rather than MSABI, so calls
to it should not be wrapped.
On systems with a TPM chip enabled and supported by the system firmware,
shim will extend various PCRs with the digests of the targets it is

View File

@ -3,6 +3,8 @@ The following PCRs are extended by shim:
PCR4:
- the Authenticode hash of the binary being loaded will be extended into
PCR4 before SB verification.
- the hash of any binary for which Verify is called through the shim_lock
protocol
PCR7:
- Any certificate in one of our certificate databases that matches a binary

23
TODO
View File

@ -1,14 +1,31 @@
- Versioned protocol:
- Make shim and the bootloaders using it express how enlightened they
are to one another, so we can stop earlier without tricks like the one
above
- Make a LoadImage/CheckImage/StartImage based protocol
are to one another, so we can stop earlier without tricks
- Make EFI_LOADED_IMAGE_2 protocol and a LOAD_IMAGE protocol with
LoadImage/CheckImage/StartImage.
- Implement EFI_CERT_X509_SHA{256,384,512} revocation checks
- It doesn't necessarily have to include timestamp checking support
- Make the openssl code supply the Pkcs7Verify() API, and use the system
one (instead) if it is available.
- And make building it optional
- Get meb30's multiple-certs patch merged
- Hashing of option roms:
- hash option roms and add them to MokListRT
- probably belongs in MokManager
- And some PCR?
- Ability to specify second stage as a device path
- including vendor path that means "parent of this image's path"
- including vendor path that means "this image"
- including path that's like Fv() to embed images.
- Make all build options be able to be set in 'git config --local shim.OPTION'
- Make the build dump those to stdout as well
- make debuginfo paths configurable
- make arch dependent names configurable
- Make it easier to avoid CryptPem
- Make an easy strip+implant tool for our embedded cert lists
- Post process full path names out of __FILE__ / __BASE_FILE__ entries in
the string table :/
- Make build.log an artifact of building.
- KEK for Mok. (koike expressed an interest in working on this.)
# vim:filetype=mail:tw=74

1
commit
View File

@ -1 +0,0 @@
5e827007b3d95c4ce999422462248f5e7d3f270f

View File

@ -47,7 +47,7 @@
#include <efilib.h>
/* Just to make sure the prototypes match the actual definitions */
#include "crypt_blowfish.h"
#include "shim.h"
typedef unsigned int BF_word;
typedef signed int BF_word_signed;

View File

@ -7,10 +7,6 @@
#include "shim.h"
#ifdef LogError
#undef LogError
#endif
static CHAR16 **errs = NULL;
static UINTN nerrs = 0;
@ -51,16 +47,16 @@ VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list arg
}
EFI_STATUS
LogError(const char *file, int line, const char *func, CHAR16 *fmt, ...)
LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...)
{
va_list args;
EFI_STATUS status;
EFI_STATUS efi_status;
va_start(args, fmt);
status = VLogError(file, line, func, fmt, args);
efi_status = VLogError(file, line, func, fmt, args);
va_end(args);
return status;
return efi_status;
}
VOID
@ -72,7 +68,7 @@ PrintErrors(VOID)
return;
for (i = 0; i < nerrs; i++)
Print(L"%s", errs[i]);
console_print(L"%s", errs[i]);
}
VOID

View File

@ -10,18 +10,13 @@
#include <efi.h>
#include <efilib.h>
#include "ucs2.h"
#include "variables.h"
#include "tpm.h"
#include "shim.h"
EFI_LOADED_IMAGE *this_image = NULL;
EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
int
get_fallback_verbose(void)
{
EFI_GUID guid = SHIM_LOCK_GUID;
UINT8 *data = NULL;
UINTN dataSize = 0;
EFI_STATUS efi_status;
@ -32,20 +27,22 @@ get_fallback_verbose(void)
return state;
efi_status = get_variable(L"FALLBACK_VERBOSE",
&data, &dataSize, guid);
&data, &dataSize, SHIM_LOCK_GUID);
if (EFI_ERROR(efi_status)) {
state = 0;
return state;
}
state = 0;
for (i = 0; i < dataSize; i++) {
if (data[i]) {
state = 1;
return state;
break;
}
}
state = 0;
if (data)
FreePool(data);
return state;
}
@ -53,7 +50,7 @@ get_fallback_verbose(void)
({ \
UINTN ret_ = 0; \
if (get_fallback_verbose()) \
ret_ = Print((fmt), ##__VA_ARGS__); \
ret_ = console_print((fmt), ##__VA_ARGS__); \
ret_; \
})
@ -61,8 +58,8 @@ get_fallback_verbose(void)
({ UINTN line_ = __LINE__; \
UINTN ret_ = 0; \
if (get_fallback_verbose()) { \
Print(L"%a:%d: ", __func__, line_); \
ret_ = Print((fmt), ##__VA_ARGS__); \
console_print(L"%a:%d: ", __func__, line_); \
ret_ = console_print((fmt), ##__VA_ARGS__); \
} \
ret_; \
})
@ -100,31 +97,32 @@ FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType,
static EFI_STATUS
get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize)
{
EFI_STATUS rc;
EFI_STATUS efi_status;
void *buffer = NULL;
UINTN bs = 0;
EFI_GUID finfo = EFI_FILE_INFO_ID;
/* The API here is "Call it once with bs=0, it fills in bs,
* then allocate a buffer and ask again to get it filled. */
rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, &bs, NULL);
if (rc == EFI_BUFFER_TOO_SMALL) {
buffer = AllocateZeroPool(bs);
if (!buffer) {
Print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo,
&bs, buffer);
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL);
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL)
return efi_status;
if (bs == 0)
return EFI_SUCCESS;
buffer = AllocateZeroPool(bs);
if (!buffer) {
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, buffer);
/* This checks *either* the error from the first GetInfo, if it isn't
* the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call
* in *any* case. */
if (EFI_ERROR(rc)) {
Print(L"Could not get file info: %d\n", rc);
* the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo
* call in *any* case. */
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get file info: %r\n", efi_status);
if (buffer)
FreePool(buffer);
return rc;
return efi_status;
}
EFI_FILE_INFO *fi = buffer;
*retsize = fi->FileSize;
@ -136,38 +134,46 @@ EFI_STATUS
read_file(EFI_FILE_HANDLE fh, CHAR16 *fullpath, CHAR16 **buffer, UINT64 *bs)
{
EFI_FILE_HANDLE fh2;
EFI_STATUS rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, fullpath,
EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(rc)) {
Print(L"Couldn't open \"%s\": %d\n", fullpath, rc);
return rc;
EFI_STATUS efi_status;
efi_status = fh->Open(fh, &fh2, fullpath, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status)) {
console_print(L"Couldn't open \"%s\": %r\n", fullpath, efi_status);
return efi_status;
}
UINTN len = 0;
CHAR16 *b = NULL;
rc = get_file_size(fh2, &len);
if (EFI_ERROR(rc)) {
uefi_call_wrapper(fh2->Close, 1, fh2);
return rc;
efi_status = get_file_size(fh2, &len);
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get file size for \"%s\": %r\n",
fullpath, efi_status);
fh2->Close(fh2);
return efi_status;
}
if (len > 1024 * PAGE_SIZE) {
fh2->Close(fh2);
return EFI_BAD_BUFFER_SIZE;
}
b = AllocateZeroPool(len + 2);
if (!buffer) {
Print(L"Could not allocate memory\n");
uefi_call_wrapper(fh2->Close, 1, fh2);
console_print(L"Could not allocate memory\n");
fh2->Close(fh2);
return EFI_OUT_OF_RESOURCES;
}
rc = uefi_call_wrapper(fh->Read, 3, fh, &len, b);
if (EFI_ERROR(rc)) {
efi_status = fh->Read(fh, &len, b);
if (EFI_ERROR(efi_status)) {
FreePool(buffer);
uefi_call_wrapper(fh2->Close, 1, fh2);
Print(L"Could not read file: %d\n", rc);
return rc;
fh2->Close(fh2);
console_print(L"Could not read file: %r\n", efi_status);
return efi_status;
}
*buffer = b;
*bs = len;
uefi_call_wrapper(fh2->Close, 1, fh2);
fh2->Close(fh2);
return EFI_SUCCESS;
}
@ -182,7 +188,7 @@ make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen)
CHAR16 *fullpath = AllocateZeroPool(len*sizeof(CHAR16));
if (!fullpath) {
Print(L"Could not allocate memory\n");
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
@ -210,8 +216,7 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
static int i = 0;
CHAR16 varname[] = L"Boot0000";
CHAR16 hexmap[] = L"0123456789ABCDEF";
EFI_GUID global = EFI_GLOBAL_VARIABLE;
EFI_STATUS rc;
EFI_STATUS efi_status;
for(; i <= 0xffff; i++) {
varname[4] = hexmap[(i & 0xf000) >> 12];
@ -219,7 +224,7 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
varname[6] = hexmap[(i & 0x00f0) >> 4];
varname[7] = hexmap[(i & 0x000f) >> 0];
void *var = LibGetVariable(varname, &global);
void *var = LibGetVariable(varname, &GV_GUID);
if (!var) {
int size = sizeof(UINT32) + sizeof (UINT16) +
StrLen(label)*2 + 2 + DevicePathSize(hddp) +
@ -237,9 +242,9 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
cursor += DevicePathSize(hddp);
StrCpy((CHAR16 *)cursor, arguments);
Print(L"Creating boot entry \"%s\" with label \"%s\" "
L"for file \"%s\"\n",
varname, label, filename);
console_print(L"Creating boot entry \"%s\" with label \"%s\" "
L"for file \"%s\"\n",
varname, label, filename);
if (!first_new_option) {
first_new_option = DuplicateDevicePath(fulldp);
@ -247,17 +252,18 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
first_new_option_size = StrLen(arguments) * sizeof (CHAR16);
}
rc = uefi_call_wrapper(RT->SetVariable, 5, varname,
&global, EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, data);
efi_status = gRT->SetVariable(varname, &GV_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, data);
FreePool(data);
if (EFI_ERROR(rc)) {
Print(L"Could not create variable: %d\n", rc);
return rc;
if (EFI_ERROR(efi_status)) {
console_print(L"Could not create variable: %r\n",
efi_status);
return efi_status;
}
CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16)
@ -275,10 +281,11 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp,
bootorder = newbootorder;
nbootorder += 1;
#ifdef DEBUG_FALLBACK
Print(L"nbootorder: %d\nBootOrder: ", nbootorder);
console_print(L"nbootorder: %d\nBootOrder: ",
nbootorder);
for (j = 0 ; j < nbootorder ; j++)
Print(L"%04x ", bootorder[j]);
Print(L"\n");
console_print(L"%04x ", bootorder[j]);
console_print(L"\n");
#endif
return EFI_SUCCESS;
@ -412,8 +419,7 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
int i = 0;
CHAR16 varname[] = L"Boot0000";
CHAR16 hexmap[] = L"0123456789ABCDEF";
EFI_GUID global = EFI_GLOBAL_VARIABLE;
EFI_STATUS rc;
EFI_STATUS efi_status;
UINTN max_candidate_size = calc_masked_boot_option_size(size);
CHAR8 *candidate = AllocateZeroPool(max_candidate_size);
@ -429,9 +435,9 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp,
varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0];
UINTN candidate_size = max_candidate_size;
rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global,
NULL, &candidate_size, candidate);
if (EFI_ERROR(rc))
efi_status = gRT->GetVariable(varname, &GV_GUID, NULL,
&candidate_size, candidate);
if (EFI_ERROR(efi_status))
continue;
if (candidate_size != size) {
@ -466,9 +472,8 @@ set_boot_order(void)
{
CHAR16 *oldbootorder;
UINTN size;
EFI_GUID global = EFI_GLOBAL_VARIABLE;
oldbootorder = LibGetVariableAndSize(L"BootOrder", &global, &size);
oldbootorder = LibGetVariableAndSize(L"BootOrder", &GV_GUID, &size);
if (oldbootorder) {
nbootorder = size / sizeof (CHAR16);
bootorder = oldbootorder;
@ -482,9 +487,8 @@ update_boot_order(void)
{
UINTN size;
UINTN len = 0;
EFI_GUID global = EFI_GLOBAL_VARIABLE;
CHAR16 *newbootorder = NULL;
EFI_STATUS rc;
EFI_STATUS efi_status;
size = nbootorder * sizeof(CHAR16);
newbootorder = AllocateZeroPool(size);
@ -496,19 +500,18 @@ update_boot_order(void)
UINTN j;
for (j = 0 ; j < size / sizeof (CHAR16); j++)
VerbosePrintUnprefixed(L"%04x ", newbootorder[j]);
Print(L"\n");
rc = uefi_call_wrapper(RT->GetVariable, 5, L"BootOrder", &global,
NULL, &len, NULL);
if (rc == EFI_BUFFER_TOO_SMALL)
LibDeleteVariable(L"BootOrder", &global);
console_print(L"\n");
efi_status = gRT->GetVariable(L"BootOrder", &GV_GUID, NULL, &len, NULL);
if (efi_status == EFI_BUFFER_TOO_SMALL)
LibDeleteVariable(L"BootOrder", &GV_GUID);
rc = uefi_call_wrapper(RT->SetVariable, 5, L"BootOrder", &global,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, newbootorder);
efi_status = gRT->SetVariable(L"BootOrder", &GV_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
size, newbootorder);
FreePool(newbootorder);
return rc;
return efi_status;
}
EFI_STATUS
@ -516,11 +519,11 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum
{
CHAR16 *fullpath = NULL;
UINT64 pathlen = 0;
EFI_STATUS rc = EFI_SUCCESS;
EFI_STATUS efi_status;
rc = make_full_path(dirname, filename, &fullpath, &pathlen);
if (EFI_ERROR(rc))
return rc;
efi_status = make_full_path(dirname, filename, &fullpath, &pathlen);
if (EFI_ERROR(efi_status))
return efi_status;
EFI_DEVICE_PATH *full_device_path = NULL;
EFI_DEVICE_PATH *dp = NULL;
@ -528,20 +531,21 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum
full_device_path = FileDevicePath(this_image->DeviceHandle, fullpath);
if (!full_device_path) {
rc = EFI_OUT_OF_RESOURCES;
efi_status = EFI_OUT_OF_RESOURCES;
goto err;
}
dps = DevicePathToStr(full_device_path);
VerbosePrint(L"file DP: %s\n", dps);
FreePool(dps);
rc = FindSubDevicePath(full_device_path,
MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp);
if (EFI_ERROR(rc)) {
if (rc == EFI_NOT_FOUND) {
efi_status = FindSubDevicePath(full_device_path,
MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP,
&dp);
if (EFI_ERROR(efi_status)) {
if (efi_status == EFI_NOT_FOUND) {
dp = full_device_path;
} else {
rc = EFI_OUT_OF_RESOURCES;
efi_status = EFI_OUT_OF_RESOURCES;
goto err;
}
}
@ -566,9 +570,11 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum
}
UINT16 option;
rc = find_boot_option(dp, full_device_path, fullpath, label, arguments, &option);
if (EFI_ERROR(rc)) {
add_boot_option(dp, full_device_path, fullpath, label, arguments);
efi_status = find_boot_option(dp, full_device_path, fullpath, label,
arguments, &option);
if (EFI_ERROR(efi_status)) {
add_boot_option(dp, full_device_path, fullpath, label,
arguments);
} else if (option != 0) {
CHAR16 *newbootorder;
newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder);
@ -590,7 +596,7 @@ err:
FreePool(dp);
if (fullpath)
FreePool(fullpath);
return rc;
return efi_status;
}
EFI_STATUS
@ -628,21 +634,22 @@ try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename)
{
CHAR16 *fullpath = NULL;
UINT64 pathlen = 0;
EFI_STATUS rc;
EFI_STATUS efi_status;
rc = make_full_path(dirname, filename, &fullpath, &pathlen);
if (EFI_ERROR(rc))
return rc;
efi_status = make_full_path(dirname, filename, &fullpath, &pathlen);
if (EFI_ERROR(efi_status))
return efi_status;
VerbosePrint(L"Found file \"%s\"\n", fullpath);
CHAR16 *buffer;
UINT64 bs;
rc = read_file(fh, fullpath, &buffer, &bs);
if (EFI_ERROR(rc)) {
Print(L"Could not read file \"%s\": %d\n", fullpath, rc);
efi_status = read_file(fh, fullpath, &buffer, &bs);
if (EFI_ERROR(efi_status)) {
console_print(L"Could not read file \"%s\": %r\n",
fullpath, efi_status);
FreePool(fullpath);
return rc;
return efi_status;
}
FreePool(fullpath);
@ -685,31 +692,37 @@ try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename)
EFI_STATUS
find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
{
EFI_STATUS rc;
EFI_STATUS efi_status;
void *buffer = NULL;
UINTN bs = 0;
EFI_GUID finfo = EFI_FILE_INFO_ID;
/* The API here is "Call it once with bs=0, it fills in bs,
* then allocate a buffer and ask again to get it filled. */
rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, &bs, NULL);
if (rc == EFI_BUFFER_TOO_SMALL) {
buffer = AllocateZeroPool(bs);
if (!buffer) {
Print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo,
&bs, buffer);
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL);
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
console_print(L"Could not get directory info for \\EFI\\%s\\: %r\n",
dirname, efi_status);
return efi_status;
}
if (bs == 0)
return EFI_SUCCESS;
buffer = AllocateZeroPool(bs);
if (!buffer) {
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, buffer);
/* This checks *either* the error from the first GetInfo, if it isn't
* the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call
* in *any* case. */
if (EFI_ERROR(rc)) {
Print(L"Could not get info for \"%s\": %d\n", dirname, rc);
* the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo
* call in *any* case. */
if (EFI_ERROR(efi_status)) {
console_print(L"Could not get info for \"%s\": %r\n", dirname,
efi_status);
if (buffer)
FreePool(buffer);
return rc;
return efi_status;
}
EFI_FILE_INFO *fi = buffer;
@ -725,12 +738,12 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
bs = 0;
do {
bs = 0;
rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, NULL);
if (EFI_ERROR(rc) && rc != EFI_BUFFER_TOO_SMALL) {
Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc);
if (buffer)
FreePool(buffer);
return rc;
efi_status = fh->Read(fh, &bs, NULL);
if (EFI_ERROR(efi_status) &&
efi_status != EFI_BUFFER_TOO_SMALL) {
console_print(L"Could not read \\EFI\\%s\\: %r\n",
dirname, efi_status);
return efi_status;
}
/* If there's no data to read, don't try to allocate 0 bytes
* and read the data... */
@ -739,15 +752,16 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
buffer = AllocateZeroPool(bs);
if (!buffer) {
Print(L"Could not allocate memory\n");
console_print(L"Could not allocate memory\n");
return EFI_OUT_OF_RESOURCES;
}
rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, buffer);
if (EFI_ERROR(rc)) {
Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc);
efi_status = fh->Read(fh, &bs, buffer);
if (EFI_ERROR(efi_status)) {
console_print(L"Could not read \\EFI\\%s\\: %r\n",
dirname, efi_status);
FreePool(buffer);
return rc;
return efi_status;
}
if (bs == 0)
@ -766,105 +780,108 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname)
buffer = NULL;
} while (bs != 0);
rc = EFI_SUCCESS;
efi_status = EFI_SUCCESS;
if (bootarchcsv) {
EFI_FILE_HANDLE fh2;
rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2,
bootarchcsv, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(rc) || fh2 == NULL) {
Print(L"Couldn't open \\EFI\\%s\\%s: %d\n",
dirname, bootarchcsv, rc);
efi_status = fh->Open(fh, &fh2, bootarchcsv,
EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status) || fh2 == NULL) {
console_print(L"Couldn't open \\EFI\\%s\\%s: %r\n",
dirname, bootarchcsv, efi_status);
} else {
rc = try_boot_csv(fh2, dirname, bootarchcsv);
uefi_call_wrapper(fh2->Close, 1, fh2);
efi_status = try_boot_csv(fh2, dirname, bootarchcsv);
fh2->Close(fh2);
if (EFI_ERROR(efi_status))
console_print(L"Could not process \\EFI\\%s\\%s: %r\n",
dirname, bootarchcsv, efi_status);
}
}
if ((EFI_ERROR(rc) || !bootarchcsv) && bootcsv) {
if ((EFI_ERROR(efi_status) || !bootarchcsv) && bootcsv) {
EFI_FILE_HANDLE fh2;
rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2,
bootcsv, EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(rc) || fh2 == NULL) {
Print(L"Couldn't open \\EFI\\%s\\%s: %d\n",
dirname, bootcsv, rc);
efi_status = fh->Open(fh, &fh2, bootcsv,
EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status) || fh2 == NULL) {
console_print(L"Couldn't open \\EFI\\%s\\%s: %r\n",
dirname, bootcsv, efi_status);
} else {
rc = try_boot_csv(fh2, dirname, bootcsv);
uefi_call_wrapper(fh2->Close, 1, fh2);
efi_status = try_boot_csv(fh2, dirname, bootcsv);
fh2->Close(fh2);
if (EFI_ERROR(efi_status))
console_print(L"Could not process \\EFI\\%s\\%s: %r\n",
dirname, bootarchcsv, efi_status);
}
}
rc = EFI_SUCCESS;
return rc;
return EFI_SUCCESS;
}
EFI_STATUS
find_boot_options(EFI_HANDLE device)
{
EFI_STATUS rc = EFI_SUCCESS;
EFI_STATUS efi_status;
EFI_FILE_IO_INTERFACE *fio = NULL;
rc = uefi_call_wrapper(BS->HandleProtocol, 3, device,
&FileSystemProtocol, (void **)&fio);
if (EFI_ERROR(rc)) {
Print(L"Couldn't find file system: %d\n", rc);
return rc;
efi_status = gBS->HandleProtocol(device, &FileSystemProtocol,
(void **) &fio);
if (EFI_ERROR(efi_status)) {
console_print(L"Couldn't find file system: %r\n", efi_status);
return efi_status;
}
/* EFI_FILE_HANDLE is a pointer to an EFI_FILE, and I have
* *no idea* what frees the memory allocated here. Hopefully
* Close() does. */
EFI_FILE_HANDLE fh = NULL;
rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &fh);
if (EFI_ERROR(rc) || fh == NULL) {
Print(L"Couldn't open file system: %d\n", rc);
return rc;
efi_status = fio->OpenVolume(fio, &fh);
if (EFI_ERROR(efi_status) || fh == NULL) {
console_print(L"Couldn't open file system: %r\n", efi_status);
return efi_status;
}
EFI_FILE_HANDLE fh2 = NULL;
rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, L"EFI",
EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(rc) || fh2 == NULL) {
Print(L"Couldn't open EFI: %d\n", rc);
uefi_call_wrapper(fh->Close, 1, fh);
return rc;
efi_status = fh->Open(fh, &fh2, L"EFI", EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status) || fh2 == NULL) {
console_print(L"Couldn't open EFI: %r\n", efi_status);
fh->Close(fh);
return efi_status;
}
rc = uefi_call_wrapper(fh2->SetPosition, 2, fh2, 0);
if (EFI_ERROR(rc)) {
Print(L"Couldn't set file position: %d\n", rc);
uefi_call_wrapper(fh2->Close, 1, fh2);
uefi_call_wrapper(fh->Close, 1, fh);
return rc;
efi_status = fh2->SetPosition(fh2, 0);
if (EFI_ERROR(efi_status)) {
console_print(L"Couldn't set file position: %r\n", efi_status);
fh2->Close(fh2);
fh->Close(fh);
return efi_status;
}
void *buffer;
UINTN bs;
do {
bs = 0;
rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, NULL);
if (rc == EFI_BUFFER_TOO_SMALL ||
(rc == EFI_SUCCESS && bs != 0)) {
buffer = AllocateZeroPool(bs);
if (!buffer) {
Print(L"Could not allocate memory\n");
/* sure, this might work, why not? */
uefi_call_wrapper(fh2->Close, 1, fh2);
uefi_call_wrapper(fh->Close, 1, fh);
return EFI_OUT_OF_RESOURCES;
}
rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, buffer);
efi_status = fh2->Read(fh2, &bs, NULL);
if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) {
console_print(L"Could not read \\EFI\\: %r\n", efi_status);
return efi_status;
}
if (bs == 0)
break;
if (EFI_ERROR(rc)) {
Print(L"Could not read \\EFI\\: %d\n", rc);
buffer = AllocateZeroPool(bs);
if (!buffer) {
console_print(L"Could not allocate memory\n");
/* sure, this might work, why not? */
fh2->Close(fh2);
fh->Close(fh);
return EFI_OUT_OF_RESOURCES;
}
efi_status = fh2->Read(fh2, &bs, buffer);
if (EFI_ERROR(efi_status)) {
if (buffer) {
FreePool(buffer);
buffer = NULL;
}
uefi_call_wrapper(fh2->Close, 1, fh2);
uefi_call_wrapper(fh->Close, 1, fh);
return rc;
fh2->Close(fh2);
fh->Close(fh);
return efi_status;
}
EFI_FILE_INFO *fi = buffer;
@ -883,74 +900,77 @@ find_boot_options(EFI_HANDLE device)
VerbosePrint(L"Found directory named \"%s\"\n", fi->FileName);
EFI_FILE_HANDLE fh3;
rc = uefi_call_wrapper(fh->Open, 5, fh2, &fh3, fi->FileName,
EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(rc)) {
Print(L"%d Couldn't open %s: %d\n", __LINE__, fi->FileName, rc);
efi_status = fh2->Open(fh2, &fh3, fi->FileName,
EFI_FILE_READ_ONLY, 0);
if (EFI_ERROR(efi_status)) {
console_print(L"%d Couldn't open %s: %r\n", __LINE__,
fi->FileName, efi_status);
FreePool(buffer);
buffer = NULL;
continue;
}
rc = find_boot_csv(fh3, fi->FileName);
efi_status = find_boot_csv(fh3, fi->FileName);
fh3->Close(fh3);
FreePool(buffer);
buffer = NULL;
if (rc == EFI_OUT_OF_RESOURCES)
if (efi_status == EFI_OUT_OF_RESOURCES)
break;
} while (1);
if (rc == EFI_SUCCESS && nbootorder > 0)
rc = update_boot_order();
if (!EFI_ERROR(efi_status) && nbootorder > 0)
efi_status = update_boot_order();
uefi_call_wrapper(fh2->Close, 1, fh2);
uefi_call_wrapper(fh->Close, 1, fh);
return rc;
fh2->Close(fh2);
fh->Close(fh);
return efi_status;
}
static EFI_STATUS
try_start_first_option(EFI_HANDLE parent_image_handle)
{
EFI_STATUS rc;
EFI_STATUS efi_status;
EFI_HANDLE image_handle;
if (!first_new_option) {
return EFI_SUCCESS;
}
rc = uefi_call_wrapper(BS->LoadImage, 6, 0, parent_image_handle,
first_new_option, NULL, 0,
&image_handle);
if (EFI_ERROR(rc)) {
efi_status = gBS->LoadImage(0, parent_image_handle, first_new_option,
NULL, 0, &image_handle);
if (EFI_ERROR(efi_status)) {
CHAR16 *dps = DevicePathToStr(first_new_option);
UINTN s = DevicePathSize(first_new_option);
unsigned int i;
UINT8 *dpv = (void *)first_new_option;
Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps);
console_print(L"LoadImage failed: %r\nDevice path: \"%s\"\n",
efi_status, dps);
for (i = 0; i < s; i++) {
if (i > 0 && i % 16 == 0)
Print(L"\n");
Print(L"%02x ", dpv[i]);
console_print(L"\n");
console_print(L"%02x ", dpv[i]);
}
Print(L"\n");
console_print(L"\n");
uefi_call_wrapper(BS->Stall, 1, 500000000);
return rc;
msleep(500000000);
return efi_status;
}
EFI_LOADED_IMAGE *image;
rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, &LoadedImageProtocol, (void *)&image);
if (!EFI_ERROR(rc)) {
efi_status = gBS->HandleProtocol(image_handle, &LoadedImageProtocol,
(void *) &image);
if (!EFI_ERROR(efi_status)) {
image->LoadOptions = first_new_option_args;
image->LoadOptionsSize = first_new_option_size;
}
rc = uefi_call_wrapper(BS->StartImage, 3, image_handle, NULL, NULL);
if (EFI_ERROR(rc)) {
Print(L"StartImage failed: %d\n", rc);
uefi_call_wrapper(BS->Stall, 1, 500000000);
efi_status = gBS->StartImage(image_handle, NULL, NULL);
if (EFI_ERROR(efi_status)) {
console_print(L"StartImage failed: %r\n", efi_status);
msleep(500000000);
}
return rc;
return efi_status;
}
extern EFI_STATUS
@ -960,31 +980,33 @@ static void
__attribute__((__optimize__("0")))
debug_hook(void)
{
EFI_GUID guid = SHIM_LOCK_GUID;
UINT8 *data = NULL;
UINTN dataSize = 0;
EFI_STATUS efi_status;
volatile register int x = 0;
extern char _etext, _edata;
efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, guid);
efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize,
SHIM_LOCK_GUID);
if (EFI_ERROR(efi_status)) {
return;
}
if (data)
FreePool(data);
if (x)
return;
x = 1;
Print(L"add-symbol-file "DEBUGDIR
L"fb" EFI_ARCH L".efi.debug %p -s .data %p\n", &_etext,
&_edata);
console_print(L"add-symbol-file "DEBUGDIR
L"fb" EFI_ARCH L".efi.debug %p -s .data %p\n",
&_etext, &_edata);
}
EFI_STATUS
efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
{
EFI_STATUS rc;
EFI_STATUS efi_status;
InitializeLib(image, systab);
@ -993,39 +1015,41 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab)
*/
debug_hook();
rc = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (void *)&this_image);
if (EFI_ERROR(rc)) {
Print(L"Error: could not find loaded image: %d\n", rc);
return rc;
efi_status = gBS->HandleProtocol(image, &LoadedImageProtocol,
(void *) &this_image);
if (EFI_ERROR(efi_status)) {
console_print(L"Error: could not find loaded image: %r\n",
efi_status);
return efi_status;
}
Print(L"System BootOrder not found. Initializing defaults.\n");
console_print(L"System BootOrder not found. Initializing defaults.\n");
set_boot_order();
rc = find_boot_options(this_image->DeviceHandle);
if (EFI_ERROR(rc)) {
Print(L"Error: could not find boot options: %d\n", rc);
return rc;
efi_status = find_boot_options(this_image->DeviceHandle);
if (EFI_ERROR(efi_status)) {
console_print(L"Error: could not find boot options: %r\n",
efi_status);
return efi_status;
}
rc = fallback_should_prefer_reset();
if (EFI_ERROR(rc)) {
efi_status = fallback_should_prefer_reset();
if (EFI_ERROR(efi_status)) {
VerbosePrint(L"tpm not present, starting the first image\n");
try_start_first_option(image);
} else {
VerbosePrint(L"tpm present, resetting system\n");
}
Print(L"Reset System\n");
console_print(L"Reset System\n");
if (get_fallback_verbose()) {
Print(L"Verbose enabled, sleeping for half a second\n");
uefi_call_wrapper(BS->Stall, 1, 500000);
console_print(L"Verbose enabled, sleeping for half a second\n");
msleep(500000);
}
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold,
EFI_SUCCESS, 0, NULL);
gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
return EFI_SUCCESS;
}

View File

@ -33,19 +33,8 @@
#include <efi.h>
#include <efilib.h>
#include "str.h"
#include "Http.h"
#include "Ip4Config2.h"
#include "Ip6Config.h"
extern UINT8 in_protocol;
#define perror(fmt, ...) ({ \
UINTN __perror_ret = 0; \
if (!in_protocol) \
__perror_ret = Print((fmt), ##__VA_ARGS__); \
__perror_ret; \
})
#include "shim.h"
static UINTN
ascii_to_int (CONST CHAR8 *str)
@ -105,10 +94,11 @@ find_httpboot (EFI_HANDLE device)
{
EFI_DEVICE_PATH *unpacked;
EFI_DEVICE_PATH *Node;
EFI_DEVICE_PATH *NextNode;
MAC_ADDR_DEVICE_PATH *MacNode;
URI_DEVICE_PATH *UriNode;
UINTN uri_size;
BOOLEAN ip_found = FALSE;
BOOLEAN ret = FALSE;
if (uri) {
FreePool(uri);
@ -128,50 +118,60 @@ find_httpboot (EFI_HANDLE device)
}
Node = unpacked;
/* Traverse the device path to find IPv4()/Uri() or IPv6()/Uri() */
/* Traverse the device path to find IPv4()/.../Uri() or
* IPv6()/.../Uri() */
while (!IsDevicePathEnd(Node)) {
/* Save the MAC node so we can match the net card later */
if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
DevicePathSubType(Node) == MSG_MAC_ADDR_DP) {
MacNode = (MAC_ADDR_DEVICE_PATH *)Node;
CopyMem(&mac_addr, &MacNode->MacAddress, sizeof(EFI_MAC_ADDRESS));
}
if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
(DevicePathSubType(Node) == MSG_IPv4_DP ||
DevicePathSubType(Node) == MSG_IPv6_DP)) {
/* Save the IP node so we can set up the connection later */
CopyMem(&mac_addr, &MacNode->MacAddress,
sizeof(EFI_MAC_ADDRESS));
} else if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
(DevicePathSubType(Node) == MSG_IPv4_DP ||
DevicePathSubType(Node) == MSG_IPv6_DP)) {
/* Save the IP node so we can set up the connection */
/* later */
if (DevicePathSubType(Node) == MSG_IPv6_DP) {
CopyMem(&ip6_node, Node, sizeof(IPv6_DEVICE_PATH));
CopyMem(&ip6_node, Node,
sizeof(IPv6_DEVICE_PATH));
is_ip6 = TRUE;
} else {
CopyMem(&ip4_node, Node, sizeof(IPv4_DEVICE_PATH));
CopyMem(&ip4_node, Node,
sizeof(IPv4_DEVICE_PATH));
is_ip6 = FALSE;
}
Node = NextDevicePathNode(Node);
ip_found = TRUE;
} else if (ip_found == TRUE &&
(DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
DevicePathSubType(Node) == MSG_URI_DP)) {
EFI_DEVICE_PATH *NextNode;
/* Check if the URI node is the last node since the */
/* RAMDISK node could be appended, and we don't need */
/* to download the second stage loader in that case. */
NextNode = NextDevicePathNode(Node);
if (DevicePathType(Node) == MESSAGING_DEVICE_PATH &&
DevicePathSubType(Node) == MSG_URI_DP &&
IsDevicePathEnd(NextNode)) {
/* Save the current URI */
UriNode = (URI_DEVICE_PATH *)Node;
uri_size = strlena(UriNode->Uri);
uri = AllocatePool(uri_size + 1);
if (!uri) {
perror(L"Failed to allocate uri\n");
return FALSE;
}
CopyMem(uri, UriNode->Uri, uri_size + 1);
FreePool(unpacked);
return TRUE;
if (!IsDevicePathEnd(NextNode))
goto out;
/* Save the current URI */
UriNode = (URI_DEVICE_PATH *)Node;
uri_size = strlena(UriNode->Uri);
uri = AllocatePool(uri_size + 1);
if (!uri) {
perror(L"Failed to allocate uri\n");
goto out;
}
CopyMem(uri, UriNode->Uri, uri_size + 1);
ret = TRUE;
goto out;
}
Node = NextDevicePathNode(Node);
}
out:
FreePool(unpacked);
return FALSE;
return ret;
}
static EFI_STATUS
@ -247,7 +247,6 @@ extract_hostname (CONST CHAR8 *url, CHAR8 **hostname)
static EFI_HANDLE
get_nic_handle (EFI_MAC_ADDRESS *mac)
{
EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
EFI_DEVICE_PATH *unpacked = NULL;
EFI_DEVICE_PATH *Node;
EFI_DEVICE_PATH *temp_path = NULL;
@ -256,17 +255,14 @@ get_nic_handle (EFI_MAC_ADDRESS *mac)
EFI_HANDLE *buffer;
UINTN NoHandles;
UINTN i;
EFI_STATUS status;
EFI_STATUS efi_status;
/* Get the list of handles that support the HTTP service binding
protocol */
status = uefi_call_wrapper(BS->LocateHandleBuffer, 5,
ByProtocol,
&http_binding_guid,
NULL,
&NoHandles,
&buffer);
if (EFI_ERROR(status))
efi_status = gBS->LocateHandleBuffer(ByProtocol,
&EFI_HTTP_BINDING_GUID,
NULL, &NoHandles, &buffer);
if (EFI_ERROR(efi_status))
return NULL;
for (i = 0; i < NoHandles; i++) {
@ -303,7 +299,7 @@ out:
}
static BOOLEAN
is_unspecified_addr (EFI_IPv6_ADDRESS ip6)
is_unspecified_ip6addr (EFI_IPv6_ADDRESS ip6)
{
UINT8 i;
@ -315,82 +311,117 @@ is_unspecified_addr (EFI_IPv6_ADDRESS ip6)
return TRUE;
}
static inline void
print_ip6_addr(EFI_IPv6_ADDRESS ip6addr)
{
perror(L"%x:%x:%x:%x:%x:%x:%x:%x\n",
ip6addr.Addr[0] << 8 | ip6addr.Addr[1],
ip6addr.Addr[2] << 8 | ip6addr.Addr[3],
ip6addr.Addr[4] << 8 | ip6addr.Addr[5],
ip6addr.Addr[6] << 8 | ip6addr.Addr[7],
ip6addr.Addr[8] << 8 | ip6addr.Addr[9],
ip6addr.Addr[10] << 8 | ip6addr.Addr[11],
ip6addr.Addr[12] << 8 | ip6addr.Addr[13],
ip6addr.Addr[14] << 8 | ip6addr.Addr[15]);
}
static EFI_STATUS
set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node)
{
EFI_GUID ip6_config_guid = EFI_IP6_CONFIG_PROTOCOL_GUID;
EFI_IP6_CONFIG_PROTOCOL *ip6cfg;
EFI_IP6_CONFIG_MANUAL_ADDRESS ip6;
EFI_IPv6_ADDRESS gateway;
EFI_STATUS status;
EFI_STATUS efi_status;
status = uefi_call_wrapper(BS->HandleProtocol, 3,
nic,
&ip6_config_guid,
(VOID **)&ip6cfg);
if (EFI_ERROR (status))
return status;
efi_status = gBS->HandleProtocol(nic, &EFI_IP6_CONFIG_GUID,
(VOID **)&ip6cfg);
if (EFI_ERROR(efi_status))
return efi_status;
ip6.Address = ip6node->LocalIpAddress;
ip6.PrefixLength = ip6node->PrefixLength;
ip6.IsAnycast = FALSE;
status = uefi_call_wrapper(ip6cfg->SetData, 4,
ip6cfg,
Ip6ConfigDataTypeManualAddress,
sizeof(ip6),
&ip6);
if (EFI_ERROR (status))
return status;
efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeManualAddress,
sizeof(ip6), &ip6);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to set IPv6 Address:\nIP: ");
print_ip6_addr(ip6.Address);
perror(L"Prefix Length: %u\n", ip6.PrefixLength);
return efi_status;
}
gateway = ip6node->GatewayIpAddress;
if (is_unspecified_addr(gateway))
if (is_unspecified_ip6addr(gateway))
return EFI_SUCCESS;
status = uefi_call_wrapper(ip6cfg->SetData, 4,
ip6cfg,
Ip6ConfigDataTypeGateway,
sizeof(gateway),
&gateway);
if (EFI_ERROR (status))
return status;
efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeGateway,
sizeof(gateway), &gateway);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to set IPv6 Gateway:\nIP: ");
print_ip6_addr(gateway);
return efi_status;
}
return EFI_SUCCESS;
}
static BOOLEAN
is_unspecified_ip4addr (EFI_IPv4_ADDRESS ip4)
{
UINT8 i;
for (i = 0; i<4; i++) {
if (ip4.Addr[i] != 0)
return FALSE;
}
return TRUE;
}
static inline void
print_ip4_addr(EFI_IPv4_ADDRESS ip4addr)
{
perror(L"%u.%u.%u.%u\n",
ip4addr.Addr[0], ip4addr.Addr[1],
ip4addr.Addr[2], ip4addr.Addr[3]);
}
static EFI_STATUS
set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node)
{
EFI_GUID ip4_config2_guid = EFI_IP4_CONFIG2_PROTOCOL_GUID;
EFI_IP4_CONFIG2_PROTOCOL *ip4cfg2;
EFI_IP4_CONFIG2_MANUAL_ADDRESS ip4;
EFI_IPv4_ADDRESS gateway;
EFI_STATUS status;
EFI_STATUS efi_status;
status = uefi_call_wrapper(BS->HandleProtocol, 3,
nic,
&ip4_config2_guid,
(VOID **)&ip4cfg2);
if (EFI_ERROR (status))
return status;
efi_status = gBS->HandleProtocol(nic, &EFI_IP4_CONFIG2_GUID,
(VOID **)&ip4cfg2);
if (EFI_ERROR(efi_status))
return efi_status;
ip4.Address = ip4node->LocalIpAddress;
ip4.SubnetMask = ip4node->SubnetMask;
status = uefi_call_wrapper(ip4cfg2->SetData, 4,
ip4cfg2,
Ip4Config2DataTypeManualAddress,
sizeof(ip4),
&ip4);
if (EFI_ERROR (status))
return status;
efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeManualAddress,
sizeof(ip4), &ip4);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to Set IPv4 Address:\nIP: ");
print_ip4_addr(ip4.Address);
perror(L"Mask: ");
print_ip4_addr(ip4.SubnetMask);
return efi_status;
}
gateway = ip4node->GatewayIpAddress;
status = uefi_call_wrapper(ip4cfg2->SetData, 4,
ip4cfg2,
Ip4Config2DataTypeGateway,
sizeof(gateway),
&gateway);
if (EFI_ERROR (status))
return status;
if (is_unspecified_ip4addr(gateway))
return EFI_SUCCESS;
efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeGateway,
sizeof(gateway), &gateway);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to Set IPv4 Gateway:\nGateway: ");
print_ip4_addr(gateway);
return efi_status;
}
return EFI_SUCCESS;
}
@ -425,7 +456,7 @@ configure_http (EFI_HTTP_PROTOCOL *http, BOOLEAN is_ip6)
http_mode.AccessPoint.IPv6Node = &ip6node;
}
return uefi_call_wrapper(http->Configure, 2, http, &http_mode);
return http->Configure(http, &http_mode);
}
static EFI_STATUS
@ -437,7 +468,7 @@ send_http_request (EFI_HTTP_PROTOCOL *http, CHAR8 *hostname, CHAR8 *uri)
EFI_HTTP_HEADER headers[3];
BOOLEAN request_done;
CHAR16 *Url = NULL;
EFI_STATUS status;
EFI_STATUS efi_status;
EFI_STATUS event_status;
/* Convert the ascii string to the UCS2 string */
@ -466,35 +497,33 @@ send_http_request (EFI_HTTP_PROTOCOL *http, CHAR8 *hostname, CHAR8 *uri)
tx_token.Message = &tx_message;
tx_token.Event = NULL;
request_done = FALSE;
status = uefi_call_wrapper(BS->CreateEvent, 5,
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
httpnotify,
&request_done,
&tx_token.Event);
if (EFI_ERROR(status)) {
perror(L"Failed to Create Event for HTTP request: %r\n", status);
efi_status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
httpnotify, &request_done,
&tx_token.Event);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to Create Event for HTTP request: %r\n",
efi_status);
goto no_event;
}
/* Send out the request */
status = uefi_call_wrapper(http->Request, 2, http, &tx_token);
if (EFI_ERROR(status)) {
perror(L"HTTP request failed: %r\n", status);
efi_status = http->Request(http, &tx_token);
if (EFI_ERROR(efi_status)) {
perror(L"HTTP request failed: %r\n", efi_status);
goto error;
}
/* Wait for the response */
while (!request_done)
uefi_call_wrapper(http->Poll, 1, http);
http->Poll(http);
if (EFI_ERROR(tx_token.Status)) {
perror(L"HTTP request: %r\n", tx_token.Status);
status = tx_token.Status;
efi_status = tx_token.Status;
}
error:
event_status = uefi_call_wrapper(BS->CloseEvent, 1, tx_token.Event);
event_status = gBS->CloseEvent(tx_token.Event);
if (EFI_ERROR(event_status)) {
perror(L"Failed to close Event for HTTP request: %r\n",
event_status);
@ -504,7 +533,7 @@ no_event:
if (Url)
FreePool(Url);
return status;
return efi_status;
}
static EFI_STATUS
@ -517,7 +546,7 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
BOOLEAN response_done;
UINTN i, downloaded;
CHAR8 rx_buffer[9216];
EFI_STATUS status;
EFI_STATUS efi_status;
EFI_STATUS event_status;
/* Initialize the rx message and buffer */
@ -532,31 +561,29 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
rx_token.Message = &rx_message;
rx_token.Event = NULL;
response_done = FALSE;
status = uefi_call_wrapper(BS->CreateEvent, 5,
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
httpnotify,
&response_done,
&rx_token.Event);
if (EFI_ERROR(status)) {
perror(L"Failed to Create Event for HTTP response: %r\n", status);
efi_status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
httpnotify, &response_done,
&rx_token.Event);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to Create Event for HTTP response: %r\n",
efi_status);
goto no_event;
}
/* Notify the firmware to receive the HTTP messages */
status = uefi_call_wrapper(http->Response, 2, http, &rx_token);
if (EFI_ERROR(status)) {
perror(L"HTTP response failed: %r\n", status);
efi_status = http->Response(http, &rx_token);
if (EFI_ERROR(efi_status)) {
perror(L"HTTP response failed: %r\n", efi_status);
goto error;
}
/* Wait for the response */
while (!response_done)
uefi_call_wrapper(http->Poll, 1, http);
http->Poll(http);
if (EFI_ERROR(rx_token.Status)) {
perror(L"HTTP response: %r\n", rx_token.Status);
status = rx_token.Status;
efi_status = rx_token.Status;
goto error;
}
@ -565,7 +592,7 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
if (http_status != HTTP_STATUS_200_OK) {
perror(L"HTTP Status Code: %d\n",
convert_http_status_code(http_status));
status = EFI_ABORTED;
efi_status = EFI_ABORTED;
goto error;
}
@ -605,23 +632,23 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
rx_token.Status = EFI_NOT_READY;
response_done = FALSE;
status = uefi_call_wrapper(http->Response, 2, http, &rx_token);
if (EFI_ERROR(status)) {
perror(L"HTTP response failed: %r\n", status);
efi_status = http->Response(http, &rx_token);
if (EFI_ERROR(efi_status)) {
perror(L"HTTP response failed: %r\n", efi_status);
goto error;
}
while (!response_done)
uefi_call_wrapper(http->Poll, 1, http);
http->Poll(http);
if (EFI_ERROR(rx_token.Status)) {
perror(L"HTTP response: %r\n", rx_token.Status);
status = rx_token.Status;
efi_status = rx_token.Status;
goto error;
}
if (rx_message.BodyLength + downloaded > *buf_size) {
status = EFI_BAD_BUFFER_SIZE;
efi_status = EFI_BAD_BUFFER_SIZE;
goto error;
}
@ -631,17 +658,17 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size)
}
error:
event_status = uefi_call_wrapper(BS->CloseEvent, 1, rx_token.Event);
event_status = gBS->CloseEvent(rx_token.Event);
if (EFI_ERROR(event_status)) {
perror(L"Failed to close Event for HTTP response: %r\n",
event_status);
}
no_event:
if (EFI_ERROR(status) && *buffer)
if (EFI_ERROR(efi_status) && *buffer)
FreePool(*buffer);
return status;
return efi_status;
}
static EFI_STATUS
@ -649,64 +676,61 @@ http_fetch (EFI_HANDLE image, EFI_HANDLE device,
CHAR8 *hostname, CHAR8 *uri, BOOLEAN is_ip6,
VOID **buffer, UINT64 *buf_size)
{
EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID;
EFI_GUID http_protocol_guid = EFI_HTTP_PROTOCOL_GUID;
EFI_SERVICE_BINDING *service;
EFI_HANDLE http_handle;
EFI_HTTP_PROTOCOL *http;
EFI_STATUS status;
EFI_STATUS efi_status;
EFI_STATUS child_status;
*buffer = NULL;
*buf_size = 0;
/* Open HTTP Service Binding Protocol */
status = uefi_call_wrapper(BS->OpenProtocol, 6, device,
&http_binding_guid, (VOID **)&service,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR (status))
return status;
efi_status = gBS->OpenProtocol(device, &EFI_HTTP_BINDING_GUID,
(VOID **) &service, image, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(efi_status))
return efi_status;
/* Create the ChildHandle from the Service Binding */
/* Set the handle to NULL to request a new handle */
http_handle = NULL;
status = uefi_call_wrapper(service->CreateChild, 2, service,
&http_handle);
if (EFI_ERROR (status))
return status;
efi_status = service->CreateChild(service, &http_handle);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to create the ChildHandle\n");
return efi_status;
}
/* Get the http protocol */
status = uefi_call_wrapper(BS->HandleProtocol, 3, http_handle,
&http_protocol_guid, (VOID **)&http);
if (EFI_ERROR (status)) {
efi_status = gBS->HandleProtocol(http_handle, &EFI_HTTP_PROTOCOL_GUID,
(VOID **) &http);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to get http\n");
goto error;
}
status = configure_http(http, is_ip6);
if (EFI_ERROR (status)) {
perror(L"Failed to configure http: %r\n", status);
efi_status = configure_http(http, is_ip6);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to configure http: %r\n", efi_status);
goto error;
}
status = send_http_request(http, hostname, uri);
if (EFI_ERROR(status)) {
perror(L"Failed to send HTTP request: %r\n", status);
efi_status = send_http_request(http, hostname, uri);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to send HTTP request: %r\n", efi_status);
goto error;
}
status = receive_http_response(http, buffer, buf_size);
if (EFI_ERROR(status)) {
perror(L"Failed to receive HTTP response: %r\n", status);
efi_status = receive_http_response(http, buffer, buf_size);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to receive HTTP response: %r\n", efi_status);
goto error;
}
error:
child_status = uefi_call_wrapper(service->DestroyChild, 2, service,
http_handle);
if (EFI_ERROR(status)) {
return status;
child_status = service->DestroyChild(service, http_handle);
if (EFI_ERROR(efi_status)) {
return efi_status;
} else if (EFI_ERROR(child_status)) {
return child_status;
}
@ -717,7 +741,7 @@ error:
EFI_STATUS
httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
{
EFI_STATUS status;
EFI_STATUS efi_status;
EFI_HANDLE nic;
CHAR8 *next_loader = NULL;
CHAR8 *next_uri = NULL;
@ -729,16 +753,16 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
next_loader = translate_slashes(DEFAULT_LOADER_CHAR);
/* Create the URI for the next loader based on the original URI */
status = generate_next_uri(uri, next_loader, &next_uri);
if (EFI_ERROR (status)) {
perror(L"Next URI: %a, %r\n", next_uri, status);
efi_status = generate_next_uri(uri, next_loader, &next_uri);
if (EFI_ERROR(efi_status)) {
perror(L"Next URI: %a, %r\n", next_uri, efi_status);
goto error;
}
/* Extract the hostname (or IP) from URI */
status = extract_hostname(uri, &hostname);
if (EFI_ERROR (status)) {
perror(L"hostname: %a, %r\n", hostname, status);
efi_status = extract_hostname(uri, &hostname);
if (EFI_ERROR(efi_status)) {
perror(L"hostname: %a, %r\n", hostname, efi_status);
goto error;
}
@ -746,6 +770,7 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
also supports the HTTP service binding protocol */
nic = get_nic_handle(&mac_addr);
if (!nic) {
efi_status = EFI_NOT_FOUND;
goto error;
}
@ -753,19 +778,19 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size)
information in the device path node. We have to set up the
connection on our own for the further operations. */
if (!is_ip6)
status = set_ip4(nic, &ip4_node);
efi_status = set_ip4(nic, &ip4_node);
else
status = set_ip6(nic, &ip6_node);
if (EFI_ERROR (status)) {
perror(L"Failed to set IP for HTTPBoot: %r\n", status);
efi_status = set_ip6(nic, &ip6_node);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to set IP for HTTPBoot: %r\n", efi_status);
goto error;
}
/* Use HTTP protocl to fetch the remote file */
status = http_fetch (image, nic, hostname, next_uri, is_ip6,
buffer, buf_size);
if (EFI_ERROR (status)) {
perror(L"Failed to fetch image: %r\n", status);
efi_status = http_fetch (image, nic, hostname, next_uri, is_ip6,
buffer, buf_size);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to fetch image: %r\n", efi_status);
goto error;
}
@ -777,5 +802,5 @@ error:
if (hostname)
FreePool(hostname);
return status;
return efi_status;
}

View File

@ -19,18 +19,8 @@
**/
#ifndef __EFI_HTTP_PROTOCOL_H__
#define __EFI_HTTP_PROTOCOL_H__
#define EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \
{ \
0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \
}
#define EFI_HTTP_PROTOCOL_GUID \
{ \
0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } \
}
#ifndef SHIM_HTTP_H
#define SHIM_HTTP_H
typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL;
@ -514,4 +504,4 @@ struct _EFI_HTTP_PROTOCOL {
EFI_HTTP_POLL Poll;
};
#endif
#endif /* SHIM_HTTP_H */

View File

@ -15,16 +15,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
This Protocol is introduced in UEFI Specification 2.5
**/
#ifndef __EFI_IP4CONFIG2_PROTOCOL_H__
#define __EFI_IP4CONFIG2_PROTOCOL_H__
#ifndef SHIM_IP4CONFIG2_H
#define SHIM_IP4CONFIG2_H
#include <efiip.h>
#define EFI_IP4_CONFIG2_PROTOCOL_GUID \
{ \
0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \
}
typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL;
@ -312,4 +307,4 @@ struct _EFI_IP4_CONFIG2_PROTOCOL {
EFI_IP4_CONFIG2_UNREGISTER_NOTIFY UnregisterDataNotify;
};
#endif
#endif /* SHIM_IP4CONFIG2_H */

View File

@ -12,16 +12,11 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __EFI_IP6CONFIG_PROTOCOL_H__
#define __EFI_IP6CONFIG_PROTOCOL_H__
#ifndef SHIM_IP6CONFIG_H
#define SHIM_IP6CONFIG_H
#include <efiip.h>
#define EFI_IP6_CONFIG_PROTOCOL_GUID \
{ \
0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \
}
typedef struct _EFI_IP6_CONFIG_PROTOCOL EFI_IP6_CONFIG_PROTOCOL;
///
@ -363,4 +358,4 @@ struct _EFI_IP6_CONFIG_PROTOCOL {
EFI_IP6_CONFIG_UNREGISTER_NOTIFY UnregisterDataNotify;
};
#endif
#endif /* SHIM_IP6CONFIG_H */

View File

@ -1,5 +1,5 @@
#ifndef __PASSWORD_CRYPT_H__
#define __PASSWORD_CRYPT_H__
#ifndef SHIM_PASSWORDCRYPT_H
#define SHIM_PASSWORDCRYPT_H
enum HashMethod {
TRADITIONAL_DES = 0,
@ -24,4 +24,4 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length,
const PASSWORD_CRYPT *pw_hash, UINT8 *hash);
UINT16 get_hash_size (const UINT16 method);
#endif /* __PASSWORD_CRYPT_H__ */
#endif /* SHIM_PASSWORDCRYPT_H */

View File

@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __PE_IMAGE_H__
#define __PE_IMAGE_H__
#ifndef SHIM_PEIMAGE_H
#define SHIM_PEIMAGE_H
#include <wincert.h>
@ -786,4 +786,4 @@ typedef struct {
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr;
} PE_COFF_LOADER_IMAGE_CONTEXT;
#endif
#endif /* SHIM_PEIMAGE_H */

View File

@ -1,3 +1,6 @@
#ifndef SHIM_CONFIGTABLE_H
#define SHIM_CONFIGTABLE_H
/* definitions straight from TianoCore */
typedef UINT32 EFI_IMAGE_EXECUTION_ACTION;
@ -66,3 +69,4 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath);
int
configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath);
#endif /* SHIM_CONFIGTABLE_H */

View File

@ -1,8 +1,18 @@
#ifndef _SHIM_LIB_CONSOLE_H
#define _SHIM_LIB_CONSOLE_H 1
#ifndef SHIM_CONSOLE_H
#define SHIM_CONSOLE_H
#define Print(fmt, ...) \
({"Do not directly call Print() use console_print() instead" = 1;});
#define PrintAt(fmt, ...) \
({"Do not directly call PrintAt() use console_print_at() instead" = 1;});
EFI_STATUS
console_get_keystroke(EFI_INPUT_KEY *key);
UINTN
console_print(const CHAR16 *fmt, ...);
UINTN
console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...);
void
console_print_box_at(CHAR16 *str_arr[], int highlight,
int start_col, int start_row,
@ -26,9 +36,6 @@ void
console_reset(void);
#define NOSEL 0x7fffffff
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
{ 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} }
typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL;
typedef enum {
@ -42,7 +49,7 @@ EFI_STATUS
(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) (
IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
OUT BOOLEAN *GopUgaExists, OPTIONAL
OUT BOOLEAN *GopUgaExists, OPTIONAL
OUT BOOLEAN *StdInLocked OPTIONAL
);
@ -66,26 +73,14 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL {
EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
};
extern VOID setup_console (int text);
extern VOID console_fini(VOID);
extern VOID setup_verbosity(VOID);
extern UINT8 verbose;
#define dprint(fmt, ...) ({ \
UINTN __dprint_ret = 0; \
if (verbose) \
__dprint_ret = Print((fmt), ##__VA_ARGS__); \
__dprint_ret; \
})
#define dprinta(fmt, ...) ({ \
UINTN __dprinta_ret = 0; \
if (verbose) { \
UINTN __dprinta_i; \
CHAR16 *__dprinta_str = AllocateZeroPool((strlena(fmt) + 1) * 2); \
for (__dprinta_i = 0; fmt[__dprinta_i] != '\0'; __dprinta_i++) \
__dprinta_str[__dprinta_i] = fmt[__dprinta_i]; \
__dprinta_ret = Print((__dprinta_str), ##__VA_ARGS__); \
FreePool(__dprinta_str); \
} \
__dprinta_ret; \
extern UINT32 verbose;
#define dprint(fmt, ...) ({ \
UINTN __dprint_ret = 0; \
if (verbose) \
__dprint_ret = console_print((fmt), ##__VA_ARGS__); \
__dprint_ret; \
})
extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line);
@ -93,4 +88,8 @@ extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *fun
extern VOID msleep(unsigned long msecs);
#endif /* _SHIM_LIB_CONSOLE_H */
/* This is used in various things to determine if we should print to the
* console */
extern UINT8 in_protocol;
#endif /* SHIM_CONSOLE_H */

View File

@ -14,9 +14,10 @@
* See crypt_blowfish.c for more information.
*/
#ifndef _CRYPT_BLOWFISH_H
#define _CRYPT_BLOWFISH_H
#ifndef SHIM_CRYPT_BLOWFISH_H
#define SHIM_CRYPT_BLOWFISH_H
char *crypt_blowfish_rn(const char *key, const char *setting,
char *output, int size);
#endif
#endif /* SHIM_CRYPT_BLOWFISH_H */

View File

@ -1,222 +1,193 @@
#ifndef _INC_EFIAUTHENTICATED_H
#define _INC_EFIAUTHENTICATED_H
#ifndef SHIM_EFIAUTHENTICATED_H
#define SHIM_EFIAUTHENTICATED_H
#include <wincert.h>
//***********************************************************************
// Signature Database
//***********************************************************************
///
/// The format of a signature database.
///
/***********************************************************************
* Signature Database
***********************************************************************/
/*
* The format of a signature database.
*/
#pragma pack(1)
typedef struct {
///
/// An identifier which identifies the agent which added the signature to the list.
///
EFI_GUID SignatureOwner;
///
/// The format of the signature is defined by the SignatureType.
///
UINT8 SignatureData[1];
/*
* An identifier which identifies the agent which added the signature to
* the list.
*/
EFI_GUID SignatureOwner;
/*
* The format of the signature is defined by the SignatureType.
*/
UINT8 SignatureData[1];
} EFI_SIGNATURE_DATA;
typedef struct {
///
/// Type of the signature. GUID signature types are defined in below.
///
EFI_GUID SignatureType;
///
/// Total size of the signature list, including this header.
///
UINT32 SignatureListSize;
///
/// Size of the signature header which precedes the array of signatures.
///
UINT32 SignatureHeaderSize;
///
/// Size of each signature.
///
UINT32 SignatureSize;
///
/// Header before the array of signatures. The format of this header is specified
/// by the SignatureType.
/// UINT8 SignatureHeader[SignatureHeaderSize];
///
/// An array of signatures. Each signature is SignatureSize bytes in length.
/// EFI_SIGNATURE_DATA Signatures[][SignatureSize];
///
/*
* Type of the signature. GUID signature types are defined below.
*/
EFI_GUID SignatureType;
/*
* Total size of the signature list, including this header.
*/
UINT32 SignatureListSize;
/*
* Size of the signature header which precedes the array of signatures.
*/
UINT32 SignatureHeaderSize;
/*
* Size of each signature.
*/
UINT32 SignatureSize;
/*
* Header before the array of signatures. The format of this header is
* specified by the SignatureType.
*/
//UINT8 SignatureHeader[SignatureHeaderSize];
/*
* An array of signatures. Each signature is SignatureSize bytes in length.
*/
//EFI_SIGNATURE_DATA Signatures[][SignatureSize];
} EFI_SIGNATURE_LIST;
#pragma pack()
//
// _WIN_CERTIFICATE.wCertificateType
//
/*
* WIN_CERTIFICATE.wCertificateType
*/
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0
#define WIN_CERT_TYPE_EFI_GUID 0x0EF1
#define EFI_CERT_X509_GUID \
(EFI_GUID){ \
0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} \
}
#define EFI_CERT_RSA2048_GUID \
(EFI_GUID){ \
0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} \
}
#define EFI_CERT_TYPE_PKCS7_GUID \
(EFI_GUID){ \
0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \
}
///
/// WIN_CERTIFICATE_UEFI_GUID.CertType
///
#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \
{0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } }
///
/// WIN_CERTIFICATE_UEFI_GUID.CertData
///
/*
* WIN_CERTIFICATE_UEFI_GUID.CertData
*/
typedef struct {
EFI_GUID HashType;
UINT8 PublicKey[256];
UINT8 Signature[256];
EFI_GUID HashType;
UINT8 PublicKey[256];
UINT8 Signature[256];
} EFI_CERT_BLOCK_RSA_2048_SHA256;
///
/// Certificate which encapsulates a GUID-specific digital signature
///
/*
* Certificate which encapsulates a GUID-specific digital signature
*/
typedef struct {
///
/// This is the standard WIN_CERTIFICATE header, where
/// wCertificateType is set to WIN_CERT_TYPE_UEFI_GUID.
///
WIN_CERTIFICATE Hdr;
///
/// This is the unique id which determines the
/// format of the CertData. .
///
EFI_GUID CertType;
///
/// The following is the certificate data. The format of
/// the data is determined by the CertType.
/// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID,
/// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
///
UINT8 CertData[1];
/*
* This is the standard WIN_CERTIFICATE header, where wCertificateType is
* set to WIN_CERT_TYPE_UEFI_GUID.
*/
WIN_CERTIFICATE Hdr;
/*
* This is the unique id which determines the format of the CertData.
*/
EFI_GUID CertType;
/*
* The following is the certificate data. The format of the data is
* determined by the CertType. If CertType is
* EFI_CERT_TYPE_RSA2048_SHA256_GUID, the CertData will be
* EFI_CERT_BLOCK_RSA_2048_SHA256 structure.
*/
UINT8 CertData[1];
} WIN_CERTIFICATE_UEFI_GUID;
///
/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
///
/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from
/// WIN_CERTIFICATE and encapsulate the information needed to
/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as
/// specified in RFC2437.
///
typedef struct {
///
/// This is the standard WIN_CERTIFICATE header, where
/// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15.
///
WIN_CERTIFICATE Hdr;
///
/// This is the hashing algorithm which was performed on the
/// UEFI executable when creating the digital signature.
///
EFI_GUID HashAlgorithm;
///
/// The following is the actual digital signature. The
/// size of the signature is the same size as the key
/// (1024-bit key is 128 bytes) and can be determined by
/// subtracting the length of the other parts of this header
/// from the total length of the certificate as found in
/// Hdr.dwLength.
///
/// UINT8 Signature[];
///
/*
* Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature.
*
* The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from
* WIN_CERTIFICATE and encapsulate the information needed to implement the
* RSASSA-PKCS1-v1_5 digital signature algorithm as specified in RFC2437.
*/
typedef struct {
/*
* This is the standard WIN_CERTIFICATE header, where
* wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15.
*/
WIN_CERTIFICATE Hdr;
/*
* This is the hashing algorithm which was performed on the UEFI
* executable when creating the digital signature.
*/
EFI_GUID HashAlgorithm;
/*
* The following is the actual digital signature. The size of the
* signature is the same size as the key (1024-bit key is 128 bytes)
* and can be determined by subtracting the length of the other parts
* of this header from the total length of the certificate as found
* in Hdr.dwLength.
*/
//UINT8 Signature[];
} WIN_CERTIFICATE_EFI_PKCS1_15;
#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
///
/// Attributes of Authenticated Variable
///
/*
* Attributes of Authenticated Variable
*/
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
///
/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType
/// WIN_CERTIFICATE_UEFI_GUID and the CertType
/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies
/// authenticated access, then the Data buffer should begin with an
/// authentication descriptor prior to the data payload and DataSize
/// should reflect the the data.and descriptor size. The caller
/// shall digest the Monotonic Count value and the associated data
/// for the variable update using the SHA-256 1-way hash algorithm.
/// The ensuing the 32-byte digest will be signed using the private
/// key associated w/ the public/private 2048-bit RSA key-pair. The
/// WIN_CERTIFICATE shall be used to describe the signature of the
/// Variable data *Data. In addition, the signature will also
/// include the MonotonicCount value to guard against replay attacks.
///
/*
* AuthInfo is a WIN_CERTIFICATE using the wCertificateType
* WIN_CERTIFICATE_UEFI_GUID and the CertType
* EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies
* authenticated access, then the Data buffer should begin with an
* authentication descriptor prior to the data payload and DataSize should
* reflect the the data.and descriptor size. The caller shall digest the
* Monotonic Count value and the associated data for the variable update
* using the SHA-256 1-way hash algorithm. The ensuing the 32-byte digest
* will be signed using the private key associated w/ the public/private
* 2048-bit RSA key-pair. The WIN_CERTIFICATE shall be used to describe the
* signature of the Variable data *Data. In addition, the signature will also
* include the MonotonicCount value to guard against replay attacks.
*/
typedef struct {
///
/// Included in the signature of
/// AuthInfo.Used to ensure freshness/no
/// replay. Incremented during each
/// "Write" access.
///
UINT64 MonotonicCount;
///
/// Provides the authorization for the variable
/// access. It is a signature across the
/// variable data and the Monotonic Count
/// value. Caller uses Private key that is
/// associated with a public key that has been
/// provisioned via the key exchange.
///
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
/*
* Included in the signature of AuthInfo.Used to ensure freshness/no
* replay. Incremented during each "Write" access.
*/
UINT64 MonotonicCount;
/*
* Provides the authorization for the variable access. It is a
* signature across the variable data and the Monotonic Count value.
* Caller uses Private key that is associated with a public key that
* has been provisioned via the key exchange.
*/
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
} EFI_VARIABLE_AUTHENTICATION;
///
/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
/// set, then the Data buffer shall begin with an instance of a complete (and serialized)
/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new
/// variable value and DataSize shall reflect the combined size of the descriptor and the new
/// variable value. The authentication descriptor is not part of the variable data and is not
/// returned by subsequent calls to GetVariable().
///
/*
* When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is
* set, then the Data buffer shall begin with an instance of a complete (and
* serialized) EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall
* be followed by the new variable value and DataSize shall reflect the
* combined size of the descriptor and the new variable value. The
* authentication descriptor is not part of the variable data and is not
* returned by subsequent calls to GetVariable().
*/
typedef struct {
///
/// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and
/// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT.
///
EFI_TIME TimeStamp;
///
/// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted.
///
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
} EFI_VARIABLE_AUTHENTICATION_2;
/*
* For the TimeStamp value, components Pad1, Nanosecond, TimeZone,
* Daylight and Pad2 shall be set to 0. This means that the time
* shall always be expressed in GMT.
*/
EFI_TIME TimeStamp;
/*
* Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted.
*/
WIN_CERTIFICATE_UEFI_GUID AuthInfo;
} EFI_VARIABLE_AUTHENTICATION_2;
///
/// Size of AuthInfo prior to the data payload.
///
#define AUTHINFO_SIZE ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \
(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \
/*
* Size of AuthInfo prior to the data payload.
*/
#define AUTHINFO_SIZE ((offsetof(EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \
(offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData)) + \
sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
#define AUTHINFO2_SIZE(VarAuth2) ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
#define AUTHINFO2_SIZE(VarAuth2) ((offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
(UINTN) ((EFI_VARIABLE_AUTHENTICATION_2 *) (VarAuth2))->AuthInfo.Hdr.dwLength)
#define OFFSET_OF_AUTHINFO2_CERT_DATA ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)))
#define OFFSET_OF_AUTHINFO2_CERT_DATA ((offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \
(offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData)))
#endif
#endif /* SHIM_EFIAUTHENTICATED_H */

View File

@ -1,3 +1,6 @@
#ifndef SHIM_ERRORS_H
#define SHIM_ERRORS_H
#include <efierr.h>
#ifndef EFI_INCOMPATIBLE_VERSION
@ -7,3 +10,4 @@
#define EFI_SECURITY_VIOLATION EFIERR(26)
#endif
#endif /* SHIM_ERRORS_H */

View File

@ -1,5 +1,10 @@
#ifndef SHIM_LIB_EXECUTE_H
#define SHIM_LIB_EXECUTE_H
EFI_STATUS
generate_path(CHAR16* name, EFI_LOADED_IMAGE *li,
EFI_DEVICE_PATH **path, CHAR16 **PathName);
EFI_STATUS
execute(EFI_HANDLE image, CHAR16 *name);
#endif /* SHIM_LIB_EXECUTE_H */

View File

@ -1,14 +1,38 @@
#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;
extern EFI_GUID X509_GUID;
extern EFI_GUID RSA2048_GUID;
extern EFI_GUID PKCS7_GUID;
extern EFI_GUID IMAGE_PROTOCOL;
extern EFI_GUID SIMPLE_FS_PROTOCOL;
extern EFI_GUID EFI_FILE_INFO_GUID;
extern EFI_GUID EFI_FILE_SYSTEM_INFO_GUID;
extern EFI_GUID EFI_CERT_RSA2048_GUID;
extern EFI_GUID EFI_CERT_SHA1_GUID;
extern EFI_GUID EFI_CERT_SHA256_GUID;
extern EFI_GUID MOK_OWNER;
extern EFI_GUID EFI_CERT_SHA224_GUID;
extern EFI_GUID EFI_CERT_SHA384_GUID;
extern EFI_GUID EFI_CERT_SHA512_GUID;
extern EFI_GUID EFI_CERT_TYPE_PKCS7_GUID;
extern EFI_GUID EFI_CERT_TYPE_RSA2048_SHA256_GUID;
extern EFI_GUID EFI_CERT_TYPE_X509_GUID;
extern EFI_GUID EFI_CONSOLE_CONTROL_GUID;
extern EFI_GUID EFI_HTTP_BINDING_GUID;
extern EFI_GUID EFI_HTTP_PROTOCOL_GUID;
extern EFI_GUID EFI_IP4_CONFIG2_GUID;
extern EFI_GUID EFI_IP6_CONFIG_GUID;
extern EFI_GUID EFI_LOADED_IMAGE_GUID;
extern EFI_GUID EFI_TPM_GUID;
extern EFI_GUID EFI_TPM2_GUID;
extern EFI_GUID EFI_SECURE_BOOT_DB_GUID;
extern EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID;
extern EFI_GUID SECURITY_PROTOCOL_GUID;
extern EFI_GUID SECURITY2_PROTOCOL_GUID;
extern EFI_GUID SHIM_LOCK_GUID;
#endif /* SHIM_GUID_H */

View File

@ -80,7 +80,7 @@ hexdump(UINT8 *data, UINTN size)
{
UINTN display_offset = (UINTN)data & 0xffffffff;
UINTN offset = 0;
//Print(L"hexdump: data=0x%016x size=0x%x\n", data, size);
//console_print(L"hexdump: data=0x%016x size=0x%x\n", data, size);
while (offset < size) {
CHAR16 hexbuf[49];
@ -90,15 +90,15 @@ hexdump(UINT8 *data, UINTN size)
sz = format_hex(data+offset, size-offset, hexbuf);
if (sz == 0)
return;
uefi_call_wrapper(BS->Stall, 1, 200000);
msleep(200000);
format_text(data+offset, size-offset, txtbuf);
Print(L"%08x %s %s\n", display_offset, hexbuf, txtbuf);
uefi_call_wrapper(BS->Stall, 1, 200000);
console_print(L"%08x %s %s\n", display_offset, hexbuf, txtbuf);
msleep(200000);
display_offset += sz;
offset += sz;
}
}
#endif
#endif /* STATIC_HEXDUMP_H */

View File

@ -31,11 +31,11 @@
* Corporation.
*/
#ifndef _HTTPBOOT_H_
#define _HTTPBOOT_H_
#ifndef SHIM_HTTPBOOT_H
#define SHIM_HTTPBOOT_H
BOOLEAN find_httpboot (EFI_DEVICE_PATH *devpath);
extern BOOLEAN find_httpboot(EFI_HANDLE device);
extern EFI_STATUS httpboot_fetch_buffer(EFI_HANDLE image, VOID **buffer,
UINT64 *buf_size);
EFI_STATUS httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size);
#endif
#endif /* SHIM_HTTPBOOT_H */

View File

@ -1,9 +1,10 @@
#ifndef _NETBOOT_H_
#define _NETBOOT_H_
#ifndef SHIM_NETBOOT_H
#define SHIM_NETBOOT_H
extern BOOLEAN findNetboot(EFI_HANDLE image_handle);
extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle);
extern EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz);
#endif
#endif /* SHIM_NETBOOT_H */

View File

@ -27,7 +27,9 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SHIM_REPLACEMENTS_H
#define SHIM_REPLACEMENTS_H 1
#define SHIM_REPLACEMENTS_H
extern EFI_SYSTEM_TABLE *get_active_systab(void);
typedef enum {
VERIFIED_BY_NOTHING,

View File

@ -1,5 +1,5 @@
#ifndef _SHIM_LIB_SECURITY_POLICY_H
#define _SHIM_LIB_SECURITY_POLICY_H 1
#ifndef SHIM_SECURITY_POLICY_H
#define SHIM_SECURITY_POLICY_H
#if defined(OVERRIDE_SECURITY_POLICY)
typedef EFI_STATUS (*SecurityHook) (void *data, UINT32 len);
@ -12,4 +12,4 @@ void
security_protocol_set_hashes(unsigned char *esl, int len);
#endif /* OVERRIDE_SECURITY_POLICY */
#endif /* SHIM_LIB_SECURITY_POLICY_H */
#endif /* SHIM_SECURITY_POLICY_H */

View File

@ -1,2 +1,7 @@
#ifndef SHIM_SHELL_H
#define SHIM_SHELL_H
EFI_STATUS
argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV);
#endif /* SHIM_SHELL_H */

View File

@ -1,3 +1,6 @@
#ifndef SHIM_SIMPLE_FILE_H
#define SHIM_SIMPLE_FILE_H
EFI_STATUS
simple_file_open (EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode);
EFI_STATUS
@ -6,8 +9,6 @@ EFI_STATUS
simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer);
EFI_STATUS
simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer);
void
simple_file_close(EFI_FILE *file);
EFI_STATUS
simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **Entries,
int *count);
@ -19,3 +20,5 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
CHAR16 *filter, CHAR16 **result);
EFI_STATUS
simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h);
#endif /* SHIM_SIMPLE_FILE_H */

View File

@ -1,7 +1,7 @@
#include <efilib.h>
#ifndef SHIM_TPM_H
#define SHIM_TPM_H
#define EFI_TPM_GUID {0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }};
#define EFI_TPM2_GUID {0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }};
#include <efilib.h>
#define TPM_ALG_SHA 0x00000004
#define EV_IPL 0x0000000d
@ -186,3 +186,6 @@ typedef UINT32 TCG_EVENTTYPE;
#define EV_EFI_VARIABLE_AUTHORITY (EV_EFI_EVENT_BASE + 0xE0)
#define PE_COFF_IMAGE 0x0000000000000010
#endif /* SHIM_TPM_H */
// vim:fenc=utf-8:tw=75

View File

@ -36,6 +36,8 @@
#ifndef SHIM_UCS2_H
#define SHIM_UCS2_H
#include <stdbool.h>
static inline INTN
__attribute__((unused))
StrCaseCmp(CHAR16 *s0, CHAR16 *s1)
@ -89,6 +91,24 @@ StrCSpn(const CHAR16 *s, const CHAR16 *reject)
return ret;
}
/*
* Test if an entire buffer is nothing but NUL characters. This
* implementation "gracefully" ignores the difference between the
* UTF-8/ASCII 1-byte NUL and the UCS-2 2-byte NUL.
*/
static inline bool
__attribute__((__unused__))
is_all_nuls(UINT8 *data, UINTN data_size)
{
UINTN i;
for (i = 0; i < data_size; i++) {
if (data[i] != 0)
return false;
}
return true;
}
static inline UINTN
__attribute__((__unused__))
count_ucs2_strings(UINT8 *data, UINTN data_size)

View File

@ -1,5 +1,7 @@
#include <efiauthenticated.h>
#ifndef SHIM_VARIABLES_H
#define SHIM_VARIABLES_H
#include <efiauthenticated.h>
#include <PeImage.h> /* for SHA256_DIGEST_SIZE */
#define certlist_for_each_certentry(cl, cl_init, s, s_init) \
@ -57,3 +59,5 @@ variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
EFI_STATUS
variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
void **out, int *outlen);
#endif /* SHIM_VARIABLES_H */

View File

@ -1,8 +0,0 @@
#define VERSION "1.3.4"
static void
version(const char *progname)
{
printf("%s " VERSION "\n", progname);
}

View File

@ -1,5 +1,5 @@
#ifndef _INC_WINCERT_H
#define _INC_WINCERT_H
#ifndef SHIM_WINCERT_H
#define SHIM_WINCERT_H
///
/// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
@ -30,4 +30,4 @@ typedef struct {
} WIN_CERTIFICATE;
#endif
#endif /* SHIM_WINCERT_H */

View File

@ -8,8 +8,7 @@
#include <efi.h>
#include <efilib.h>
#include <guid.h>
#include <configtable.h>
#include "shim.h"
void *
configtable_get_table(EFI_GUID *guid)
@ -46,26 +45,26 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath)
int i;
for (i = 0; i < entries; i++) {
#ifdef DEBUG_CONFIG
Print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action);
console_print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action);
/* print what we have for debugging */
UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2;
Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
d += 16;
Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
d += 16;
Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
d += 16;
Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
d += 16;
Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
d += 16;
Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
#endif
CHAR16 *name = (CHAR16 *)(e->Data);
@ -77,33 +76,33 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath)
if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) {
skip = StrSize(name);
#ifdef DEBUG_CONFIG
Print(L"FOUND NAME %s (%d)\n", name, skip);
console_print(L"FOUND NAME %s (%d)\n", name, skip);
#endif
}
EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp;
if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0
|| ((unsigned)((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) {
/* Parse error, table corrupt, bail */
Print(L"Image Execution Information table corrupt\n");
console_print(L"Image Execution Information table corrupt\n");
break;
}
UINTN Size;
DevicePathInstance(&dpn, &Size);
#ifdef DEBUG_CONFIG
Print(L"Path: %s\n", DevicePathToStr(dp));
Print(L"Device Path Size %d\n", Size);
console_print(L"Path: %s\n", DevicePathToStr(dp));
console_print(L"Device Path Size %d\n", Size);
#endif
if (Size > e->InfoSize) {
/* parse error; the platform obviously has a
* corrupted image table; bail */
Print(L"Image Execution Information table corrupt\n");
console_print(L"Image Execution Information table corrupt\n");
break;
}
if (CompareMem(dp, (void *)DevicePath, Size) == 0) {
#ifdef DEBUG_CONFIG
Print(L"***FOUND\n");
console_print(L"***FOUND\n");
console_get_keystroke();
#endif
return e;
@ -112,7 +111,7 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath)
}
#ifdef DEBUG_CONFIG
Print(L"***NOT FOUND\n");
console_print(L"***NOT FOUND\n");
console_get_keystroke();
#endif
@ -135,7 +134,7 @@ configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath)
|| e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED)) {
/* this means the images signing key is in dbx */
#ifdef DEBUG_CONFIG
Print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n");
console_print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n");
#endif
return 1;
}

View File

@ -8,21 +8,10 @@
#include <efilib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <console.h>
#include <variables.h>
#include <errors.h>
#include <Library/BaseCryptLib.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
static EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
#include "shim.h"
static int min(int a, int b)
{
if (a < b)
return a;
return b;
}
static UINT8 console_text_mode = 0;
static int
count_lines(CHAR16 *str_arr[])
@ -47,17 +36,95 @@ SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c)
EFI_STATUS
console_get_keystroke(EFI_INPUT_KEY *key)
{
SIMPLE_INPUT_INTERFACE *ci = ST->ConIn;
UINTN EventIndex;
EFI_STATUS status;
EFI_STATUS efi_status;
do {
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex);
status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, key);
} while (status == EFI_NOT_READY);
gBS->WaitForEvent(1, &ci->WaitForKey, &EventIndex);
efi_status = ci->ReadKeyStroke(ci, key);
} while (efi_status == EFI_NOT_READY);
return status;
return efi_status;
}
static VOID setup_console (int text)
{
EFI_STATUS efi_status;
EFI_CONSOLE_CONTROL_PROTOCOL *concon;
static EFI_CONSOLE_CONTROL_SCREEN_MODE mode =
EfiConsoleControlScreenGraphics;
EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode;
efi_status = LibLocateProtocol(&EFI_CONSOLE_CONTROL_GUID,
(VOID **)&concon);
if (EFI_ERROR(efi_status))
return;
if (text) {
new_mode = EfiConsoleControlScreenText;
efi_status = concon->GetMode(concon, &mode, 0, 0);
/* If that didn't work, assume it's graphics */
if (EFI_ERROR(efi_status))
mode = EfiConsoleControlScreenGraphics;
if (text < 0) {
if (mode == EfiConsoleControlScreenGraphics)
console_text_mode = 0;
else
console_text_mode = 1;
return;
}
} else {
new_mode = mode;
}
concon->SetMode(concon, new_mode);
console_text_mode = text;
}
VOID console_fini(VOID)
{
if (console_text_mode)
setup_console(0);
}
UINTN
console_print(const CHAR16 *fmt, ...)
{
va_list args;
UINTN ret;
if (!console_text_mode)
setup_console(1);
va_start(args, fmt);
ret = VPrint(fmt, args);
va_end(args);
return ret;
}
UINTN
console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...)
{
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
va_list args;
UINTN ret;
if (!console_text_mode)
setup_console(1);
co->SetCursorPosition(co, col, row);
va_start(args, fmt);
ret = VPrint(fmt, args);
va_end(args);
return ret;
}
void
console_print_box_at(CHAR16 *str_arr[], int highlight,
int start_col, int start_row,
@ -72,7 +139,10 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
if (lines == 0)
return;
uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);
if (!console_text_mode)
setup_console(1);
co->QueryMode(co, co->Mode->Mode, &cols, &rows);
/* last row on screen is unusable without scrolling, so ignore it */
rows--;
@ -92,8 +162,8 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
start_row = 0;
if (start_col > (int)cols || start_row > (int)rows) {
Print(L"Starting Position (%d,%d) is off screen\n",
start_col, start_row);
console_print(L"Starting Position (%d,%d) is off screen\n",
start_col, start_row);
return;
}
if (size_cols + start_col > (int)cols)
@ -106,7 +176,7 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
Line = AllocatePool((size_cols+1)*sizeof(CHAR16));
if (!Line) {
Print(L"Failed Allocation\n");
console_print(L"Failed Allocation\n");
return;
}
@ -115,8 +185,8 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
Line[0] = BOXDRAW_DOWN_RIGHT;
Line[size_cols - 1] = BOXDRAW_DOWN_LEFT;
Line[size_cols] = L'\0';
uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, start_row);
uefi_call_wrapper(co->OutputString, 2, co, Line);
co->SetCursorPosition(co, start_col, start_row);
co->OutputString(co, Line);
int start;
if (offset == 0)
@ -147,19 +217,21 @@ console_print_box_at(CHAR16 *str_arr[], int highlight,
CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2);
}
if (line >= 0 && line == highlight)
uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK);
uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i);
uefi_call_wrapper(co->OutputString, 2, co, Line);
co->SetAttribute(co, EFI_LIGHTGRAY |
EFI_BACKGROUND_BLACK);
co->SetCursorPosition(co, start_col, i);
co->OutputString(co, Line);
if (line >= 0 && line == highlight)
uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
co->SetAttribute(co, EFI_LIGHTGRAY |
EFI_BACKGROUND_BLUE);
}
SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
Line[0] = BOXDRAW_UP_RIGHT;
Line[size_cols - 1] = BOXDRAW_UP_LEFT;
Line[size_cols] = L'\0';
uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i);
uefi_call_wrapper(co->OutputString, 2, co, Line);
co->SetCursorPosition(co, start_col, i);
co->OutputString(co, Line);
FreePool (Line);
@ -172,18 +244,22 @@ console_print_box(CHAR16 *str_arr[], int highlight)
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
EFI_INPUT_KEY key;
if (!console_text_mode)
setup_console(1);
CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode));
uefi_call_wrapper(co->EnableCursor, 2, co, FALSE);
uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
co->EnableCursor(co, FALSE);
co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0,
count_lines(str_arr));
console_get_keystroke(&key);
uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);
uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute);
co->EnableCursor(co, SavedConsoleMode.CursorVisible);
co->SetCursorPosition(co, SavedConsoleMode.CursorColumn,
SavedConsoleMode.CursorRow);
co->SetAttribute(co, SavedConsoleMode.Attribute);
}
int
@ -192,7 +268,7 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
EFI_INPUT_KEY k;
EFI_STATUS status;
EFI_STATUS efi_status;
int selector;
unsigned int selector_lines = count_lines(selectors);
int selector_max_cols = 0;
@ -201,7 +277,10 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
unsigned int selector_offset;
UINTN cols, rows;
uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);
if (!console_text_mode)
setup_console(1);
co->QueryMode(co, co->Mode->Mode, &cols, &rows);
for (i = 0; i < selector_lines; i++) {
int len = StrLen(selectors[i]);
@ -210,8 +289,6 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
selector_max_cols = len;
}
if (start < 0)
start = 0;
if (start >= selector_lines)
start = selector_lines - 1;
@ -238,8 +315,8 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
}
CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode));
uefi_call_wrapper(co->EnableCursor, 2, co, FALSE);
uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
co->EnableCursor(co, FALSE);
co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title));
@ -247,9 +324,10 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
size_cols, size_rows, 0, lines);
do {
status = console_get_keystroke(&k);
if (EFI_ERROR (status)) {
Print(L"Failed to read the keystroke: %r", status);
efi_status = console_get_keystroke(&k);
if (EFI_ERROR (efi_status)) {
console_print(L"Failed to read the keystroke: %r",
efi_status);
selector = -1;
break;
}
@ -277,9 +355,10 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
} while (!(k.ScanCode == SCAN_NULL
&& k.UnicodeChar == CHAR_CARRIAGE_RETURN));
uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);
uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute);
co->EnableCursor(co, SavedConsoleMode.CursorVisible);
co->SetCursorPosition(co, SavedConsoleMode.CursorColumn,
SavedConsoleMode.CursorRow);
co->SetAttribute(co, SavedConsoleMode.Attribute);
if (selector < 0)
/* ESC pressed */
@ -291,13 +370,15 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start)
int
console_yes_no(CHAR16 *str_arr[])
{
return console_select(str_arr, (CHAR16 *[]){ L"No", L"Yes", NULL }, 0);
CHAR16 *yes_no[] = { L"No", L"Yes", NULL };
return console_select(str_arr, yes_no, 0);
}
void
console_alertbox(CHAR16 **title)
{
console_select(title, (CHAR16 *[]){ L"OK", 0 }, 0);
CHAR16 *okay[] = { L"OK", NULL };
console_select(title, okay, 0);
}
void
@ -374,13 +455,13 @@ static struct {
static CHAR16 *
err_string (
IN EFI_STATUS Status
IN EFI_STATUS efi_status
)
{
UINTN Index;
for (Index = 0; error_table[Index].Desc; Index +=1) {
if (error_table[Index].Code == Status) {
if (error_table[Index].Code == efi_status) {
return error_table[Index].Desc;
}
}
@ -389,7 +470,7 @@ err_string (
}
void
console_error(CHAR16 *err, EFI_STATUS status)
console_error(CHAR16 *err, EFI_STATUS efi_status)
{
CHAR16 **err_arr = (CHAR16 *[]){
L"ERROR",
@ -399,8 +480,8 @@ console_error(CHAR16 *err, EFI_STATUS status)
};
CHAR16 str[512];
SPrint(str, sizeof(str), L"%s: (0x%x) %s", err, status, err_string(status));
SPrint(str, sizeof(str), L"%s: (0x%x) %s", err, efi_status,
err_string(efi_status));
err_arr[2] = str;
@ -412,80 +493,69 @@ console_reset(void)
{
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
uefi_call_wrapper(co->Reset, 2, co, TRUE);
if (!console_text_mode)
setup_console(1);
co->Reset(co, TRUE);
/* set mode 0 - required to be 80x25 */
uefi_call_wrapper(co->SetMode, 2, co, 0);
uefi_call_wrapper(co->ClearScreen, 1, co);
co->SetMode(co, 0);
co->ClearScreen(co);
}
UINT8 verbose;
UINT32 verbose = 0;
VOID
setup_verbosity(VOID)
{
EFI_STATUS status;
EFI_GUID guid = SHIM_LOCK_GUID;
UINT8 verbose_check;
EFI_STATUS efi_status;
UINT8 *verbose_check_ptr = NULL;
UINTN verbose_check_size;
verbose_check_size = 1;
status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check,
&verbose_check_size, guid);
verbose = 0;
if (!EFI_ERROR(status))
verbose = verbose_check;
}
VOID setup_console (int text)
{
EFI_STATUS status;
EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
EFI_CONSOLE_CONTROL_PROTOCOL *concon;
static EFI_CONSOLE_CONTROL_SCREEN_MODE mode =
EfiConsoleControlScreenGraphics;
EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode;
status = LibLocateProtocol(&console_control_guid, (VOID **)&concon);
if (status != EFI_SUCCESS)
return;
if (text) {
new_mode = EfiConsoleControlScreenText;
status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode,
0, 0);
/* If that didn't work, assume it's graphics */
if (status != EFI_SUCCESS)
mode = EfiConsoleControlScreenGraphics;
} else {
new_mode = mode;
verbose_check_size = sizeof(verbose);
efi_status = get_variable(L"SHIM_VERBOSE", &verbose_check_ptr,
&verbose_check_size, SHIM_LOCK_GUID);
if (!EFI_ERROR(efi_status)) {
verbose = *(__typeof__(verbose) *)verbose_check_ptr;
verbose &= (1ULL << (8 * verbose_check_size)) - 1ULL;
FreePool(verbose_check_ptr);
}
uefi_call_wrapper(concon->SetMode, 2, concon, new_mode);
setup_console(-1);
}
/* Included here because they mess up the definition of va_list and friends */
#include <Library/BaseCryptLib.h>
#include <openssl/err.h>
#include <openssl/crypto.h>
static int
print_errors_cb(const char *str, size_t len, void *u)
{
Print(L"%a", str);
console_print(L"%a", str);
return len;
}
EFI_STATUS
print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line)
print_crypto_errors(EFI_STATUS efi_status,
char *file, const char *func, int line)
{
if (!(verbose && EFI_ERROR(rc)))
return rc;
if (!(verbose && EFI_ERROR(efi_status)))
return efi_status;
Print(L"SSL Error: %a:%d %a(): %r\n", file, line, func, rc);
console_print(L"SSL Error: %a:%d %a(): %r\n", file, line, func,
efi_status);
ERR_print_errors_cb(print_errors_cb, NULL);
return rc;
return efi_status;
}
VOID
msleep(unsigned long msecs)
{
uefi_call_wrapper(BS->Stall, 1, msecs);
gBS->Stall(msecs);
}
/* This is used in various things to determine if we should print to the
* console */
UINT8 in_protocol = 0;

View File

@ -41,8 +41,7 @@
#include <efi.h>
#include <efilib.h>
#include <guid.h>
#include <execute.h>
#include "shim.h"
EFI_STATUS
generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName)
@ -74,7 +73,7 @@ generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16
*PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16));
if (!*PathName) {
Print(L"Failed to allocate path buffer\n");
console_print(L"Failed to allocate path buffer\n");
efi_status = EFI_OUT_OF_RESOURCES;
goto error;
}
@ -96,32 +95,30 @@ error:
EFI_STATUS
execute(EFI_HANDLE image, CHAR16 *name)
{
EFI_STATUS status;
EFI_STATUS efi_status;
EFI_HANDLE h;
EFI_LOADED_IMAGE *li;
EFI_DEVICE_PATH *devpath;
CHAR16 *PathName;
status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
&IMAGE_PROTOCOL, (void **)&li);
if (status != EFI_SUCCESS)
return status;
efi_status = gBS->HandleProtocol(image, &IMAGE_PROTOCOL,
(void **) &li);
if (EFI_ERROR(efi_status))
return efi_status;
status = generate_path(name, li, &devpath, &PathName);
if (status != EFI_SUCCESS)
return status;
efi_status = generate_path(name, li, &devpath, &PathName);
if (EFI_ERROR(efi_status))
return efi_status;
status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image,
devpath, NULL, 0, &h);
if (status != EFI_SUCCESS)
efi_status = gBS->LoadImage(FALSE, image, devpath, NULL, 0, &h);
if (EFI_ERROR(efi_status))
goto out;
status = uefi_call_wrapper(BS->StartImage, 3, h, NULL, NULL);
uefi_call_wrapper(BS->UnloadImage, 1, h);
efi_status = gBS->StartImage(h, NULL, NULL);
gBS->UnloadImage(h);
out:
FreePool(PathName);
FreePool(devpath);
return status;
return efi_status;
}

View File

@ -4,19 +4,36 @@
* see COPYING file
*/
#include <guid.h>
#include "shim.h"
/* all the necessary guids */
EFI_GUID BDS_GUID = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } };
EFI_GUID GV_GUID = EFI_GLOBAL_VARIABLE;
EFI_GUID SIG_DB = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }};
EFI_GUID X509_GUID = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} };
EFI_GUID RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} };
EFI_GUID PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} };
EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL;
EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL;
EFI_GUID EFI_FILE_INFO_GUID = EFI_FILE_INFO_ID;
EFI_GUID EFI_FILE_SYSTEM_INFO_GUID = EFI_FILE_SYSTEM_INFO_ID;
EFI_GUID EFI_CERT_RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} };
EFI_GUID EFI_CERT_SHA1_GUID = { 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd }};
EFI_GUID EFI_CERT_SHA256_GUID = { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } };
EFI_GUID MOK_OWNER = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
EFI_GUID EFI_CERT_SHA224_GUID = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} };
EFI_GUID EFI_CERT_SHA384_GUID = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} };
EFI_GUID EFI_CERT_SHA512_GUID = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} };
EFI_GUID EFI_CERT_TYPE_PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} };
EFI_GUID EFI_CERT_TYPE_RSA2048_SHA256_GUID = { 0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } };
EFI_GUID EFI_CERT_TYPE_X509_GUID = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} };
EFI_GUID EFI_CONSOLE_CONTROL_GUID = { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} };
EFI_GUID EFI_HTTP_BINDING_GUID = { 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } };
EFI_GUID EFI_HTTP_PROTOCOL_GUID = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } };
EFI_GUID EFI_IP4_CONFIG2_GUID = { 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } };
EFI_GUID EFI_IP6_CONFIG_GUID = { 0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } };
EFI_GUID EFI_LOADED_IMAGE_GUID = EFI_LOADED_IMAGE_PROTOCOL_GUID;
EFI_GUID EFI_TPM_GUID = { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd } };
EFI_GUID EFI_TPM2_GUID = { 0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f } };
EFI_GUID EFI_SECURE_BOOT_DB_GUID = { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f } };
EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID = SIMPLE_FILE_SYSTEM_PROTOCOL;
EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } };
EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
EFI_GUID SHIM_LOCK_GUID = {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } };

View File

@ -9,7 +9,8 @@
#include <efi.h>
#include <efilib.h>
#include <guid.h>
#include "shim.h"
#include <variables.h>
#include <simple_file.h>
#include <errors.h>
@ -80,16 +81,14 @@ security2_policy_authentication (
BOOLEAN BootPolicy
)
{
EFI_STATUS status, auth;
EFI_STATUS efi_status, auth;
/* Chain original security policy */
status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer,
FileSize, BootPolicy);
efi_status = es2fa(This, DevicePath, FileBuffer, FileSize, BootPolicy);
/* if OK, don't bother with MOK check */
if (status == EFI_SUCCESS)
return status;
if (!EFI_ERROR(efi_status))
return efi_status;
if (extra_check)
auth = extra_check(FileBuffer, FileSize);
@ -100,7 +99,7 @@ security2_policy_authentication (
/* return previous status, which is the correct one
* for the platform: may be either EFI_ACCESS_DENIED
* or EFI_SECURITY_VIOLATION */
return status;
return efi_status;
return auth;
}
@ -112,7 +111,7 @@ security_policy_authentication (
const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst
)
{
EFI_STATUS status, fail_status;
EFI_STATUS efi_status, fail_status;
EFI_DEVICE_PATH *DevPath
= DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst),
*OrigDevPath = DevPath;
@ -121,50 +120,49 @@ security_policy_authentication (
VOID *FileBuffer;
UINTN FileSize;
CHAR16* DevPathStr;
EFI_GUID SIMPLE_FS_PROTOCOL = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
/* Chain original security policy */
status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus,
DevicePathConst);
efi_status = esfas(This, AuthenticationStatus, DevicePathConst);
/* if OK avoid checking MOK: It's a bit expensive to
* read the whole file in again (esfas already did this) */
if (status == EFI_SUCCESS)
if (!EFI_ERROR(efi_status))
goto out;
/* capture failure status: may be either EFI_ACCESS_DENIED or
* EFI_SECURITY_VIOLATION */
fail_status = status;
fail_status = efi_status;
status = uefi_call_wrapper(BS->LocateDevicePath, 3,
&SIMPLE_FS_PROTOCOL, &DevPath, &h);
if (status != EFI_SUCCESS)
efi_status = gBS->LocateDevicePath(&SIMPLE_FS_PROTOCOL, &DevPath, &h);
if (EFI_ERROR(efi_status))
goto out;
DevPathStr = DevicePathToStr(DevPath);
status = simple_file_open_by_handle(h, DevPathStr, &f,
EFI_FILE_MODE_READ);
efi_status = simple_file_open_by_handle(h, DevPathStr, &f,
EFI_FILE_MODE_READ);
FreePool(DevPathStr);
if (status != EFI_SUCCESS)
if (EFI_ERROR(efi_status))
goto out;
status = simple_file_read_all(f, &FileSize, &FileBuffer);
simple_file_close(f);
if (status != EFI_SUCCESS)
efi_status = simple_file_read_all(f, &FileSize, &FileBuffer);
f->Close(f);
if (EFI_ERROR(efi_status))
goto out;
if (extra_check)
status = extra_check(FileBuffer, FileSize);
efi_status = extra_check(FileBuffer, FileSize);
else
status = EFI_SECURITY_VIOLATION;
efi_status = EFI_SECURITY_VIOLATION;
FreePool(FileBuffer);
if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION)
if (efi_status == EFI_ACCESS_DENIED ||
efi_status == EFI_SECURITY_VIOLATION)
/* return what the platform originally said */
status = fail_status;
efi_status = fail_status;
out:
FreePool(OrigDevPath);
return status;
return efi_status;
}
@ -265,7 +263,7 @@ security_policy_install(SecurityHook hook)
{
EFI_SECURITY_PROTOCOL *security_protocol;
EFI_SECURITY2_PROTOCOL *security2_protocol = NULL;
EFI_STATUS status;
EFI_STATUS efi_status;
if (esfas)
/* Already Installed */
@ -274,20 +272,18 @@ security_policy_install(SecurityHook hook)
/* Don't bother with status here. The call is allowed
* to fail, since SECURITY2 was introduced in PI 1.2.1
* If it fails, use security2_protocol == NULL as indicator */
uefi_call_wrapper(BS->LocateProtocol, 3,
&SECURITY2_PROTOCOL_GUID, NULL,
LibLocateProtocol(&SECURITY2_PROTOCOL_GUID,
(VOID **) &security2_protocol);
status = uefi_call_wrapper(BS->LocateProtocol, 3,
&SECURITY_PROTOCOL_GUID, NULL,
(VOID **) &security_protocol);
if (status != EFI_SUCCESS)
efi_status = LibLocateProtocol(&SECURITY_PROTOCOL_GUID,
(VOID **) &security_protocol);
if (EFI_ERROR(efi_status))
/* This one is mandatory, so there's a serious problem */
return status;
return efi_status;
if (security2_protocol) {
es2fa = security2_protocol->FileAuthentication;
security2_protocol->FileAuthentication =
security2_protocol->FileAuthentication =
(EFI_SECURITY2_FILE_AUTHENTICATION) thunk_security2_policy_authentication;
}
@ -304,17 +300,15 @@ security_policy_install(SecurityHook hook)
EFI_STATUS
security_policy_uninstall(void)
{
EFI_STATUS status;
EFI_STATUS efi_status;
if (esfas) {
EFI_SECURITY_PROTOCOL *security_protocol;
status = uefi_call_wrapper(BS->LocateProtocol, 3,
&SECURITY_PROTOCOL_GUID, NULL,
(VOID **) &security_protocol);
if (status != EFI_SUCCESS)
return status;
efi_status = LibLocateProtocol(&SECURITY_PROTOCOL_GUID,
(VOID **) &security_protocol);
if (EFI_ERROR(efi_status))
return efi_status;
security_protocol->FileAuthenticationState = esfas;
esfas = NULL;
@ -326,12 +320,10 @@ security_policy_uninstall(void)
if (es2fa) {
EFI_SECURITY2_PROTOCOL *security2_protocol;
status = uefi_call_wrapper(BS->LocateProtocol, 3,
&SECURITY2_PROTOCOL_GUID, NULL,
(VOID **) &security2_protocol);
if (status != EFI_SUCCESS)
return status;
efi_status = LibLocateProtocol(&SECURITY2_PROTOCOL_GUID,
(VOID **) &security2_protocol);
if (EFI_ERROR(efi_status))
return efi_status;
security2_protocol->FileAuthentication = es2fa;
es2fa = NULL;

View File

@ -8,22 +8,23 @@
#include <efi.h>
#include <efilib.h>
#include <shell.h>
#include "shim.h"
EFI_STATUS
argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV)
{
unsigned int i, count = 1;
EFI_STATUS status;
EFI_STATUS efi_status;
EFI_LOADED_IMAGE *info;
CHAR16 *start;
*argc = 0;
status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info);
if (EFI_ERROR(status)) {
Print(L"Failed to get arguments\n");
return status;
efi_status = gBS->HandleProtocol(image, &LoadedImageProtocol,
(VOID **) &info);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to get arguments\n");
return efi_status;
}
for (i = 0; i < info->LoadOptionsSize; i += 2) {
@ -33,7 +34,8 @@ argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV)
}
}
(*argc)++; /* we counted spaces, so add one for initial */
/* we counted spaces, so add one for initial */
(*argc)++;
*ARGV = AllocatePool(*argc * sizeof(**ARGV));
if (!*ARGV) {

View File

@ -7,15 +7,7 @@
#include <efi.h>
#include <efilib.h>
#include <console.h>
#include <simple_file.h>
#include <efiauthenticated.h>
#include <execute.h> /* for generate_path() */
static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL;
static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL;
static EFI_GUID FILE_INFO = EFI_FILE_INFO_ID;
static EFI_GUID FS_INFO = EFI_FILE_SYSTEM_INFO_ID;
#include "shim.h"
EFI_STATUS
simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode)
@ -24,23 +16,21 @@ simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UIN
EFI_FILE_IO_INTERFACE *drive;
EFI_FILE *root;
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
&SIMPLE_FS_PROTOCOL, (void **)&drive);
if (efi_status != EFI_SUCCESS) {
Print(L"Unable to find simple file protocol (%d)\n", efi_status);
efi_status = gBS->HandleProtocol(device, &EFI_SIMPLE_FILE_SYSTEM_GUID,
(void **)&drive);
if (EFI_ERROR(efi_status)) {
console_print(L"Unable to find simple file protocol (%d)\n",
efi_status);
goto error;
}
efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to open drive volume (%d)\n", efi_status);
efi_status = drive->OpenVolume(drive, &root);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to open drive volume (%d)\n", efi_status);
goto error;
}
efi_status = uefi_call_wrapper(root->Open, 5, root, file, name,
mode, 0);
efi_status = root->Open(root, file, name, mode, 0);
error:
return efi_status;
@ -55,16 +45,14 @@ simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode)
EFI_DEVICE_PATH *loadpath = NULL;
CHAR16 *PathName = NULL;
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
&IMAGE_PROTOCOL, (void **)&li);
if (efi_status != EFI_SUCCESS)
efi_status = gBS->HandleProtocol(image, &IMAGE_PROTOCOL,
(void **) &li);
if (EFI_ERROR(efi_status))
return simple_file_open_by_handle(image, name, file, mode);
efi_status = generate_path(name, li, &loadpath, &PathName);
if (efi_status != EFI_SUCCESS) {
Print(L"Unable to generate load path for %s\n", name);
if (EFI_ERROR(efi_status)) {
console_print(L"Unable to generate load path for %s\n", name);
return efi_status;
}
@ -82,33 +70,32 @@ EFI_STATUS
simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EFI_FILE_INFO **entries,
int *count)
{
EFI_STATUS status;
EFI_STATUS efi_status;
char buf[4096];
UINTN size = sizeof(buf);
EFI_FILE_INFO *fi = (void *)buf;
status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO,
&size, fi);
if (status != EFI_SUCCESS) {
Print(L"Failed to get file info\n");
efi_status = file->GetInfo(file, &EFI_FILE_INFO_GUID, &size, fi);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to get file info\n");
goto out;
}
if ((fi->Attribute & EFI_FILE_DIRECTORY) == 0) {
Print(L"Not a directory %s\n", name);
status = EFI_INVALID_PARAMETER;
console_print(L"Not a directory %s\n", name);
efi_status = EFI_INVALID_PARAMETER;
goto out;
}
size = 0;
*count = 0;
for (;;) {
UINTN len = sizeof(buf);
status = uefi_call_wrapper(file->Read, 3, file, &len, buf);
if (status != EFI_SUCCESS || len == 0)
efi_status = file->Read(file, &len, buf);
if (EFI_ERROR(efi_status) || len == 0)
break;
(*count)++;
size += len;
}
uefi_call_wrapper(file->SetPosition, 2, file, 0);
file->SetPosition(file, 0);
char *ptr = AllocatePool(size);
*entries = (EFI_FILE_INFO *)ptr;
@ -117,18 +104,18 @@ simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EF
int i;
for (i = 0; i < *count; i++) {
UINTN len = size;
uefi_call_wrapper(file->Read, 3, file, &len, ptr);
file->Read(file, &len, ptr);
ptr += len;
size -= len;
}
status = EFI_SUCCESS;
efi_status = EFI_SUCCESS;
out:
simple_file_close(file);
if (status != EFI_SUCCESS && *entries) {
file->Close(file);
if (EFI_ERROR(efi_status) && *entries) {
FreePool(*entries);
*entries = NULL;
}
return status;
return efi_status;
}
EFI_STATUS
@ -136,12 +123,12 @@ simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **entries,
int *count)
{
EFI_FILE *file;
EFI_STATUS status;
EFI_STATUS efi_status;
status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ);
if (status != EFI_SUCCESS) {
Print(L"failed to open file %s: %d\n", name, status);
return status;
efi_status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ);
if (EFI_ERROR(efi_status)) {
console_print(L"failed to open file %s: %d\n", name, efi_status);
return efi_status;
}
return simple_dir_read_all_by_handle(image, file, name, entries, count);
@ -156,12 +143,10 @@ simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer)
*size = sizeof(buf);
fi = (void *)buf;
efi_status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO,
size, fi);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to get file info\n");
efi_status = file->GetInfo(file, &EFI_FILE_INFO_GUID, size, fi);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to get file info\n");
return efi_status;
}
@ -169,11 +154,11 @@ simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer)
*buffer = AllocatePool(*size);
if (!*buffer) {
Print(L"Failed to allocate buffer of size %d\n", *size);
console_print(L"Failed to allocate buffer of size %d\n", *size);
return EFI_OUT_OF_RESOURCES;
}
efi_status = uefi_call_wrapper(file->Read, 3, file, size, *buffer);
efi_status = file->Read(file, size, *buffer);
return efi_status;
}
@ -183,29 +168,24 @@ simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer)
{
EFI_STATUS efi_status;
efi_status = uefi_call_wrapper(file->Write, 3, file, &size, buffer);
efi_status = file->Write(file, &size, buffer);
return efi_status;
}
void
simple_file_close(EFI_FILE *file)
{
uefi_call_wrapper(file->Close, 1, file);
}
EFI_STATUS
simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h)
{
UINTN count, i;
EFI_HANDLE *vol_handles = NULL;
EFI_STATUS status;
EFI_STATUS efi_status;
CHAR16 **entries;
int val;
uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol,
&SIMPLE_FS_PROTOCOL, NULL, &count, &vol_handles);
efi_status = gBS->LocateHandleBuffer(ByProtocol,
&EFI_SIMPLE_FILE_SYSTEM_GUID,
NULL, &count, &vol_handles);
if (EFI_ERROR(efi_status))
return efi_status;
if (!count || !vol_handles)
return EFI_NOT_FOUND;
@ -221,25 +201,23 @@ simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h)
CHAR16 *name;
EFI_FILE_IO_INTERFACE *drive;
status = uefi_call_wrapper(BS->HandleProtocol, 3,
vol_handles[i],
&SIMPLE_FS_PROTOCOL,
(void **)&drive);
if (status != EFI_SUCCESS || !drive)
efi_status = gBS->HandleProtocol(vol_handles[i],
&EFI_SIMPLE_FILE_SYSTEM_GUID,
(void **) &drive);
if (EFI_ERROR(efi_status) || !drive)
continue;
status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
if (status != EFI_SUCCESS)
efi_status = drive->OpenVolume(drive, &root);
if (EFI_ERROR(efi_status))
continue;
status = uefi_call_wrapper(root->GetInfo, 4, root, &FS_INFO,
efi_status = root->GetInfo(root, &EFI_FILE_SYSTEM_INFO_GUID,
&size, fi);
if (status != EFI_SUCCESS)
if (EFI_ERROR(efi_status))
continue;
name = fi->VolumeLabel;
if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0)
if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0)
name = DevicePathToStr(DevicePathFromHandle(vol_handles[i]));
entries[i] = AllocatePool((StrLen(name) + 2) * sizeof(CHAR16));
@ -269,7 +247,6 @@ simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h)
FreePool(entries);
FreePool(vol_handles);
return EFI_SUCCESS;
}
@ -277,7 +254,7 @@ EFI_STATUS
simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
CHAR16 ***result, int *count, EFI_FILE_INFO **entries)
{
EFI_STATUS status;
EFI_STATUS efi_status;
int tot, offs = StrLen(filter), i, c, filtercount = 1;
EFI_FILE_INFO *next;
void *ptr;
@ -308,9 +285,8 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
*count = 0;
status = simple_dir_read_all(image, name, entries, &tot);
if (status != EFI_SUCCESS)
efi_status = simple_dir_read_all(image, name, entries, &tot);
if (EFI_ERROR(efi_status))
goto out;
ptr = next = *entries;
@ -326,7 +302,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
break;
}
}
ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
ptr += offsetof(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
next = ptr;
}
if (*count)
@ -347,7 +323,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
if (next->Attribute & EFI_FILE_DIRECTORY) {
(*result)[(*count)] = PoolPrint(L"%s/", next->FileName);
if (!(*result)[(*count)]) {
Print(L"Failed to allocate buffer");
console_print(L"Failed to allocate buffer");
return EFI_OUT_OF_RESOURCES;
}
(*count)++;
@ -360,7 +336,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) {
(*result)[(*count)] = StrDuplicate(next->FileName);
if (!(*result)[(*count)]) {
Print(L"Failed to allocate buffer");
console_print(L"Failed to allocate buffer");
return EFI_OUT_OF_RESOURCES;
}
(*count)++;
@ -370,7 +346,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
break;
}
next:
next:
if (StrCmp(next->FileName, L"..") == 0) {
/* place .. directory first */
CHAR16 *tmp = (*result)[(*count) - 1];
@ -379,7 +355,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
(*result)[0] = tmp;
}
ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
ptr += offsetof(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
next = ptr;
}
if (*count == 0) {
@ -387,10 +363,10 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
(*result)[(*count)++] = L"./";
}
(*result)[*count] = NULL;
status = EFI_SUCCESS;
efi_status = EFI_SUCCESS;
out:
if (status != EFI_SUCCESS) {
if (EFI_ERROR(efi_status)) {
if (*entries)
FreePool(*entries);
*entries = NULL;
@ -398,7 +374,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
FreePool(*result);
*result = NULL;
}
return status;
return efi_status;
}
static void
@ -411,12 +387,12 @@ free_entries(CHAR16 **entries, int count)
}
void
simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
CHAR16 *filter, CHAR16 **result)
simple_file_selector(EFI_HANDLE * im, CHAR16 ** title, CHAR16 * name,
CHAR16 * filter, CHAR16 ** result)
{
EFI_STATUS status;
EFI_STATUS efi_status;
CHAR16 **entries = NULL;
EFI_FILE_INFO *dmp;
EFI_FILE_INFO *dmp = NULL;
int count, select, len;
CHAR16 *newname, *selected;
@ -436,18 +412,18 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
*im = h;
}
newname = AllocatePool((StrLen(name) + 1)*sizeof(CHAR16));
newname = AllocatePool((StrLen(name) + 1) * sizeof(CHAR16));
if (!newname)
return;
StrCpy(newname, name);
name = newname;
redo:
status = simple_dir_filter(*im, name, filter, &entries, &count, &dmp);
if (status != EFI_SUCCESS)
goto out_free_name;
redo:
efi_status = simple_dir_filter(*im, name, filter, &entries, &count,
&dmp);
if (EFI_ERROR(efi_status))
goto out_free;
select = console_select(title, entries, 0);
if (select < 0)
@ -469,9 +445,6 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
} else if (StrCmp(selected, L"../") == 0) {
int i;
i = StrLen(name) - 1;
for (i = StrLen(name); i > 0; --i) {
if (name[i] == '\\')
break;
@ -489,11 +462,12 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
goto redo;
}
}
newname = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16));
newname =
AllocatePool((StrLen(name) + len + 2) * sizeof(CHAR16));
if (!newname)
goto out_free;
StrCpy(newname, name);
if (name[StrLen(name) - 1] != '\\')
StrCat(newname, L"\\");
StrCat(newname, selected);
@ -509,7 +483,7 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
goto redo;
}
*result = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16));
*result = AllocatePool((StrLen(name) + len + 2) * sizeof(CHAR16));
if (*result) {
StrCpy(*result, name);
if (name[StrLen(name) - 1] != '\\')
@ -517,12 +491,12 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
StrCat(*result, selected);
}
out_free:
FreePool(dmp);
out_free:
if (dmp)
FreePool(dmp);
if (entries) {
free_entries(entries, count);
FreePool(entries);
}
out_free_name:
FreePool(name);
}

View File

@ -11,23 +11,18 @@
* Copyright (c) 2011 - 2012, 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
* 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.
*
*
*/
#include <efi.h>
#include <efilib.h>
#include <efiauthenticated.h>
#include <variables.h>
#include <guid.h>
#include <console.h>
#include <errors.h>
#include "shim.h"
EFI_STATUS
variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
@ -56,76 +51,75 @@ variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
return EFI_SUCCESS;
}
EFI_STATUS
CreateTimeBasedPayload (
IN OUT UINTN *DataSize,
IN OUT UINT8 **Data
)
CreateTimeBasedPayload(IN OUT UINTN * DataSize, IN OUT UINT8 ** Data)
{
EFI_STATUS Status;
UINT8 *NewData;
UINT8 *Payload;
UINTN PayloadSize;
EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
UINTN DescriptorSize;
EFI_TIME Time;
EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID;
if (Data == NULL || DataSize == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// In Setup mode or Custom mode, the variable does not need to be signed but the
// parameters to the SetVariable() call still need to be prepared as authenticated
// variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
// data in it.
//
Payload = *Data;
PayloadSize = *DataSize;
DescriptorSize = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
if (NewData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
EFI_STATUS efi_status;
UINT8 *NewData;
UINT8 *Payload;
UINTN PayloadSize;
EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData;
UINTN DescriptorSize;
EFI_TIME Time;
if ((Payload != NULL) && (PayloadSize != 0)) {
CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
}
if (Data == NULL || DataSize == NULL) {
return EFI_INVALID_PARAMETER;
}
/*
* In Setup mode or Custom mode, the variable does not need to be
* signed but the
* parameters to the SetVariable() call still need to be prepared as
* authenticated variable. So we create EFI_VARIABLE_AUTHENTICATED_2
* descriptor without certificate data in it.
*/
Payload = *Data;
PayloadSize = *DataSize;
DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
DescriptorSize = offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)
+ offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData);
NewData = (UINT8 *) AllocateZeroPool(DescriptorSize + PayloadSize);
if (NewData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (&Time, sizeof (EFI_TIME));
Status = uefi_call_wrapper(RT->GetTime,2, &Time, NULL);
if (EFI_ERROR (Status)) {
FreePool(NewData);
return Status;
}
Time.Pad1 = 0;
Time.Nanosecond = 0;
Time.TimeZone = 0;
Time.Daylight = 0;
Time.Pad2 = 0;
CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
DescriptorData->AuthInfo.CertType = efi_cert_type;
/* we're expecting an EFI signature list, so don't free the input since
* it might not be in a pool */
if ((Payload != NULL) && (PayloadSize != 0)) {
CopyMem(NewData + DescriptorSize, Payload, PayloadSize);
}
DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
ZeroMem(&Time, sizeof(EFI_TIME));
efi_status = gRT->GetTime(&Time, NULL);
if (EFI_ERROR(efi_status)) {
FreePool(NewData);
return efi_status;
}
Time.Pad1 = 0;
Time.Nanosecond = 0;
Time.TimeZone = 0;
Time.Daylight = 0;
Time.Pad2 = 0;
CopyMem(&DescriptorData->TimeStamp, &Time, sizeof(EFI_TIME));
DescriptorData->AuthInfo.Hdr.dwLength =
offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData);
DescriptorData->AuthInfo.Hdr.wRevision = 0x0200;
DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
DescriptorData->AuthInfo.CertType = EFI_CERT_TYPE_PKCS7_GUID;
/*
* we're expecting an EFI signature list, so don't free the input
* since it might not be in a pool
*/
#if 0
if (Payload != NULL) {
FreePool(Payload);
}
if (Payload != NULL) {
FreePool(Payload);
}
#endif
*DataSize = DescriptorSize + PayloadSize;
*Data = NewData;
return EFI_SUCCESS;
*DataSize = DescriptorSize + PayloadSize;
*Data = NewData;
return EFI_SUCCESS;
}
EFI_STATUS
@ -146,8 +140,9 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner,
int ds;
efi_status = variable_create_esl(Data, len, &X509_GUID, NULL,
(void **)&Cert, &ds);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to create %s certificate %d\n", var, efi_status);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to create %s certificate %d\n",
var, efi_status);
return efi_status;
}
@ -158,19 +153,18 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner,
DataSize = len;
}
efi_status = CreateTimeBasedPayload(&DataSize, (UINT8 **)&Cert);
if (efi_status != EFI_SUCCESS) {
Print(L"Failed to create time based payload %d\n", efi_status);
if (EFI_ERROR(efi_status)) {
console_print(L"Failed to create time based payload %d\n",
efi_status);
return efi_status;
}
efi_status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner,
EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
| options,
DataSize, Cert);
efi_status = gRT->SetVariable(var, &owner,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS |
options, DataSize, Cert);
return efi_status;
}
@ -181,8 +175,9 @@ GetOSIndications(void)
UINTN DataSize = sizeof(indications);
EFI_STATUS efi_status;
efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"OsIndicationsSupported", &GV_GUID, NULL, &DataSize, &indications);
if (efi_status != EFI_SUCCESS)
efi_status = gRT->GetVariable(L"OsIndicationsSupported", &GV_GUID,
NULL, &DataSize, &indications);
if (EFI_ERROR(efi_status))
return 0;
return indications;
@ -194,17 +189,15 @@ SETOSIndicationsAndReboot(UINT64 indications)
UINTN DataSize = sizeof(indications);
EFI_STATUS efi_status;
efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"OsIndications",
&GV_GUID,
EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS,
DataSize, &indications);
if (efi_status != EFI_SUCCESS)
efi_status = gRT->SetVariable(L"OsIndications", &GV_GUID,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_BOOTSERVICE_ACCESS,
DataSize, &indications);
if (EFI_ERROR(efi_status))
return efi_status;
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, NULL);
gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
/* does not return */
return EFI_SUCCESS;
@ -218,19 +211,19 @@ get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner,
*len = 0;
efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
NULL, len, NULL);
if (efi_status != EFI_BUFFER_TOO_SMALL)
efi_status = gRT->GetVariable(var, &owner, NULL, len, NULL);
if (efi_status != EFI_BUFFER_TOO_SMALL) {
if (!EFI_ERROR(efi_status)) /* this should never happen */
return EFI_PROTOCOL_ERROR;
return efi_status;
}
*data = AllocateZeroPool(*len);
if (!*data)
return EFI_OUT_OF_RESOURCES;
efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
attributes, len, *data);
if (efi_status != EFI_SUCCESS) {
efi_status = gRT->GetVariable(var, &owner, attributes, len, *data);
if (EFI_ERROR(efi_status)) {
FreePool(*data);
*data = NULL;
}
@ -263,19 +256,19 @@ 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)
{
UINTN DataSize;
UINT8 *Data;
EFI_STATUS status;
UINTN DataSize = 0;
UINT8 *Data = NULL;
EFI_STATUS efi_status;
status = get_variable(var, &Data, &DataSize, owner);
if (status != EFI_SUCCESS)
return status;
efi_status = get_variable(var, &Data, &DataSize, owner);
if (EFI_ERROR(efi_status))
return efi_status;
status = find_in_esl(Data, DataSize, key, keylen);
efi_status = find_in_esl(Data, DataSize, key, keylen);
FreePool(Data);
return status;
return efi_status;
}
int
@ -284,11 +277,11 @@ variable_is_setupmode(int default_return)
/* set to 1 because we return true if SetupMode doesn't exist */
UINT8 SetupMode = default_return;
UINTN DataSize = sizeof(SetupMode);
EFI_STATUS status;
EFI_STATUS efi_status;
status = uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL,
&DataSize, &SetupMode);
if (EFI_ERROR(status))
efi_status = gRT->GetVariable(L"SetupMode", &GV_GUID, NULL,
&DataSize, &SetupMode);
if (EFI_ERROR(efi_status))
return default_return;
return SetupMode;
@ -300,12 +293,12 @@ variable_is_secureboot(void)
/* return false if variable doesn't exist */
UINT8 SecureBoot = 0;
UINTN DataSize;
EFI_STATUS status;
EFI_STATUS efi_status;
DataSize = sizeof(SecureBoot);
status = uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL,
&DataSize, &SecureBoot);
if (EFI_ERROR(status))
efi_status = gRT->GetVariable(L"SecureBoot", &GV_GUID, NULL,
&DataSize, &SecureBoot);
if (EFI_ERROR(efi_status))
return 0;
return SecureBoot;
@ -315,14 +308,15 @@ EFI_STATUS
variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
UINT8 hash[SHA256_DIGEST_SIZE])
{
EFI_STATUS status;
EFI_STATUS efi_status;
if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE)
== EFI_SUCCESS)
efi_status = find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE);
if (!EFI_ERROR(efi_status))
/* hash already present */
return EFI_ALREADY_STARTED;
UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE];
UINT8 sig[sizeof(EFI_SIGNATURE_LIST)
+ sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE];
EFI_SIGNATURE_LIST *l = (void *)sig;
EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST);
SetMem(sig, 0, sizeof(sig));
@ -330,16 +324,16 @@ variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
l->SignatureListSize = sizeof(sig);
l->SignatureSize = 16 +32; /* UEFI defined */
CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE);
d->SignatureOwner = MOK_OWNER;
d->SignatureOwner = SHIM_LOCK_GUID;
if (CompareGuid(&owner, &SIG_DB) == 0)
status = SetSecureVariable(var, sig, sizeof(sig), owner,
EFI_VARIABLE_APPEND_WRITE, 0);
efi_status = SetSecureVariable(var, sig, sizeof(sig), owner,
EFI_VARIABLE_APPEND_WRITE, 0);
else
status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner,
EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_APPEND_WRITE,
sizeof(sig), sig);
return status;
efi_status = gRT->SetVariable(var, &owner,
EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_APPEND_WRITE,
sizeof(sig), sig);
return efi_status;
}

136
model.c Normal file
View File

@ -0,0 +1,136 @@
/*
* model.c - modeling file for coverity
* Copyright 2017 Peter Jones <pjones@redhat.com>
*
*/
#ifndef __COVERITY__
/* This is so vim's Syntastic checker won't yell about all these. */
extern void __coverity_string_size_sanitize__(int);
extern void __coverity_negative_sink__(int);
extern void __coverity_alloc_nosize__(void);
extern void *__coverity_alloc__(int);
extern void __coverity_sleep__();
extern void __coverity_tainted_data_sanitize__(void *);
#endif
void *
OBJ_dup(void *o)
{
__coverity_alloc_nosize__();
}
int
UTF8_getc(const unsigned char *str, int len, unsigned long *val)
{
/* You can't quite express the right thing here, so instead we're
* telling covscan that if len is a certain value, the string has
* been checked for having a NUL at the right place. Ideally what
* we'd tell it is it's never allowed to give us a string shorter
* than a certain length if certain bits (i.e. the UTF-8 surrogate
* length bits) are set. */
if (len <= 0) {
__coverity_string_size_sanitize__(0);
return 0;
} else if (len <= 6) {
__coverity_string_size_sanitize__(0);
return len;
}
return -2;
}
typedef unsigned long long u64;
typedef struct {
unsigned long long hi;
unsigned long long lo;
} u128;
void
gcm_gmult_4bit(u64 Xi[2], u128 Htable[16])
{
__coverity_tainted_data_sanitize__(Htable);
}
void
msleep(int n)
{
__coverity_sleep__();
}
/* From MdePkg/Include/Base.h or so */
typedef unsigned long long UINT64;
typedef unsigned long UINTN;
typedef long INTN;
typedef UINT64 EFI_PHYSICAL_ADDRESS;
typedef UINTN RETURN_STATUS;
typedef RETURN_STATUS EFI_STATUS;
#define MAX_BIT (1ULL << (sizeof (INTN) * 8 - 1))
#define MAX_INTN ((INTN)~MAX_BIT)
#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode)))
#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode))
#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0)
#define RETURN_SUCCESS 0
#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2)
#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9)
/* From MdePkg/Include/Uefi/UefiBaseType.h */
#define EFI_SUCCESS RETURN_SUCCESS
#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER
#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES
#define EFI_PAGE_MASK 0xFFF
#define EFI_PAGE_SHIFT 12
#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0))
#define EFI_PAGES_TO_SIZE(a) ((a) << EFI_PAGE_SHIFT)
/* From MdePkg/Include/Uefi/UefiMultiPhase.h */
typedef enum {
EfiReservedMemoryType,
EfiLoaderCode,
EfiLoaderData,
EfiBootServicesCode,
EfiBootServicesData,
EfiRuntimeServicesCode,
EfiRuntimeServicesData,
EfiConventionalMemory,
EfiUnusableMemory,
EfiACPIReclaimMemory,
EfiACPIMemoryNVS,
EfiMemoryMappedIO,
EfiMemoryMappedIOPortSpace,
EfiPalCode,
EfiPersistentMemory,
EfiMaxMemoryType
} EFI_MEMORY_TYPE;
/* From MdePkg/Include/Uefi/UefiSpec.h */
typedef enum {
AllocateAnyPages,
AllocateMaxAddress,
AllocateAddress,
MaxAllocateType
} EFI_ALLOCATE_TYPE;
EFI_STATUS
AllocatePages(EFI_ALLOCATE_TYPE Type,
EFI_MEMORY_TYPE MemoryType,
unsigned long Pages,
EFI_PHYSICAL_ADDRESS *Memory)
{
int has_memory;
unsigned long bytes = EFI_PAGES_TO_SIZE(Pages);
if (Pages >= (unsigned long)((-1L) >> EFI_PAGE_SHIFT))
return EFI_INVALID_PARAMETER;
__coverity_negative_sink__(bytes);
if (has_memory) {
*Memory = (EFI_PHYSICAL_ADDRESS)__coverity_alloc__(bytes);
return EFI_SUCCESS;
}
return EFI_OUT_OF_RESOURCES;
}
// vim:fenc=utf-8:tw=75

334
mok.c Normal file
View File

@ -0,0 +1,334 @@
/*
* mok.c
* Copyright 2017 Peter Jones <pjones@redhat.com>
*
* Distributed under terms of the GPLv3 license.
*/
#include "shim.h"
/*
* Check if a variable exists
*/
static BOOLEAN check_var(CHAR16 *varname)
{
EFI_STATUS efi_status;
UINTN size = sizeof(UINT32);
UINT32 MokVar;
UINT32 attributes;
efi_status = gRT->GetVariable(varname, &SHIM_LOCK_GUID, &attributes,
&size, (void *)&MokVar);
if (!EFI_ERROR(efi_status) || efi_status == EFI_BUFFER_TOO_SMALL)
return TRUE;
return FALSE;
}
/*
* If the OS has set any of these variables we need to drop into MOK and
* handle them appropriately
*/
static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
{
EFI_STATUS efi_status;
if (check_var(L"MokNew") || check_var(L"MokSB") ||
check_var(L"MokPW") || check_var(L"MokAuth") ||
check_var(L"MokDel") || check_var(L"MokDB") ||
check_var(L"MokXNew") || check_var(L"MokXDel") ||
check_var(L"MokXAuth")) {
efi_status = start_image(image_handle, MOK_MANAGER);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to start MokManager: %r\n", efi_status);
return efi_status;
}
}
return EFI_SUCCESS;
}
/*
* MoK variables that need to have their storage validated.
*
* The order here is important, since this is where we measure for the
* tpm as well.
*/
struct mok_state_variable {
CHAR16 *name;
char *name8;
CHAR16 *rtname;
EFI_GUID *guid;
UINT8 *data;
UINTN data_size;
/*
* These two are indirect pointers just to make initialization
* saner...
*/
UINT8 **addend_source;
UINT32 *addend_size;
UINT32 yes_attr;
UINT32 no_attr;
UINT32 flags;
UINTN pcr;
UINT8 *state;
};
#define MOK_MIRROR_KEYDB 0x01
#define MOK_MIRROR_DELETE_FIRST 0x02
#define MOK_VARIABLE_MEASURE 0x04
#define MOK_VARIABLE_LOG 0x08
struct mok_state_variable mok_state_variables[] = {
{.name = L"MokList",
.name8 = "MokList",
.rtname = L"MokListRT",
.guid = &SHIM_LOCK_GUID,
.yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_NON_VOLATILE,
.no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
.addend_source = &vendor_cert,
.addend_size = &vendor_cert_size,
.flags = MOK_MIRROR_KEYDB |
MOK_VARIABLE_LOG,
.pcr = 14,
},
{.name = L"MokListX",
.name8 = "MokListX",
.rtname = L"MokListXRT",
.guid = &SHIM_LOCK_GUID,
.yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_NON_VOLATILE,
.no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
.flags = MOK_MIRROR_KEYDB |
MOK_VARIABLE_LOG,
.pcr = 14,
},
{.name = L"MokSBState",
.name8 = "MokSBState",
.rtname = L"MokSBStateRT",
.guid = &SHIM_LOCK_GUID,
.yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_NON_VOLATILE,
.no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
.flags = MOK_MIRROR_DELETE_FIRST |
MOK_VARIABLE_MEASURE |
MOK_VARIABLE_LOG,
.pcr = 14,
.state = &user_insecure_mode,
},
{.name = L"MokDBState",
.name8 = "MokDBState",
.rtname = L"MokIgnoreDB",
.guid = &SHIM_LOCK_GUID,
.yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_NON_VOLATILE,
.no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
.state = &ignore_db,
},
{ NULL, }
};
static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
{
EFI_STATUS efi_status = EFI_SUCCESS;
void *FullData = NULL;
UINTN FullDataSize = 0;
uint8_t *p = NULL;
if ((v->flags & MOK_MIRROR_KEYDB) &&
v->addend_source && *v->addend_source &&
v->addend_size && *v->addend_size) {
EFI_SIGNATURE_LIST *CertList = NULL;
EFI_SIGNATURE_DATA *CertData = NULL;
FullDataSize = v->data_size
+ sizeof (*CertList)
+ sizeof (EFI_GUID)
+ *v->addend_size;
FullData = AllocatePool(FullDataSize);
if (!FullData) {
perror(L"Failed to allocate space for MokListRT\n");
return EFI_OUT_OF_RESOURCES;
}
p = FullData;
if (!EFI_ERROR(efi_status) && v->data_size > 0) {
CopyMem(p, v->data, v->data_size);
p += v->data_size;
}
CertList = (EFI_SIGNATURE_LIST *)p;
p += sizeof (*CertList);
CertData = (EFI_SIGNATURE_DATA *)p;
p += sizeof (EFI_GUID);
CertList->SignatureType = EFI_CERT_TYPE_X509_GUID;
CertList->SignatureListSize = *v->addend_size
+ sizeof (*CertList)
+ sizeof (*CertData)
-1;
CertList->SignatureHeaderSize = 0;
CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID);
CertData->SignatureOwner = SHIM_LOCK_GUID;
CopyMem(p, *v->addend_source, *v->addend_size);
if (v->data && v->data_size)
FreePool(v->data);
v->data = FullData;
v->data_size = FullDataSize;
} else {
FullDataSize = v->data_size;
FullData = v->data;
}
if (FullDataSize) {
efi_status = gRT->SetVariable(v->rtname, v->guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
FullDataSize, FullData);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to set %s: %r\n",
v->rtname, efi_status);
}
}
return efi_status;
}
/*
* Verify our non-volatile MoK state. This checks the variables above
* accessable and have valid attributes. If they don't, it removes
* them. If any of them can't be removed, our ability to do this is
* comprimized, so return EFI_SECURITY_VIOLATION.
*
* Any variable that isn't deleted and has ->measure == TRUE is then
* measured into the tpm.
*
* Any variable with a ->rtname element is then mirrored to a
* runtime-accessable version. The new ones won't be marked NV, so the OS
* can't modify them.
*/
EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
{
UINTN i;
EFI_STATUS ret = EFI_SUCCESS;
EFI_STATUS efi_status;
user_insecure_mode = 0;
ignore_db = 0;
for (i = 0; mok_state_variables[i].name != NULL; i++) {
struct mok_state_variable *v = &mok_state_variables[i];
UINT32 attrs = 0;
BOOLEAN delete = FALSE, present, addend;
efi_status = get_variable_attr(v->name,
&v->data, &v->data_size,
*v->guid, &attrs);
if (efi_status == EFI_NOT_FOUND)
continue;
if (EFI_ERROR(efi_status)) {
perror(L"Could not verify %s: %r\n", v->name,
efi_status);
/*
* don't clobber EFI_SECURITY_VIOLATION from some
* other variable in the list.
*/
if (ret != EFI_SECURITY_VIOLATION)
ret = efi_status;
continue;
}
if (!(attrs & v->yes_attr)) {
perror(L"Variable %s is missing attributes:\n",
v->name);
perror(L" 0x%08x should have 0x%08x set.\n",
attrs, v->yes_attr);
delete = TRUE;
}
if (attrs & v->no_attr) {
perror(L"Variable %s has incorrect attribute:\n",
v->name);
perror(L" 0x%08x should not have 0x%08x set.\n",
attrs, v->no_attr);
delete = TRUE;
}
if (delete == TRUE) {
perror(L"Deleting bad variable %s\n", v->name);
efi_status = LibDeleteVariable(v->name, v->guid);
if (EFI_ERROR(efi_status)) {
perror(L"Failed to erase %s\n", v->name);
ret = EFI_SECURITY_VIOLATION;
}
FreePool(v->data);
v->data = NULL;
v->data_size = 0;
continue;
}
if (v->data && v->data_size == sizeof(UINT8) && v->state) {
*v->state = v->data[0];
}
present = (v->data && v->data_size) ? TRUE : FALSE;
addend = (v->addend_source && v->addend_size &&
*v->addend_source && *v->addend_size)
? TRUE : FALSE;
if (v->flags & MOK_VARIABLE_MEASURE && present) {
/*
* Measure this into PCR 7 in the Microsoft format
*/
efi_status = tpm_measure_variable(v->name, *v->guid,
v->data_size,
v->data);
if (EFI_ERROR(efi_status)) {
if (ret != EFI_SECURITY_VIOLATION)
ret = efi_status;
}
}
if (v->flags & MOK_VARIABLE_LOG && present) {
/*
* Log this variable into whichever PCR the table
* says.
*/
EFI_PHYSICAL_ADDRESS datap =
(EFI_PHYSICAL_ADDRESS)(UINTN)v->data,
efi_status = tpm_log_event(datap, v->data_size,
v->pcr, (CHAR8 *)v->name8);
if (EFI_ERROR(efi_status)) {
if (ret != EFI_SECURITY_VIOLATION)
ret = efi_status;
}
}
if (v->rtname && present && addend) {
if (v->flags & MOK_MIRROR_DELETE_FIRST)
LibDeleteVariable(v->rtname, v->guid);
efi_status = mirror_one_mok_variable(v);
if (EFI_ERROR(efi_status) &&
ret != EFI_SECURITY_VIOLATION)
ret = efi_status;
}
}
/*
* Enter MokManager if necessary. Any actual *changes* here will
* cause MokManager to demand a machine reboot, so this is safe to
* have after the entire loop.
*/
efi_status = check_mok_request(image_handle);
if (EFI_ERROR(efi_status)) {
if (ret != EFI_SECURITY_VIOLATION)
ret = efi_status;
return ret;
}
return ret;
}
// vim:fenc=utf-8:tw=75

View File

@ -34,9 +34,8 @@
*/
#include "shim.h"
#include <string.h>
#include "netboot.h"
#include "str.h"
#define ntohs(x) __builtin_bswap16(x) /* supported both by GCC and clang */
#define htons(x) ntohs(x)
@ -59,11 +58,11 @@ typedef struct {
*/
BOOLEAN findNetboot(EFI_HANDLE device)
{
EFI_STATUS status;
EFI_STATUS efi_status;
status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
&PxeBaseCodeProtocol, (VOID **)&pxe);
if (status != EFI_SUCCESS) {
efi_status = gBS->HandleProtocol(device, &PxeBaseCodeProtocol,
(VOID **) &pxe);
if (EFI_ERROR(efi_status)) {
pxe = NULL;
return FALSE;
}
@ -196,12 +195,12 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
memset(ip6inv, 0, sizeof(ip6inv));
if (strncmp((UINT8 *)url, (UINT8 *)"tftp://", 7)) {
Print(L"URLS MUST START WITH tftp://\n");
console_print(L"URLS MUST START WITH tftp://\n");
return FALSE;
}
start = url + 7;
if (*start != '[') {
Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
return FALSE;
}
@ -210,12 +209,12 @@ static BOOLEAN extract_tftp_info(CHAR8 *url)
while ((*end != '\0') && (*end != ']')) {
end++;
if (end - start >= (int)sizeof(ip6str)) {
Print(L"TFTP URL includes malformed IPv6 address\n");
console_print(L"TFTP URL includes malformed IPv6 address\n");
return FALSE;
}
}
if (*end == '\0') {
Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n");
return FALSE;
}
memset(ip6str, 0, sizeof(ip6str));
@ -257,10 +256,20 @@ static EFI_STATUS parseDhcp4()
{
CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR);
INTN template_len = strlen(template) + 1;
EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4;
INTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127);
if(pxe->Mode->ProxyOfferReceived) {
/*
* Proxy should not have precedence. Check if DhcpAck
* contained boot info.
*/
if(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile[0] == '\0')
pkt_v4 = &pxe->Mode->ProxyOffer.Dhcpv4;
}
INTN dir_len = strnlena(pkt_v4->BootpBootFile, 127);
INTN i;
UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile;
UINT8 *dir = pkt_v4->BootpBootFile;
for (i = dir_len; i >= 0; i--) {
if (dir[i] == '/')
@ -281,7 +290,7 @@ static EFI_STATUS parseDhcp4()
if (dir_len == 0 && dir[0] != '/' && template[0] == '/')
template++;
strcata(full_path, template);
memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4);
memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4);
return EFI_SUCCESS;
}
@ -289,7 +298,7 @@ static EFI_STATUS parseDhcp4()
EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle)
{
EFI_STATUS rc;
EFI_STATUS efi_status;
if (!pxe)
return EFI_NOT_READY;
@ -301,33 +310,32 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle)
* if its ipv4 or ipv6
*/
if (pxe->Mode->UsingIpv6){
rc = parseDhcp6();
efi_status = parseDhcp6();
} else
rc = parseDhcp4();
return rc;
efi_status = parseDhcp4();
return efi_status;
}
EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz)
{
EFI_STATUS rc;
EFI_STATUS efi_status;
EFI_PXE_BASE_CODE_TFTP_OPCODE read = EFI_PXE_BASE_CODE_TFTP_READ_FILE;
BOOLEAN overwrite = FALSE;
BOOLEAN nobuffer = FALSE;
UINTN blksz = 512;
Print(L"Fetching Netboot Image\n");
console_print(L"Fetching Netboot Image\n");
if (*buffer == NULL) {
*buffer = AllocatePool(4096 * 1024);
if (!*buffer)
return EFI_OUT_OF_RESOURCES;
return EFI_OUT_OF_RESOURCES;
*bufsiz = 4096 * 1024;
}
try_again:
rc = uefi_call_wrapper(pxe->Mtftp, 10, pxe, read, *buffer, overwrite,
bufsiz, &blksz, &tftp_addr, full_path, NULL, nobuffer);
if (rc == EFI_BUFFER_TOO_SMALL) {
efi_status = pxe->Mtftp(pxe, read, *buffer, overwrite, bufsiz, &blksz,
&tftp_addr, full_path, NULL, nobuffer);
if (efi_status == EFI_BUFFER_TOO_SMALL) {
/* try again, doubling buf size */
*bufsiz *= 2;
FreePool(*buffer);
@ -337,8 +345,8 @@ try_again:
goto try_again;
}
if (rc != EFI_SUCCESS && *buffer) {
if (EFI_ERROR(efi_status) && *buffer) {
FreePool(*buffer);
}
return rc;
return efi_status;
}

View File

@ -50,13 +50,19 @@
#include <efi.h>
#include <efiapi.h>
#include <efilib.h>
#include "shim.h"
#include "replacements.h"
#include "console.h"
#include "errors.h"
static EFI_SYSTEM_TABLE *systab;
EFI_SYSTEM_TABLE *
get_active_systab(void)
{
if (systab)
return systab;
return ST;
}
static typeof(systab->BootServices->LoadImage) system_load_image;
static typeof(systab->BootServices->StartImage) system_start_image;
static typeof(systab->BootServices->Exit) system_exit;
@ -73,6 +79,7 @@ unhook_system_services(void)
systab->BootServices->LoadImage = system_load_image;
systab->BootServices->StartImage = system_start_image;
systab->BootServices->ExitBootServices = system_exit_boot_services;
gBS = systab->BootServices;
}
static EFI_STATUS EFIAPI
@ -80,80 +87,67 @@ load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle,
EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer,
UINTN SourceSize, EFI_HANDLE *ImageHandle)
{
EFI_STATUS status;
unhook_system_services();
EFI_STATUS efi_status;
status = systab->BootServices->LoadImage(BootPolicy,
ParentImageHandle, DevicePath,
SourceBuffer, SourceSize, ImageHandle);
unhook_system_services();
efi_status = gBS->LoadImage(BootPolicy, ParentImageHandle, DevicePath,
SourceBuffer, SourceSize, ImageHandle);
hook_system_services(systab);
if (EFI_ERROR(status))
if (EFI_ERROR(efi_status))
last_loaded_image = NULL;
else
last_loaded_image = *ImageHandle;
return status;
return efi_status;
}
static EFI_STATUS EFIAPI
start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data)
{
EFI_STATUS status;
EFI_STATUS efi_status;
unhook_system_services();
/* We have to uninstall shim's protocol here, because if we're
* On the fallback.efi path, then our call pathway is:
*
* shim->fallback->shim->grub
* ^ ^ ^
* | | \- gets protocol #0
* | \- installs its protocol (#1)
* \- installs its protocol (#0)
* and if we haven't removed this, then grub will get the *first*
* shim's protocol, but it'll get the second shim's systab
* replacements. So even though it will participate and verify
* the kernel, the systab never finds out.
*/
if (image_handle == last_loaded_image) {
loader_is_participating = 1;
uninstall_shim_protocols();
}
status = systab->BootServices->StartImage(image_handle, exit_data_size, exit_data);
if (EFI_ERROR(status)) {
efi_status = gBS->StartImage(image_handle, exit_data_size, exit_data);
if (EFI_ERROR(efi_status)) {
if (image_handle == last_loaded_image) {
EFI_STATUS status2 = install_shim_protocols();
EFI_STATUS efi_status2 = install_shim_protocols();
if (EFI_ERROR(status2)) {
Print(L"Something has gone seriously wrong: %d\n",
status2);
Print(L"shim cannot continue, sorry.\n");
if (EFI_ERROR(efi_status2)) {
console_print(L"Something has gone seriously wrong: %r\n",
efi_status2);
console_print(L"shim cannot continue, sorry.\n");
msleep(5000000);
systab->RuntimeServices->ResetSystem(
EfiResetShutdown,
EFI_SECURITY_VIOLATION, 0, NULL);
gRT->ResetSystem(EfiResetShutdown,
EFI_SECURITY_VIOLATION,
0, NULL);
}
}
hook_system_services(systab);
loader_is_participating = 0;
}
return status;
return efi_status;
}
static EFI_STATUS EFIAPI
exit_boot_services(EFI_HANDLE image_key, UINTN map_key)
{
if (loader_is_participating || verification_method == VERIFIED_BY_HASH) {
if (loader_is_participating ||
verification_method == VERIFIED_BY_HASH) {
unhook_system_services();
EFI_STATUS status;
status = systab->BootServices->ExitBootServices(image_key, map_key);
if (status != EFI_SUCCESS)
EFI_STATUS efi_status;
efi_status = gBS->ExitBootServices(image_key, map_key);
if (EFI_ERROR(efi_status))
hook_system_services(systab);
return status;
return efi_status;
}
Print(L"Bootloader has not verified loaded image.\n");
Print(L"System is compromised. halting.\n");
console_print(L"Bootloader has not verified loaded image.\n");
console_print(L"System is compromised. halting.\n");
msleep(5000000);
systab->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL);
gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL);
return EFI_SECURITY_VIOLATION;
}
@ -161,41 +155,41 @@ static EFI_STATUS EFIAPI
do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus,
UINTN ExitDataSize, CHAR16 *ExitData)
{
EFI_STATUS status;
EFI_STATUS efi_status;
shim_fini();
status = systab->BootServices->Exit(ImageHandle, ExitStatus,
ExitDataSize, ExitData);
if (EFI_ERROR(status)) {
EFI_STATUS status2 = shim_init();
efi_status = gBS->Exit(ImageHandle, ExitStatus,
ExitDataSize, ExitData);
if (EFI_ERROR(efi_status)) {
EFI_STATUS efi_status2 = shim_init();
if (EFI_ERROR(status2)) {
Print(L"Something has gone seriously wrong: %r\n",
status2);
Print(L"shim cannot continue, sorry.\n");
if (EFI_ERROR(efi_status2)) {
console_print(L"Something has gone seriously wrong: %r\n",
efi_status2);
console_print(L"shim cannot continue, sorry.\n");
msleep(5000000);
systab->RuntimeServices->ResetSystem(
EfiResetShutdown,
EFI_SECURITY_VIOLATION, 0, NULL);
gRT->ResetSystem(EfiResetShutdown,
EFI_SECURITY_VIOLATION, 0, NULL);
}
}
return status;
return efi_status;
}
void
hook_system_services(EFI_SYSTEM_TABLE *local_systab)
{
systab = local_systab;
gBS = systab->BootServices;
/* We need to hook various calls to make this work... */
/* We need LoadImage() hooked so that fallback.c can load shim
* without having to fake LoadImage as well. This allows it
* to call the system LoadImage(), and have us track the output
* and mark loader_is_participating in start_image. This means
* anything added by fallback has to be verified by the system db,
* which we want to preserve anyway, since that's all launching
* and mark loader_is_participating in replacement_start_image. This
* means anything added by fallback has to be verified by the system
* db, which we want to preserve anyway, since that's all launching
* through BDS gives us. */
system_load_image = systab->BootServices->LoadImage;
systab->BootServices->LoadImage = load_image;
@ -203,7 +197,7 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab)
/* we need StartImage() so that we can allow chain booting to an
* image trusted by the firmware */
system_start_image = systab->BootServices->StartImage;
systab->BootServices->StartImage = start_image;
systab->BootServices->StartImage = replacement_start_image;
/* we need to hook ExitBootServices() so a) we can enforce the policy
* and b) we can unwrap when we're done. */
@ -215,12 +209,14 @@ void
unhook_exit(void)
{
systab->BootServices->Exit = system_exit;
gBS = systab->BootServices;
}
void
hook_exit(EFI_SYSTEM_TABLE *local_systab)
{
systab = local_systab;
gBS = local_systab->BootServices;
/* we need to hook Exit() so that we can allow users to quit the
* bootloader and still e.g. start a new one or run an internal

1072
shim.c

File diff suppressed because it is too large Load Diff

216
shim.h
View File

@ -1,12 +1,128 @@
#ifndef SHIM_H_
#define SHIM_H_
#if defined __GNUC__ && defined __GNUC_MINOR__
# define GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define GNUC_PREREQ(maj, min) 0
#endif
#if defined __clang_major__ && defined __clang_minor__
# define CLANG_PREREQ(maj, min) \
((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
#else
# define CLANG_PREREQ(maj, min) 0
#endif
#if defined(__x86_64__)
#if !defined(GNU_EFI_USE_MS_ABI)
#error On x86_64 you must use ms_abi (GNU_EFI_USE_MS_ABI) in gnu-efi and shim.
#endif
/* gcc 4.5.4 is the first documented release with -mabi=ms */
#if !GNUC_PREREQ(4, 7) && !CLANG_PREREQ(3, 4)
#error On x86_64 you must have a compiler new enough to support __attribute__((__ms_abi__))
#endif
#endif
#include <efi.h>
#include <efilib.h>
#undef uefi_call_wrapper
#include "PeImage.h"
#include <stddef.h>
extern EFI_GUID SHIM_LOCK_GUID;
#define min(a, b) ({(a) < (b) ? (a) : (b);})
#ifdef __x86_64__
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubx64.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubx64.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"x64"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/x64/"
#endif
#endif
#if defined(__i686__) || defined(__i386__)
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubia32.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubia32.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"ia32"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/ia32/"
#endif
#endif
#if defined(__aarch64__)
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubaa64.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubaa64.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"aa64"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/aa64/"
#endif
#endif
#if defined(__arm__)
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubarm.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubarm.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"arm"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/arm/"
#endif
#endif
#define FALLBACK L"\\fb" EFI_ARCH L".efi"
#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi"
#include "include/configtable.h"
#include "include/console.h"
#include "include/crypt_blowfish.h"
#include "include/efiauthenticated.h"
#include "include/errors.h"
#include "include/execute.h"
#include "include/guid.h"
#include "include/Http.h"
#include "include/httpboot.h"
#include "include/Ip4Config2.h"
#include "include/Ip6Config.h"
#include "include/netboot.h"
#include "include/PasswordCrypt.h"
#include "include/PeImage.h"
#include "include/replacements.h"
#if defined(OVERRIDE_SECURITY_POLICY)
#include "include/security_policy.h"
#endif
#include "include/simple_file.h"
#include "include/str.h"
#include "include/tpm.h"
#include "include/ucs2.h"
#include "include/variables.h"
#include "version.h"
#ifdef ENABLE_SHIM_CERT
#include "shim_cert.h"
#endif
INTERFACE_DECL(_SHIM_LOCK);
@ -43,88 +159,30 @@ typedef struct _SHIM_LOCK {
extern EFI_STATUS shim_init(void);
extern void shim_fini(void);
extern EFI_STATUS LogError(const char *file, int line, const char *func, CHAR16 *fmt, ...);
extern EFI_STATUS LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...);
extern EFI_STATUS VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args);
extern VOID PrintErrors(VOID);
extern VOID ClearErrors(VOID);
extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath);
extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle);
#ifdef __x86_64__
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubx64.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubx64.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"x64"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/x64/"
#endif
#endif
extern UINT32 vendor_cert_size;
extern UINT32 vendor_dbx_size;
extern UINT8 *vendor_cert;
extern UINT8 *vendor_dbx;
#if defined(__i686__) || defined(__i386__)
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubia32.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubia32.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"ia32"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/ia32/"
#endif
#endif
extern UINT8 user_insecure_mode;
extern UINT8 ignore_db;
extern UINT8 in_protocol;
#if defined(__aarch64__)
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubaa64.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubaa64.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"aa64"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/aa64/"
#endif
#endif
#if defined(__arm__)
#ifndef DEFAULT_LOADER
#define DEFAULT_LOADER L"\\grubarm.efi"
#endif
#ifndef DEFAULT_LOADER_CHAR
#define DEFAULT_LOADER_CHAR "\\grubarm.efi"
#endif
#ifndef EFI_ARCH
#define EFI_ARCH L"arm"
#endif
#ifndef DEBUGDIR
#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/arm/"
#endif
#endif
#include "netboot.h"
#include "httpboot.h"
#include "replacements.h"
#include "tpm.h"
#include "ucs2.h"
#include "guid.h"
#include "variables.h"
#include "efiauthenticated.h"
#include "security_policy.h"
#include "console.h"
#include "version.h"
#ifdef ENABLE_SHIM_CERT
#include "shim_cert.h"
#endif
#define LogError(fmt, ...) LogError(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
#define perror_(file, line, func, fmt, ...) ({ \
UINTN __perror_ret = 0; \
if (!in_protocol) \
__perror_ret = console_print((fmt), ##__VA_ARGS__); \
LogError_(file, line, func, fmt, ##__VA_ARGS__); \
__perror_ret; \
})
#define perror(fmt, ...) perror_(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
#define LogError(fmt, ...) LogError_(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__)
#endif /* SHIM_H_ */

141
tpm.c
View File

@ -3,17 +3,7 @@
#include <string.h>
#include <stdint.h>
#include "tpm.h"
extern UINT8 in_protocol;
#define perror(fmt, ...) ({ \
UINTN __perror_ret = 0; \
if (!in_protocol) \
__perror_ret = Print((fmt), ##__VA_ARGS__); \
__perror_ret; \
})
#include "shim.h"
typedef struct {
CHAR16 *VariableName;
@ -25,22 +15,18 @@ typedef struct {
UINTN measuredcount = 0;
VARIABLE_RECORD *measureddata = NULL;
EFI_GUID tpm_guid = EFI_TPM_GUID;
EFI_GUID tpm2_guid = EFI_TPM2_GUID;
static BOOLEAN tpm_present(efi_tpm_protocol_t *tpm)
{
EFI_STATUS status;
EFI_STATUS efi_status;
TCG_EFI_BOOT_SERVICE_CAPABILITY caps;
UINT32 flags;
EFI_PHYSICAL_ADDRESS eventlog, lastevent;
caps.Size = (UINT8)sizeof(caps);
status = uefi_call_wrapper(tpm->status_check, 5, tpm, &caps, &flags,
&eventlog, &lastevent);
if (status != EFI_SUCCESS || caps.TPMDeactivatedFlag
|| !caps.TPMPresentFlag)
efi_status = tpm->status_check(tpm, &caps, &flags,
&eventlog, &lastevent);
if (EFI_ERROR(efi_status) ||
caps.TPMDeactivatedFlag || !caps.TPMPresentFlag)
return FALSE;
return TRUE;
@ -50,18 +36,19 @@ static EFI_STATUS tpm2_get_caps(efi_tpm2_protocol_t *tpm,
EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps,
BOOLEAN *old_caps)
{
EFI_STATUS status;
EFI_STATUS efi_status;
caps->Size = (UINT8)sizeof(*caps);
status = uefi_call_wrapper(tpm->get_capability, 2, tpm, caps);
if (status != EFI_SUCCESS)
return status;
efi_status = tpm->get_capability(tpm, caps);
if (EFI_ERROR(efi_status))
return efi_status;
if (caps->StructureVersion.Major == 1 &&
caps->StructureVersion.Minor == 0)
*old_caps = TRUE;
else
*old_caps = FALSE;
return EFI_SUCCESS;
}
@ -115,8 +102,7 @@ static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2,
else
log_fmt = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
return uefi_call_wrapper(tpm2->get_event_log, 5, tpm2, log_fmt,
&start, &end, &truncated);
return tpm2->get_event_log(tpm2, log_fmt, &start, &end, &truncated);
}
static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm,
@ -124,19 +110,19 @@ static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm,
BOOLEAN *old_caps_p,
EFI_TCG2_BOOT_SERVICE_CAPABILITY *capsp)
{
EFI_STATUS status;
EFI_STATUS efi_status;
*tpm = NULL;
*tpm2 = NULL;
status = LibLocateProtocol(&tpm2_guid, (VOID **)tpm2);
efi_status = LibLocateProtocol(&EFI_TPM2_GUID, (VOID **)tpm2);
/* TPM 2.0 */
if (status == EFI_SUCCESS) {
if (!EFI_ERROR(efi_status)) {
BOOLEAN old_caps;
EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
status = tpm2_get_caps(*tpm2, &caps, &old_caps);
if (EFI_ERROR(status))
return status;
efi_status = tpm2_get_caps(*tpm2, &caps, &old_caps);
if (EFI_ERROR(efi_status))
return efi_status;
if (tpm2_present(&caps, old_caps)) {
if (old_caps_p)
@ -146,9 +132,9 @@ static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm,
return EFI_SUCCESS;
}
} else {
status = LibLocateProtocol(&tpm_guid, (VOID **)tpm);
if (EFI_ERROR(status))
return status;
efi_status = LibLocateProtocol(&EFI_TPM_GUID, (VOID **)tpm);
if (EFI_ERROR(efi_status))
return efi_status;
if (tpm_present(*tpm))
return EFI_SUCCESS;
@ -161,25 +147,35 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
UINT8 pcr, const CHAR8 *log, UINTN logsize,
UINT32 type, CHAR8 *hash)
{
EFI_STATUS status;
EFI_STATUS efi_status;
efi_tpm_protocol_t *tpm;
efi_tpm2_protocol_t *tpm2;
BOOLEAN old_caps;
EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
status = tpm_locate_protocol(&tpm, &tpm2, &old_caps, &caps);
if (EFI_ERROR(status)) {
return status;
efi_status = tpm_locate_protocol(&tpm, &tpm2, &old_caps, &caps);
if (EFI_ERROR(efi_status)) {
#ifdef REQUIRE_TPM
perror(L"TPM logging failed: %r\n", efi_status);
return efi_status;
#else
if (efi_status != EFI_NOT_FOUND) {
perror(L"TPM logging failed: %r\n", efi_status);
return efi_status;
}
#endif
} else if (tpm2) {
EFI_TCG2_EVENT *event;
EFI_TCG2_EVENT_LOG_BITMAP supported_logs;
supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps);
status = trigger_tcg2_final_events_table(tpm2, supported_logs);
if (EFI_ERROR(status)) {
perror(L"Unable to trigger tcg2 final events table: %r\n", status);
return status;
efi_status = trigger_tcg2_final_events_table(tpm2,
supported_logs);
if (EFI_ERROR(efi_status)) {
perror(L"Unable to trigger tcg2 final events table: %r\n",
efi_status);
return efi_status;
}
event = AllocatePool(sizeof(*event) + logsize);
@ -196,26 +192,26 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
CopyMem(event->Event, (VOID *)log, logsize);
if (hash) {
/* TPM 2 systems will generate the appropriate hash
themselves if we pass PE_COFF_IMAGE
themselves if we pass PE_COFF_IMAGE. In case that
fails we fall back to measuring without it.
*/
status = uefi_call_wrapper(tpm2->hash_log_extend_event,
5, tpm2, PE_COFF_IMAGE, buf,
(UINT64) size, event);
} else {
status = uefi_call_wrapper(tpm2->hash_log_extend_event,
5, tpm2, 0, buf,
(UINT64) size, event);
efi_status = tpm2->hash_log_extend_event(tpm2,
PE_COFF_IMAGE, buf, (UINT64) size, event);
}
if (!hash || EFI_ERROR(efi_status)) {
efi_status = tpm2->hash_log_extend_event(tpm2,
0, buf, (UINT64) size, event);
}
FreePool(event);
return status;
return efi_status;
} else if (tpm) {
TCG_PCR_EVENT *event;
UINT32 eventnum = 0;
EFI_PHYSICAL_ADDRESS lastevent;
status = LibLocateProtocol(&tpm_guid, (VOID **)&tpm);
if (status != EFI_SUCCESS)
efi_status = LibLocateProtocol(&EFI_TPM_GUID, (VOID **)&tpm);
if (EFI_ERROR(efi_status))
return EFI_SUCCESS;
if (!tpm_present(tpm))
@ -237,18 +233,15 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size,
hash rather than allowing the firmware to attempt
to calculate it */
CopyMem(event->digest, hash, sizeof(event->digest));
status = uefi_call_wrapper(tpm->log_extend_event, 7,
tpm, 0, 0, TPM_ALG_SHA,
event, &eventnum,
&lastevent);
efi_status = tpm->log_extend_event(tpm, 0, 0,
TPM_ALG_SHA, event, &eventnum, &lastevent);
} else {
status = uefi_call_wrapper(tpm->log_extend_event, 7,
tpm, buf, (UINT64)size,
TPM_ALG_SHA, event,
&eventnum, &lastevent);
efi_status = tpm->log_extend_event(tpm, buf,
(UINT64)size, TPM_ALG_SHA, event, &eventnum,
&lastevent);
}
FreePool(event);
return status;
return efi_status;
}
return EFI_SUCCESS;
@ -335,7 +328,7 @@ static EFI_STATUS tpm_record_data_measurement(CHAR16 *VarName, EFI_GUID VendorGu
EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData)
{
EFI_STATUS Status;
EFI_STATUS efi_status;
UINTN VarNameLength;
EFI_VARIABLE_DATA_TREE *VarLog;
UINT32 VarLogSize;
@ -365,14 +358,14 @@ EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarS
CopyMem ((CHAR16 *)VarLog->UnicodeName + VarNameLength, VarData,
VarSize);
Status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)(intptr_t)VarLog,
VarLogSize, 7, (CHAR8 *)VarLog, VarLogSize,
EV_EFI_VARIABLE_AUTHORITY, NULL);
efi_status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)(intptr_t)VarLog,
VarLogSize, 7, (CHAR8 *)VarLog, VarLogSize,
EV_EFI_VARIABLE_AUTHORITY, NULL);
FreePool(VarLog);
if (Status != EFI_SUCCESS)
return Status;
if (EFI_ERROR(efi_status))
return efi_status;
return tpm_record_data_measurement(VarName, VendorGuid, VarSize,
VarData);
@ -381,12 +374,12 @@ EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarS
EFI_STATUS
fallback_should_prefer_reset(void)
{
EFI_STATUS status;
EFI_STATUS efi_status;
efi_tpm_protocol_t *tpm;
efi_tpm2_protocol_t *tpm2;
status = tpm_locate_protocol(&tpm, &tpm2, NULL, NULL);
if (EFI_ERROR(status))
efi_status = tpm_locate_protocol(&tpm, &tpm2, NULL, NULL);
if (EFI_ERROR(efi_status))
return EFI_NOT_FOUND;
return EFI_SUCCESS;
}