mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-08-02 15:08:07 +00:00
New upstream version 15+1531942534.dd3230d
This commit is contained in:
parent
6215e920e7
commit
f892ac6608
2
.gitignore
vendored
2
.gitignore
vendored
@ -25,3 +25,5 @@ shim_cert.h
|
||||
*.srl.old
|
||||
*.tar.*
|
||||
version.c
|
||||
cov-int/
|
||||
scan-results/
|
||||
|
@ -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
17
.travis.yml
Normal 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
|
4
BUILDING
4
BUILDING
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
44
Cryptlib/Pem/CryptPemNull.c
Normal file
44
Cryptlib/Pem/CryptPemNull.c
Normal 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
48
Make.coverity
Normal 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
131
Make.defaults
Normal 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
3
Make.rules
Normal file
@ -0,0 +1,3 @@
|
||||
define get-config
|
||||
$(shell git config --local --get "shim.$(1)")
|
||||
endef
|
20
Make.scan-build
Normal file
20
Make.scan-build
Normal 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
164
Makefile
@ -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)
|
||||
|
||||
|
1249
MokManager.c
1249
MokManager.c
File diff suppressed because it is too large
Load Diff
@ -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
4
README
@ -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
|
||||
|
@ -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
23
TODO
@ -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
|
||||
|
@ -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;
|
||||
|
14
errlog.c
14
errlog.c
@ -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
|
||||
|
510
fallback.c
510
fallback.c
@ -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;
|
||||
}
|
||||
|
387
httpboot.c
387
httpboot.c
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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,
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
@ -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)
|
@ -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 */
|
||||
|
@ -1,8 +0,0 @@
|
||||
#define VERSION "1.3.4"
|
||||
|
||||
static void
|
||||
version(const char *progname)
|
||||
{
|
||||
printf("%s " VERSION "\n", progname);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
270
lib/console.c
270
lib/console.c
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
27
lib/guid.c
27
lib/guid.c
@ -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 } };
|
||||
|
@ -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;
|
||||
|
16
lib/shell.c
16
lib/shell.c
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
254
lib/variables.c
254
lib/variables.c
@ -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
136
model.c
Normal 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
334
mok.c
Normal 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
|
60
netboot.c
60
netboot.c
@ -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;
|
||||
}
|
||||
|
118
replacements.c
118
replacements.c
@ -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
|
||||
|
216
shim.h
216
shim.h
@ -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
141
tpm.c
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user