mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-05-29 15:33:12 +00:00
Port MokManager to Linux Foundation loader UI code
This is the first stage of porting the MokManager UI to the UI code used by the Linux Foundation UEFI loader.
This commit is contained in:
parent
2aa2ddd8a8
commit
17857eb8b5
9
Makefile
9
Makefile
@ -1,6 +1,6 @@
|
|||||||
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
||||||
|
|
||||||
SUBDIRS = Cryptlib
|
SUBDIRS = Cryptlib lib
|
||||||
|
|
||||||
LIB_PATH = /usr/lib64
|
LIB_PATH = /usr/lib64
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ fallback.so: $(FALLBACK_OBJS)
|
|||||||
|
|
||||||
MokManager.o: $(SOURCES)
|
MokManager.o: $(SOURCES)
|
||||||
|
|
||||||
MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a
|
MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a
|
||||||
$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS)
|
$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a
|
||||||
|
|
||||||
Cryptlib/libcryptlib.a:
|
Cryptlib/libcryptlib.a:
|
||||||
$(MAKE) -C Cryptlib
|
$(MAKE) -C Cryptlib
|
||||||
@ -87,6 +87,9 @@ Cryptlib/libcryptlib.a:
|
|||||||
Cryptlib/OpenSSL/libopenssl.a:
|
Cryptlib/OpenSSL/libopenssl.a:
|
||||||
$(MAKE) -C Cryptlib/OpenSSL
|
$(MAKE) -C Cryptlib/OpenSSL
|
||||||
|
|
||||||
|
lib/lib.a:
|
||||||
|
$(MAKE) -C lib
|
||||||
|
|
||||||
%.efi: %.so
|
%.efi: %.so
|
||||||
objcopy -j .text -j .sdata -j .data \
|
objcopy -j .text -j .sdata -j .data \
|
||||||
-j .dynamic -j .dynsym -j .rel \
|
-j .dynamic -j .dynsym -j .rel \
|
||||||
|
787
include/PeImage.h
Normal file
787
include/PeImage.h
Normal file
@ -0,0 +1,787 @@
|
|||||||
|
/** @file
|
||||||
|
EFI image format for PE32, PE32+ and TE. Please note some data structures are
|
||||||
|
different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and
|
||||||
|
EFI_IMAGE_NT_HEADERS64 is for PE32+.
|
||||||
|
|
||||||
|
This file is coded to the Visual Studio, Microsoft Portable Executable and
|
||||||
|
Common Object File Format Specification, Revision 8.0 - May 16, 2006.
|
||||||
|
This file also includes some definitions in PI Specification, Revision 1.0.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php.
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __PE_IMAGE_H__
|
||||||
|
#define __PE_IMAGE_H__
|
||||||
|
|
||||||
|
#include <wincert.h>
|
||||||
|
|
||||||
|
#define SIGNATURE_16(A, B) ((A) | (B << 8))
|
||||||
|
#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
|
||||||
|
#define SIGNATURE_64(A, B, C, D, E, F, G, H) \
|
||||||
|
(SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32))
|
||||||
|
|
||||||
|
#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1)))
|
||||||
|
#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment))))
|
||||||
|
|
||||||
|
//
|
||||||
|
// PE32+ Subsystem type for EFI images
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// PE32+ Machine type for EFI images
|
||||||
|
//
|
||||||
|
#define IMAGE_FILE_MACHINE_I386 0x014c
|
||||||
|
#define IMAGE_FILE_MACHINE_IA64 0x0200
|
||||||
|
#define IMAGE_FILE_MACHINE_EBC 0x0EBC
|
||||||
|
#define IMAGE_FILE_MACHINE_X64 0x8664
|
||||||
|
#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2
|
||||||
|
|
||||||
|
//
|
||||||
|
// EXE file formats
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z')
|
||||||
|
#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E')
|
||||||
|
#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E')
|
||||||
|
#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0')
|
||||||
|
|
||||||
|
///
|
||||||
|
/// PE images can start with an optional DOS header, so if an image is run
|
||||||
|
/// under DOS it can print an error message.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT16 e_magic; ///< Magic number.
|
||||||
|
UINT16 e_cblp; ///< Bytes on last page of file.
|
||||||
|
UINT16 e_cp; ///< Pages in file.
|
||||||
|
UINT16 e_crlc; ///< Relocations.
|
||||||
|
UINT16 e_cparhdr; ///< Size of header in paragraphs.
|
||||||
|
UINT16 e_minalloc; ///< Minimum extra paragraphs needed.
|
||||||
|
UINT16 e_maxalloc; ///< Maximum extra paragraphs needed.
|
||||||
|
UINT16 e_ss; ///< Initial (relative) SS value.
|
||||||
|
UINT16 e_sp; ///< Initial SP value.
|
||||||
|
UINT16 e_csum; ///< Checksum.
|
||||||
|
UINT16 e_ip; ///< Initial IP value.
|
||||||
|
UINT16 e_cs; ///< Initial (relative) CS value.
|
||||||
|
UINT16 e_lfarlc; ///< File address of relocation table.
|
||||||
|
UINT16 e_ovno; ///< Overlay number.
|
||||||
|
UINT16 e_res[4]; ///< Reserved words.
|
||||||
|
UINT16 e_oemid; ///< OEM identifier (for e_oeminfo).
|
||||||
|
UINT16 e_oeminfo; ///< OEM information; e_oemid specific.
|
||||||
|
UINT16 e_res2[10]; ///< Reserved words.
|
||||||
|
UINT32 e_lfanew; ///< File address of new exe header.
|
||||||
|
} EFI_IMAGE_DOS_HEADER;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// COFF File Header (Object and Image).
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Machine;
|
||||||
|
UINT16 NumberOfSections;
|
||||||
|
UINT32 TimeDateStamp;
|
||||||
|
UINT32 PointerToSymbolTable;
|
||||||
|
UINT32 NumberOfSymbols;
|
||||||
|
UINT16 SizeOfOptionalHeader;
|
||||||
|
UINT16 Characteristics;
|
||||||
|
} EFI_IMAGE_FILE_HEADER;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of EFI_IMAGE_FILE_HEADER.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_FILE_HEADER 20
|
||||||
|
|
||||||
|
//
|
||||||
|
// Characteristics
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_FILE_RELOCS_STRIPPED (1 << 0) ///< 0x0001 Relocation info stripped from file.
|
||||||
|
#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE (1 << 1) ///< 0x0002 File is executable (i.e. no unresolved externel references).
|
||||||
|
#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED (1 << 2) ///< 0x0004 Line nunbers stripped from file.
|
||||||
|
#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED (1 << 3) ///< 0x0008 Local symbols stripped from file.
|
||||||
|
#define EFI_IMAGE_FILE_BYTES_REVERSED_LO (1 << 7) ///< 0x0080 Bytes of machine word are reversed.
|
||||||
|
#define EFI_IMAGE_FILE_32BIT_MACHINE (1 << 8) ///< 0x0100 32 bit word machine.
|
||||||
|
#define EFI_IMAGE_FILE_DEBUG_STRIPPED (1 << 9) ///< 0x0200 Debugging info stripped from file in .DBG file.
|
||||||
|
#define EFI_IMAGE_FILE_SYSTEM (1 << 12) ///< 0x1000 System File.
|
||||||
|
#define EFI_IMAGE_FILE_DLL (1 << 13) ///< 0x2000 File is a DLL.
|
||||||
|
#define EFI_IMAGE_FILE_BYTES_REVERSED_HI (1 << 15) ///< 0x8000 Bytes of machine word are reversed.
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Header Data Directories.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 VirtualAddress;
|
||||||
|
UINT32 Size;
|
||||||
|
} EFI_IMAGE_DATA_DIRECTORY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Directory Entries
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9
|
||||||
|
#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
|
||||||
|
|
||||||
|
#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @attention
|
||||||
|
/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and
|
||||||
|
/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary
|
||||||
|
/// after NT additional fields.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Optional Header Standard Fields for PE32.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// Standard fields.
|
||||||
|
///
|
||||||
|
UINT16 Magic;
|
||||||
|
UINT8 MajorLinkerVersion;
|
||||||
|
UINT8 MinorLinkerVersion;
|
||||||
|
UINT32 SizeOfCode;
|
||||||
|
UINT32 SizeOfInitializedData;
|
||||||
|
UINT32 SizeOfUninitializedData;
|
||||||
|
UINT32 AddressOfEntryPoint;
|
||||||
|
UINT32 BaseOfCode;
|
||||||
|
UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+.
|
||||||
|
///
|
||||||
|
/// Optional Header Windows-Specific Fields.
|
||||||
|
///
|
||||||
|
UINT32 ImageBase;
|
||||||
|
UINT32 SectionAlignment;
|
||||||
|
UINT32 FileAlignment;
|
||||||
|
UINT16 MajorOperatingSystemVersion;
|
||||||
|
UINT16 MinorOperatingSystemVersion;
|
||||||
|
UINT16 MajorImageVersion;
|
||||||
|
UINT16 MinorImageVersion;
|
||||||
|
UINT16 MajorSubsystemVersion;
|
||||||
|
UINT16 MinorSubsystemVersion;
|
||||||
|
UINT32 Win32VersionValue;
|
||||||
|
UINT32 SizeOfImage;
|
||||||
|
UINT32 SizeOfHeaders;
|
||||||
|
UINT32 CheckSum;
|
||||||
|
UINT16 Subsystem;
|
||||||
|
UINT16 DllCharacteristics;
|
||||||
|
UINT32 SizeOfStackReserve;
|
||||||
|
UINT32 SizeOfStackCommit;
|
||||||
|
UINT32 SizeOfHeapReserve;
|
||||||
|
UINT32 SizeOfHeapCommit;
|
||||||
|
UINT32 LoaderFlags;
|
||||||
|
UINT32 NumberOfRvaAndSizes;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
|
||||||
|
} EFI_IMAGE_OPTIONAL_HEADER32;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @attention
|
||||||
|
/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and
|
||||||
|
/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary
|
||||||
|
/// after NT additional fields.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Optional Header Standard Fields for PE32+.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// Standard fields.
|
||||||
|
///
|
||||||
|
UINT16 Magic;
|
||||||
|
UINT8 MajorLinkerVersion;
|
||||||
|
UINT8 MinorLinkerVersion;
|
||||||
|
UINT32 SizeOfCode;
|
||||||
|
UINT32 SizeOfInitializedData;
|
||||||
|
UINT32 SizeOfUninitializedData;
|
||||||
|
UINT32 AddressOfEntryPoint;
|
||||||
|
UINT32 BaseOfCode;
|
||||||
|
///
|
||||||
|
/// Optional Header Windows-Specific Fields.
|
||||||
|
///
|
||||||
|
UINT64 ImageBase;
|
||||||
|
UINT32 SectionAlignment;
|
||||||
|
UINT32 FileAlignment;
|
||||||
|
UINT16 MajorOperatingSystemVersion;
|
||||||
|
UINT16 MinorOperatingSystemVersion;
|
||||||
|
UINT16 MajorImageVersion;
|
||||||
|
UINT16 MinorImageVersion;
|
||||||
|
UINT16 MajorSubsystemVersion;
|
||||||
|
UINT16 MinorSubsystemVersion;
|
||||||
|
UINT32 Win32VersionValue;
|
||||||
|
UINT32 SizeOfImage;
|
||||||
|
UINT32 SizeOfHeaders;
|
||||||
|
UINT32 CheckSum;
|
||||||
|
UINT16 Subsystem;
|
||||||
|
UINT16 DllCharacteristics;
|
||||||
|
UINT64 SizeOfStackReserve;
|
||||||
|
UINT64 SizeOfStackCommit;
|
||||||
|
UINT64 SizeOfHeapReserve;
|
||||||
|
UINT64 SizeOfHeapCommit;
|
||||||
|
UINT32 LoaderFlags;
|
||||||
|
UINT32 NumberOfRvaAndSizes;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES];
|
||||||
|
} EFI_IMAGE_OPTIONAL_HEADER64;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @attention
|
||||||
|
/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
EFI_IMAGE_FILE_HEADER FileHeader;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader;
|
||||||
|
} EFI_IMAGE_NT_HEADERS32;
|
||||||
|
|
||||||
|
#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32)
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @attention
|
||||||
|
/// EFI_IMAGE_HEADERS64 is for use ONLY by tools.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
EFI_IMAGE_FILE_HEADER FileHeader;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader;
|
||||||
|
} EFI_IMAGE_NT_HEADERS64;
|
||||||
|
|
||||||
|
#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Other Windows Subsystem Values
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_NATIVE 1
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5
|
||||||
|
#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Length of ShortName.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_SHORT_NAME 8
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Section Table. This table immediately follows the optional header.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME];
|
||||||
|
union {
|
||||||
|
UINT32 PhysicalAddress;
|
||||||
|
UINT32 VirtualSize;
|
||||||
|
} Misc;
|
||||||
|
UINT32 VirtualAddress;
|
||||||
|
UINT32 SizeOfRawData;
|
||||||
|
UINT32 PointerToRawData;
|
||||||
|
UINT32 PointerToRelocations;
|
||||||
|
UINT32 PointerToLinenumbers;
|
||||||
|
UINT16 NumberOfRelocations;
|
||||||
|
UINT16 NumberOfLinenumbers;
|
||||||
|
UINT32 Characteristics;
|
||||||
|
} EFI_IMAGE_SECTION_HEADER;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of EFI_IMAGE_SECTION_HEADER.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40
|
||||||
|
|
||||||
|
//
|
||||||
|
// Section Flags Values
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved.
|
||||||
|
#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020
|
||||||
|
#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040
|
||||||
|
#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080
|
||||||
|
|
||||||
|
#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved.
|
||||||
|
#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information.
|
||||||
|
#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image.
|
||||||
|
#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000
|
||||||
|
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000
|
||||||
|
#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000
|
||||||
|
|
||||||
|
#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000
|
||||||
|
#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000
|
||||||
|
#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000
|
||||||
|
#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000
|
||||||
|
#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000
|
||||||
|
#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000
|
||||||
|
#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of a Symbol Table Record.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_SYMBOL 18
|
||||||
|
|
||||||
|
//
|
||||||
|
// Symbols have a section number of the section in which they are
|
||||||
|
// defined. Otherwise, section numbers have the following meanings:
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common.
|
||||||
|
#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value.
|
||||||
|
#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Symbol Type (fundamental) values.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type.
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type.
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character.
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer.
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_INT 4
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_LONG 5
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_FLOAT 6
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_DOUBLE 7
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_STRUCT 8
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_UNION 9
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration.
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration.
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_BYTE 12
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_WORD 13
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_UINT 14
|
||||||
|
#define EFI_IMAGE_SYM_TYPE_DWORD 15
|
||||||
|
|
||||||
|
//
|
||||||
|
// Symbol Type (derived) values.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type.
|
||||||
|
#define EFI_IMAGE_SYM_DTYPE_POINTER 1
|
||||||
|
#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2
|
||||||
|
#define EFI_IMAGE_SYM_DTYPE_ARRAY 3
|
||||||
|
|
||||||
|
//
|
||||||
|
// Storage classes.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1)
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_NULL 0
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_STATIC 3
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_REGISTER 4
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_LABEL 6
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_BLOCK 100
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_FUNCTION 101
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_FILE 103
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_SECTION 104
|
||||||
|
#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105
|
||||||
|
|
||||||
|
//
|
||||||
|
// type packing constants
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_N_BTMASK 017
|
||||||
|
#define EFI_IMAGE_N_TMASK 060
|
||||||
|
#define EFI_IMAGE_N_TMASK1 0300
|
||||||
|
#define EFI_IMAGE_N_TMASK2 0360
|
||||||
|
#define EFI_IMAGE_N_BTSHFT 4
|
||||||
|
#define EFI_IMAGE_N_TSHIFT 2
|
||||||
|
|
||||||
|
//
|
||||||
|
// Communal selection types.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1
|
||||||
|
#define EFI_IMAGE_COMDAT_SELECT_ANY 2
|
||||||
|
#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3
|
||||||
|
#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4
|
||||||
|
#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5
|
||||||
|
|
||||||
|
//
|
||||||
|
// the following values only be referred in PeCoff, not defined in PECOFF.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1
|
||||||
|
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2
|
||||||
|
#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Relocation format.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 VirtualAddress;
|
||||||
|
UINT32 SymbolTableIndex;
|
||||||
|
UINT16 Type;
|
||||||
|
} EFI_IMAGE_RELOCATION;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of EFI_IMAGE_RELOCATION
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_RELOCATION 10
|
||||||
|
|
||||||
|
//
|
||||||
|
// I386 relocation types.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary.
|
||||||
|
#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address.
|
||||||
|
#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address.
|
||||||
|
#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address.
|
||||||
|
#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included.
|
||||||
|
#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address.
|
||||||
|
#define EFI_IMAGE_REL_I386_SECTION 0x000A
|
||||||
|
#define EFI_IMAGE_REL_I386_SECREL 0x000B
|
||||||
|
#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address.
|
||||||
|
|
||||||
|
//
|
||||||
|
// x64 processor relocation types.
|
||||||
|
//
|
||||||
|
#define IMAGE_REL_AMD64_ABSOLUTE 0x0000
|
||||||
|
#define IMAGE_REL_AMD64_ADDR64 0x0001
|
||||||
|
#define IMAGE_REL_AMD64_ADDR32 0x0002
|
||||||
|
#define IMAGE_REL_AMD64_ADDR32NB 0x0003
|
||||||
|
#define IMAGE_REL_AMD64_REL32 0x0004
|
||||||
|
#define IMAGE_REL_AMD64_REL32_1 0x0005
|
||||||
|
#define IMAGE_REL_AMD64_REL32_2 0x0006
|
||||||
|
#define IMAGE_REL_AMD64_REL32_3 0x0007
|
||||||
|
#define IMAGE_REL_AMD64_REL32_4 0x0008
|
||||||
|
#define IMAGE_REL_AMD64_REL32_5 0x0009
|
||||||
|
#define IMAGE_REL_AMD64_SECTION 0x000A
|
||||||
|
#define IMAGE_REL_AMD64_SECREL 0x000B
|
||||||
|
#define IMAGE_REL_AMD64_SECREL7 0x000C
|
||||||
|
#define IMAGE_REL_AMD64_TOKEN 0x000D
|
||||||
|
#define IMAGE_REL_AMD64_SREL32 0x000E
|
||||||
|
#define IMAGE_REL_AMD64_PAIR 0x000F
|
||||||
|
#define IMAGE_REL_AMD64_SSPAN32 0x0010
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Based relocation format.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 VirtualAddress;
|
||||||
|
UINT32 SizeOfBlock;
|
||||||
|
} EFI_IMAGE_BASE_RELOCATION;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of EFI_IMAGE_BASE_RELOCATION.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8
|
||||||
|
|
||||||
|
//
|
||||||
|
// Based relocation types.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_REL_BASED_ABSOLUTE 0
|
||||||
|
#define EFI_IMAGE_REL_BASED_HIGH 1
|
||||||
|
#define EFI_IMAGE_REL_BASED_LOW 2
|
||||||
|
#define EFI_IMAGE_REL_BASED_HIGHLOW 3
|
||||||
|
#define EFI_IMAGE_REL_BASED_HIGHADJ 4
|
||||||
|
#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5
|
||||||
|
#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5
|
||||||
|
#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7
|
||||||
|
#define EFI_IMAGE_REL_BASED_IA64_IMM64 9
|
||||||
|
#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9
|
||||||
|
#define EFI_IMAGE_REL_BASED_DIR64 10
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Line number format.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0.
|
||||||
|
UINT32 VirtualAddress; ///< Virtual address of line number.
|
||||||
|
} Type;
|
||||||
|
UINT16 Linenumber; ///< Line number.
|
||||||
|
} EFI_IMAGE_LINENUMBER;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of EFI_IMAGE_LINENUMBER.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_LINENUMBER 6
|
||||||
|
|
||||||
|
//
|
||||||
|
// Archive format.
|
||||||
|
//
|
||||||
|
#define EFI_IMAGE_ARCHIVE_START_SIZE 8
|
||||||
|
#define EFI_IMAGE_ARCHIVE_START "!<arch>\n"
|
||||||
|
#define EFI_IMAGE_ARCHIVE_END "`\n"
|
||||||
|
#define EFI_IMAGE_ARCHIVE_PAD "\n"
|
||||||
|
#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ "
|
||||||
|
#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// "
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Archive Member Headers
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Name[16]; ///< File member name - `/' terminated.
|
||||||
|
UINT8 Date[12]; ///< File member date - decimal.
|
||||||
|
UINT8 UserID[6]; ///< File member user id - decimal.
|
||||||
|
UINT8 GroupID[6]; ///< File member group id - decimal.
|
||||||
|
UINT8 Mode[8]; ///< File member mode - octal.
|
||||||
|
UINT8 Size[10]; ///< File member size - decimal.
|
||||||
|
UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A).
|
||||||
|
} EFI_IMAGE_ARCHIVE_MEMBER_HEADER;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER.
|
||||||
|
///
|
||||||
|
#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// DLL Support
|
||||||
|
//
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Export Directory Table.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Characteristics;
|
||||||
|
UINT32 TimeDateStamp;
|
||||||
|
UINT16 MajorVersion;
|
||||||
|
UINT16 MinorVersion;
|
||||||
|
UINT32 Name;
|
||||||
|
UINT32 Base;
|
||||||
|
UINT32 NumberOfFunctions;
|
||||||
|
UINT32 NumberOfNames;
|
||||||
|
UINT32 AddressOfFunctions;
|
||||||
|
UINT32 AddressOfNames;
|
||||||
|
UINT32 AddressOfNameOrdinals;
|
||||||
|
} EFI_IMAGE_EXPORT_DIRECTORY;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Hint/Name Table.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Hint;
|
||||||
|
UINT8 Name[1];
|
||||||
|
} EFI_IMAGE_IMPORT_BY_NAME;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Import Address Table RVA (Thunk Table).
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
UINT32 Function;
|
||||||
|
UINT32 Ordinal;
|
||||||
|
EFI_IMAGE_IMPORT_BY_NAME *AddressOfData;
|
||||||
|
} u1;
|
||||||
|
} EFI_IMAGE_THUNK_DATA;
|
||||||
|
|
||||||
|
#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32.
|
||||||
|
#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0)
|
||||||
|
#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Import Directory Table
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Characteristics;
|
||||||
|
UINT32 TimeDateStamp;
|
||||||
|
UINT32 ForwarderChain;
|
||||||
|
UINT32 Name;
|
||||||
|
EFI_IMAGE_THUNK_DATA *FirstThunk;
|
||||||
|
} EFI_IMAGE_IMPORT_DESCRIPTOR;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Debug Directory Format.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Characteristics;
|
||||||
|
UINT32 TimeDateStamp;
|
||||||
|
UINT16 MajorVersion;
|
||||||
|
UINT16 MinorVersion;
|
||||||
|
UINT32 Type;
|
||||||
|
UINT32 SizeOfData;
|
||||||
|
UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base.
|
||||||
|
UINT32 FileOffset; ///< The file pointer to the debug data.
|
||||||
|
} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY;
|
||||||
|
|
||||||
|
#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information.
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Debug Data Structure defined in Microsoft C++.
|
||||||
|
///
|
||||||
|
#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0')
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature; ///< "NB10"
|
||||||
|
UINT32 Unknown;
|
||||||
|
UINT32 Unknown2;
|
||||||
|
UINT32 Unknown3;
|
||||||
|
//
|
||||||
|
// Filename of .PDB goes here
|
||||||
|
//
|
||||||
|
} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Debug Data Structure defined in Microsoft C++.
|
||||||
|
///
|
||||||
|
#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S')
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature; ///< "RSDS".
|
||||||
|
UINT32 Unknown;
|
||||||
|
UINT32 Unknown2;
|
||||||
|
UINT32 Unknown3;
|
||||||
|
UINT32 Unknown4;
|
||||||
|
UINT32 Unknown5;
|
||||||
|
//
|
||||||
|
// Filename of .PDB goes here
|
||||||
|
//
|
||||||
|
} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Debug Data Structure defined by Apple Mach-O to Coff utility.
|
||||||
|
///
|
||||||
|
#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C')
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature; ///< "MTOC".
|
||||||
|
EFI_GUID MachOUuid;
|
||||||
|
//
|
||||||
|
// Filename of .DLL (Mach-O with debug info) goes here
|
||||||
|
//
|
||||||
|
} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Resource format.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Characteristics;
|
||||||
|
UINT32 TimeDateStamp;
|
||||||
|
UINT16 MajorVersion;
|
||||||
|
UINT16 MinorVersion;
|
||||||
|
UINT16 NumberOfNamedEntries;
|
||||||
|
UINT16 NumberOfIdEntries;
|
||||||
|
//
|
||||||
|
// Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here.
|
||||||
|
//
|
||||||
|
} EFI_IMAGE_RESOURCE_DIRECTORY;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Resource directory entry format.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
UINT32 NameOffset:31;
|
||||||
|
UINT32 NameIsString:1;
|
||||||
|
} s;
|
||||||
|
UINT32 Id;
|
||||||
|
} u1;
|
||||||
|
union {
|
||||||
|
UINT32 OffsetToData;
|
||||||
|
struct {
|
||||||
|
UINT32 OffsetToDirectory:31;
|
||||||
|
UINT32 DataIsDirectory:1;
|
||||||
|
} s;
|
||||||
|
} u2;
|
||||||
|
} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Resource directory entry for string.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Length;
|
||||||
|
CHAR16 String[1];
|
||||||
|
} EFI_IMAGE_RESOURCE_DIRECTORY_STRING;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Resource directory entry for data array.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT32 OffsetToData;
|
||||||
|
UINT32 Size;
|
||||||
|
UINT32 CodePage;
|
||||||
|
UINT32 Reserved;
|
||||||
|
} EFI_IMAGE_RESOURCE_DATA_ENTRY;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Header format for TE images, defined in the PI Specification, 1.0.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT16 Signature; ///< The signature for TE format = "VZ".
|
||||||
|
UINT16 Machine; ///< From the original file header.
|
||||||
|
UINT8 NumberOfSections; ///< From the original file header.
|
||||||
|
UINT8 Subsystem; ///< From original optional header.
|
||||||
|
UINT16 StrippedSize; ///< Number of bytes we removed from the header.
|
||||||
|
UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header.
|
||||||
|
UINT32 BaseOfCode; ///< From original image -- required for ITP debug.
|
||||||
|
UINT64 ImageBase; ///< From original file header.
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory.
|
||||||
|
} EFI_TE_IMAGE_HEADER;
|
||||||
|
|
||||||
|
|
||||||
|
#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z')
|
||||||
|
|
||||||
|
//
|
||||||
|
// Data directory indexes in our TE image header
|
||||||
|
//
|
||||||
|
#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0
|
||||||
|
#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Union of PE32, PE32+, and TE headers.
|
||||||
|
///
|
||||||
|
typedef union {
|
||||||
|
EFI_IMAGE_NT_HEADERS32 Pe32;
|
||||||
|
EFI_IMAGE_NT_HEADERS64 Pe32Plus;
|
||||||
|
EFI_TE_IMAGE_HEADER Te;
|
||||||
|
} EFI_IMAGE_OPTIONAL_HEADER_UNION;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
EFI_IMAGE_NT_HEADERS32 *Pe32;
|
||||||
|
EFI_IMAGE_NT_HEADERS64 *Pe32Plus;
|
||||||
|
EFI_TE_IMAGE_HEADER *Te;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *Union;
|
||||||
|
} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WIN_CERTIFICATE Hdr;
|
||||||
|
UINT8 CertData[1];
|
||||||
|
} WIN_CERTIFICATE_EFI_PKCS;
|
||||||
|
|
||||||
|
#define SHA256_DIGEST_SIZE 32
|
||||||
|
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT64 ImageAddress;
|
||||||
|
UINT64 ImageSize;
|
||||||
|
UINT64 EntryPoint;
|
||||||
|
UINTN SizeOfHeaders;
|
||||||
|
UINT16 ImageType;
|
||||||
|
UINT16 NumberOfSections;
|
||||||
|
EFI_IMAGE_SECTION_HEADER *FirstSection;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY *RelocDir;
|
||||||
|
EFI_IMAGE_DATA_DIRECTORY *SecDir;
|
||||||
|
UINT64 NumberOfRvaAndSizes;
|
||||||
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr;
|
||||||
|
} PE_COFF_LOADER_IMAGE_CONTEXT;
|
||||||
|
|
||||||
|
#endif
|
68
include/configtable.h
Normal file
68
include/configtable.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* definitions straight from TianoCore */
|
||||||
|
|
||||||
|
typedef UINT32 EFI_IMAGE_EXECUTION_ACTION;
|
||||||
|
|
||||||
|
#define EFI_IMAGE_EXECUTION_AUTHENTICATION 0x00000007
|
||||||
|
#define EFI_IMAGE_EXECUTION_AUTH_UNTESTED 0x00000000
|
||||||
|
#define EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED 0x00000001
|
||||||
|
#define EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED 0x00000002
|
||||||
|
#define EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND 0x00000003
|
||||||
|
#define EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND 0x00000004
|
||||||
|
#define EFI_IMAGE_EXECUTION_POLICY_FAILED 0x00000005
|
||||||
|
#define EFI_IMAGE_EXECUTION_INITIALIZED 0x00000008
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// Describes the action taken by the firmware regarding this image.
|
||||||
|
///
|
||||||
|
EFI_IMAGE_EXECUTION_ACTION Action;
|
||||||
|
///
|
||||||
|
/// Size of all of the entire structure.
|
||||||
|
///
|
||||||
|
UINT32 InfoSize;
|
||||||
|
///
|
||||||
|
/// If this image was a UEFI device driver (for option ROM, for example) this is the
|
||||||
|
/// null-terminated, user-friendly name for the device. If the image was for an application,
|
||||||
|
/// then this is the name of the application. If this cannot be determined, then a simple
|
||||||
|
/// NULL character should be put in this position.
|
||||||
|
/// CHAR16 Name[];
|
||||||
|
///
|
||||||
|
|
||||||
|
///
|
||||||
|
/// For device drivers, this is the device path of the device for which this device driver
|
||||||
|
/// was intended. In some cases, the driver itself may be stored as part of the system
|
||||||
|
/// firmware, but this field should record the device's path, not the firmware path. For
|
||||||
|
/// applications, this is the device path of the application. If this cannot be determined,
|
||||||
|
/// a simple end-of-path device node should be put in this position.
|
||||||
|
/// EFI_DEVICE_PATH_PROTOCOL DevicePath;
|
||||||
|
///
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Zero or more image signatures. If the image contained no signatures,
|
||||||
|
/// then this field is empty.
|
||||||
|
///
|
||||||
|
///EFI_SIGNATURE_LIST Signature;
|
||||||
|
UINT8 Data[];
|
||||||
|
} EFI_IMAGE_EXECUTION_INFO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// Number of EFI_IMAGE_EXECUTION_INFO structures.
|
||||||
|
///
|
||||||
|
UINTN NumberOfImages;
|
||||||
|
///
|
||||||
|
/// Number of image instances of EFI_IMAGE_EXECUTION_INFO structures.
|
||||||
|
///
|
||||||
|
EFI_IMAGE_EXECUTION_INFO InformationInfo[];
|
||||||
|
} EFI_IMAGE_EXECUTION_INFO_TABLE;
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
configtable_get_table(EFI_GUID *guid);
|
||||||
|
EFI_IMAGE_EXECUTION_INFO_TABLE *
|
||||||
|
configtable_get_image_table(void);
|
||||||
|
EFI_IMAGE_EXECUTION_INFO *
|
||||||
|
configtable_find_image(const EFI_DEVICE_PATH *DevicePath);
|
||||||
|
int
|
||||||
|
configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath);
|
||||||
|
|
21
include/console.h
Normal file
21
include/console.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
EFI_INPUT_KEY
|
||||||
|
console_get_keystroke(void);
|
||||||
|
void
|
||||||
|
console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines);
|
||||||
|
void
|
||||||
|
console_print_box(CHAR16 *str_arr[], int highlight);
|
||||||
|
int
|
||||||
|
console_yes_no(CHAR16 *str_arr[]);
|
||||||
|
int
|
||||||
|
console_select(CHAR16 *title[], CHAR16* selectors[], int start);
|
||||||
|
void
|
||||||
|
console_errorbox(CHAR16 *err);
|
||||||
|
void
|
||||||
|
console_error(CHAR16 *err, EFI_STATUS);
|
||||||
|
void
|
||||||
|
console_alertbox(CHAR16 **title);
|
||||||
|
void
|
||||||
|
console_notify(CHAR16 *string);
|
||||||
|
void
|
||||||
|
console_reset(void);
|
||||||
|
#define NOSEL 0x7fffffff
|
222
include/efiauthenticated.h
Normal file
222
include/efiauthenticated.h
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
#ifndef _INC_EFIAUTHENTICATED_H
|
||||||
|
#define _INC_EFIAUTHENTICATED_H
|
||||||
|
#include <wincert.h>
|
||||||
|
//***********************************************************************
|
||||||
|
// 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];
|
||||||
|
} 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];
|
||||||
|
///
|
||||||
|
} EFI_SIGNATURE_LIST;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
//
|
||||||
|
// _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
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
EFI_GUID HashType;
|
||||||
|
UINT8 PublicKey[256];
|
||||||
|
UINT8 Signature[256];
|
||||||
|
} EFI_CERT_BLOCK_RSA_2048_SHA256;
|
||||||
|
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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];
|
||||||
|
} 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[];
|
||||||
|
///
|
||||||
|
} WIN_CERTIFICATE_EFI_PKCS1_15;
|
||||||
|
|
||||||
|
#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field))
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
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;
|
||||||
|
} 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().
|
||||||
|
///
|
||||||
|
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;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of AuthInfo prior to the data payload.
|
||||||
|
///
|
||||||
|
#define AUTHINFO_SIZE ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \
|
||||||
|
(OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \
|
||||||
|
sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256))
|
||||||
|
|
||||||
|
#define AUTHINFO2_SIZE(VarAuth2) ((OFFSET_OF (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)))
|
||||||
|
|
||||||
|
#endif
|
9
include/errors.h
Normal file
9
include/errors.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include <efierr.h>
|
||||||
|
|
||||||
|
#ifndef EFI_INCOMPATIBLE_VERSION
|
||||||
|
#define EFI_INCOMPATIBLE_VERSION EFIERR(25)
|
||||||
|
#endif
|
||||||
|
#ifndef EFI_SECURITY_VIOLATION
|
||||||
|
#define EFI_SECURITY_VIOLATION EFIERR(26)
|
||||||
|
#endif
|
||||||
|
|
5
include/execute.h
Normal file
5
include/execute.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
EFI_STATUS
|
||||||
|
generate_path(CHAR16* name, EFI_LOADED_IMAGE *li,
|
||||||
|
EFI_DEVICE_PATH **path, CHAR16 **PathName);
|
||||||
|
EFI_STATUS
|
||||||
|
execute(EFI_HANDLE image, CHAR16 *name);
|
18
include/guid.h
Normal file
18
include/guid.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#include <efi.h>
|
||||||
|
|
||||||
|
#ifndef BUILD_EFI
|
||||||
|
const char *guid_to_str(EFI_GUID *guid);
|
||||||
|
void str_to_guid(const char *str, EFI_GUID *guid);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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_CERT_SHA256_GUID;
|
||||||
|
extern EFI_GUID MOK_OWNER;
|
||||||
|
extern EFI_GUID SECURITY_PROTOCOL_GUID;
|
||||||
|
extern EFI_GUID SECURITY2_PROTOCOL_GUID;
|
6
include/security_policy.h
Normal file
6
include/security_policy.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
EFI_STATUS
|
||||||
|
security_policy_install(void);
|
||||||
|
EFI_STATUS
|
||||||
|
security_policy_uninstall(void);
|
||||||
|
void
|
||||||
|
security_protocol_set_hashes(unsigned char *esl, int len);
|
2
include/shell.h
Normal file
2
include/shell.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
EFI_STATUS
|
||||||
|
argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV);
|
21
include/simple_file.h
Normal file
21
include/simple_file.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
EFI_STATUS
|
||||||
|
simple_file_open (EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode);
|
||||||
|
EFI_STATUS
|
||||||
|
simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode);
|
||||||
|
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);
|
||||||
|
EFI_STATUS
|
||||||
|
simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
|
||||||
|
CHAR16 ***result, int *count, EFI_FILE_INFO **entries);
|
||||||
|
void
|
||||||
|
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);
|
59
include/variables.h
Normal file
59
include/variables.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include <efiauthenticated.h>
|
||||||
|
|
||||||
|
#include <sha256.h> /* for SHA256_DIGEST_SIZE */
|
||||||
|
|
||||||
|
#define certlist_for_each_certentry(cl, cl_init, s, s_init) \
|
||||||
|
for (cl = (EFI_SIGNATURE_LIST *)(cl_init), s = (s_init); \
|
||||||
|
s > 0 && s >= cl->SignatureListSize; \
|
||||||
|
s -= cl->SignatureListSize, \
|
||||||
|
cl = (EFI_SIGNATURE_LIST *) ((UINT8 *)cl + cl->SignatureListSize))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Warning: this assumes (cl)->SignatureHeaderSize is zero. It is for all
|
||||||
|
* the signatures we process (X509, RSA2048, SHA256)
|
||||||
|
*/
|
||||||
|
#define certentry_for_each_cert(c, cl) \
|
||||||
|
for (c = (EFI_SIGNATURE_DATA *)((UINT8 *) (cl) + sizeof(EFI_SIGNATURE_LIST) + (cl)->SignatureHeaderSize); \
|
||||||
|
(UINT8 *)c < ((UINT8 *)(cl)) + (cl)->SignatureListSize; \
|
||||||
|
c = (EFI_SIGNATURE_DATA *)((UINT8 *)c + (cl)->SignatureSize))
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
CreatePkX509SignatureList (
|
||||||
|
IN UINT8 *X509Data,
|
||||||
|
IN UINTN X509DataSize,
|
||||||
|
IN EFI_GUID owner,
|
||||||
|
OUT EFI_SIGNATURE_LIST **PkCert
|
||||||
|
);
|
||||||
|
EFI_STATUS
|
||||||
|
CreateTimeBasedPayload (
|
||||||
|
IN OUT UINTN *DataSize,
|
||||||
|
IN OUT UINT8 **Data
|
||||||
|
);
|
||||||
|
EFI_STATUS
|
||||||
|
SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, UINT32 options, int createtimebased);
|
||||||
|
EFI_STATUS
|
||||||
|
get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner);
|
||||||
|
EFI_STATUS
|
||||||
|
get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner,
|
||||||
|
UINT32 *attributes);
|
||||||
|
EFI_STATUS
|
||||||
|
find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen);
|
||||||
|
EFI_STATUS
|
||||||
|
find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen);
|
||||||
|
|
||||||
|
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
GetOSIndications(void);
|
||||||
|
EFI_STATUS
|
||||||
|
SETOSIndicationsAndReboot(UINT64 indications);
|
||||||
|
int
|
||||||
|
variable_is_secureboot(void);
|
||||||
|
int
|
||||||
|
variable_is_setupmode(void);
|
||||||
|
EFI_STATUS
|
||||||
|
variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
|
||||||
|
UINT8 hash[SHA256_DIGEST_SIZE]);
|
||||||
|
EFI_STATUS
|
||||||
|
variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
|
||||||
|
void **out, int *outlen);
|
8
include/version.h
Normal file
8
include/version.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#define VERSION "1.3.4"
|
||||||
|
|
||||||
|
static void
|
||||||
|
version(const char *progname)
|
||||||
|
{
|
||||||
|
printf("%s " VERSION "\n", progname);
|
||||||
|
}
|
||||||
|
|
33
include/wincert.h
Normal file
33
include/wincert.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef _INC_WINCERT_H
|
||||||
|
#define _INC_WINCERT_H
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The WIN_CERTIFICATE structure is part of the PE/COFF specification.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
///
|
||||||
|
/// The length of the entire certificate,
|
||||||
|
/// including the length of the header, in bytes.
|
||||||
|
///
|
||||||
|
UINT32 dwLength;
|
||||||
|
///
|
||||||
|
/// The revision level of the WIN_CERTIFICATE
|
||||||
|
/// structure. The current revision level is 0x0200.
|
||||||
|
///
|
||||||
|
UINT16 wRevision;
|
||||||
|
///
|
||||||
|
/// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI
|
||||||
|
/// certificate types. The UEFI specification reserves the range of
|
||||||
|
/// certificate type values from 0x0EF0 to 0x0EFF.
|
||||||
|
///
|
||||||
|
UINT16 wCertificateType;
|
||||||
|
///
|
||||||
|
/// The following is the actual certificate. The format of
|
||||||
|
/// the certificate depends on wCertificateType.
|
||||||
|
///
|
||||||
|
/// UINT8 bCertificate[ANYSIZE_ARRAY];
|
||||||
|
///
|
||||||
|
} WIN_CERTIFICATE;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
28
lib/Makefile
Normal file
28
lib/Makefile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
TARGET = lib.a
|
||||||
|
|
||||||
|
LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o
|
||||||
|
|
||||||
|
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
||||||
|
|
||||||
|
EFI_INCLUDE = /usr/include/efi
|
||||||
|
EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I../include
|
||||||
|
EFI_PATH = /usr/lib64/gnuefi
|
||||||
|
|
||||||
|
EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o
|
||||||
|
EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds
|
||||||
|
|
||||||
|
CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \
|
||||||
|
-fshort-wchar -Wall -mno-red-zone -DBUILD_EFI $(EFI_INCLUDES)
|
||||||
|
ifeq ($(ARCH),x86_64)
|
||||||
|
CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI
|
||||||
|
endif
|
||||||
|
|
||||||
|
lib.a: $(LIBFILES)
|
||||||
|
ar rcs lib.a $(LIBFILES)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f lib.a
|
||||||
|
rm -f $(LIBFILES)
|
||||||
|
|
144
lib/configtable.c
Normal file
144
lib/configtable.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*
|
||||||
|
* read some platform configuration tables
|
||||||
|
*/
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include <guid.h>
|
||||||
|
#include <configtable.h>
|
||||||
|
|
||||||
|
void *
|
||||||
|
configtable_get_table(EFI_GUID *guid)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ST->NumberOfTableEntries; i++) {
|
||||||
|
EFI_CONFIGURATION_TABLE *CT = &ST->ConfigurationTable[i];
|
||||||
|
|
||||||
|
if (CompareGuid(guid, &CT->VendorGuid) == 0) {
|
||||||
|
return CT->VendorTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_IMAGE_EXECUTION_INFO_TABLE *
|
||||||
|
configtable_get_image_table(void)
|
||||||
|
{
|
||||||
|
return configtable_get_table(&SIG_DB);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_IMAGE_EXECUTION_INFO *
|
||||||
|
configtable_find_image(const EFI_DEVICE_PATH *DevicePath)
|
||||||
|
{
|
||||||
|
EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table();
|
||||||
|
|
||||||
|
if (!t)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int entries = t->NumberOfImages;
|
||||||
|
EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < entries; i++) {
|
||||||
|
#ifdef DEBUG_CONFIG
|
||||||
|
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",
|
||||||
|
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",
|
||||||
|
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",
|
||||||
|
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",
|
||||||
|
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",
|
||||||
|
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",
|
||||||
|
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);
|
||||||
|
int skip = 0;
|
||||||
|
|
||||||
|
/* There's a bug in a lot of EFI platforms and they forget to
|
||||||
|
* put the name here. The only real way of detecting it is to
|
||||||
|
* look for either a UC16 NULL or ASCII as UC16 */
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp;
|
||||||
|
if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0
|
||||||
|
|| (((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) {
|
||||||
|
/* Parse error, table corrupt, bail */
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
if (Size > e->InfoSize) {
|
||||||
|
/* parse error; the platform obviously has a
|
||||||
|
* corrupted image table; bail */
|
||||||
|
Print(L"Image Execution Information table corrupt\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareMem(dp, DevicePath, Size) == 0) {
|
||||||
|
#ifdef DEBUG_CONFIG
|
||||||
|
Print(L"***FOUND\n");
|
||||||
|
console_get_keystroke();
|
||||||
|
#endif
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_CONFIG
|
||||||
|
Print(L"***NOT FOUND\n");
|
||||||
|
console_get_keystroke();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath)
|
||||||
|
{
|
||||||
|
EFI_IMAGE_EXECUTION_INFO *e = configtable_find_image(DevicePath);
|
||||||
|
|
||||||
|
/* Image may not be in DB if it gets executed successfully If it is,
|
||||||
|
* and EFI_IMAGE_EXECUTION_INITIALIZED is not set, then the image
|
||||||
|
* isn't authenticated. If there's no signature, usually
|
||||||
|
* EFI_IMAGE_EXECUTION_AUTH_UNTESTED is set, if the hash is in dbx,
|
||||||
|
* EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND is returned, and if the key is
|
||||||
|
* in dbx, EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED is returned*/
|
||||||
|
|
||||||
|
if (e && (e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND
|
||||||
|
|| 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");
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
402
lib/console.c
Normal file
402
lib/console.c
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*/
|
||||||
|
#include <efi/efi.h>
|
||||||
|
#include <efi/efilib.h>
|
||||||
|
|
||||||
|
#include <console.h>
|
||||||
|
#include <errors.h>
|
||||||
|
|
||||||
|
static int min(int a, int b)
|
||||||
|
{
|
||||||
|
if (a < b)
|
||||||
|
return a;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
count_lines(CHAR16 *str_arr[])
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (str_arr[i])
|
||||||
|
i++;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n/2; i++) {
|
||||||
|
dst[i] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_INPUT_KEY
|
||||||
|
console_get_keystroke(void)
|
||||||
|
{
|
||||||
|
EFI_INPUT_KEY key;
|
||||||
|
UINTN EventIndex;
|
||||||
|
|
||||||
|
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex);
|
||||||
|
uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key);
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
|
||||||
|
UINTN rows, cols;
|
||||||
|
CHAR16 *Line;
|
||||||
|
|
||||||
|
if (lines == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);
|
||||||
|
|
||||||
|
/* last row on screen is unusable without scrolling, so ignore it */
|
||||||
|
rows--;
|
||||||
|
|
||||||
|
if (size_rows < 0)
|
||||||
|
size_rows = rows + size_rows + 1;
|
||||||
|
if (size_cols < 0)
|
||||||
|
size_cols = cols + size_cols + 1;
|
||||||
|
|
||||||
|
if (start_col < 0)
|
||||||
|
start_col = (cols + start_col + 2)/2;
|
||||||
|
if (start_row < 0)
|
||||||
|
start_row = (rows + start_row + 2)/2;
|
||||||
|
if (start_col < 0)
|
||||||
|
start_col = 0;
|
||||||
|
if (start_row < 0)
|
||||||
|
start_row = 0;
|
||||||
|
|
||||||
|
if (start_col > cols || start_row > rows) {
|
||||||
|
Print(L"Starting Position (%d,%d) is off screen\n",
|
||||||
|
start_col, start_row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (size_cols + start_col > cols)
|
||||||
|
size_cols = cols - start_col;
|
||||||
|
if (size_rows + start_row > rows)
|
||||||
|
size_rows = rows - start_row;
|
||||||
|
|
||||||
|
if (lines > size_rows - 2)
|
||||||
|
lines = size_rows - 2;
|
||||||
|
|
||||||
|
Line = AllocatePool((size_cols+1)*sizeof(CHAR16));
|
||||||
|
if (!Line) {
|
||||||
|
Print(L"Failed Allocation\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int start;
|
||||||
|
if (offset == 0)
|
||||||
|
/* middle */
|
||||||
|
start = (size_rows - lines)/2 + start_row + offset;
|
||||||
|
else if (offset < 0)
|
||||||
|
/* from bottom */
|
||||||
|
start = start_row + size_rows - lines + offset - 1;
|
||||||
|
else
|
||||||
|
/* from top */
|
||||||
|
start = start_row + offset;
|
||||||
|
|
||||||
|
|
||||||
|
for (i = start_row + 1; i < size_rows + start_row - 1; i++) {
|
||||||
|
int line = i - start;
|
||||||
|
|
||||||
|
SetMem16 (Line, size_cols*2, L' ');
|
||||||
|
Line[0] = BOXDRAW_VERTICAL;
|
||||||
|
Line[size_cols - 1] = BOXDRAW_VERTICAL;
|
||||||
|
Line[size_cols] = L'\0';
|
||||||
|
if (line >= 0 && line < lines) {
|
||||||
|
CHAR16 *s = str_arr[line];
|
||||||
|
int len = StrLen(s);
|
||||||
|
int col = (size_cols - 2 - len)/2;
|
||||||
|
|
||||||
|
if (col < 0)
|
||||||
|
col = 0;
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (line >= 0 && line == highlight)
|
||||||
|
uefi_call_wrapper(co->SetAttribute, 2, 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);
|
||||||
|
|
||||||
|
FreePool (Line);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_print_box(CHAR16 *str_arr[], int highlight)
|
||||||
|
{
|
||||||
|
SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;
|
||||||
|
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
|
||||||
|
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);
|
||||||
|
|
||||||
|
console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0,
|
||||||
|
count_lines(str_arr));
|
||||||
|
|
||||||
|
console_get_keystroke();
|
||||||
|
|
||||||
|
uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
console_select(CHAR16 *title[], CHAR16* selectors[], int start)
|
||||||
|
{
|
||||||
|
SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;
|
||||||
|
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
|
||||||
|
EFI_INPUT_KEY k;
|
||||||
|
int selector;
|
||||||
|
int selector_lines = count_lines(selectors);
|
||||||
|
int selector_max_cols = 0;
|
||||||
|
int i, offs_col, offs_row, size_cols, size_rows, lines;
|
||||||
|
int selector_offset;
|
||||||
|
UINTN cols, rows;
|
||||||
|
|
||||||
|
uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows);
|
||||||
|
|
||||||
|
for (i = 0; i < selector_lines; i++) {
|
||||||
|
int len = StrLen(selectors[i]);
|
||||||
|
|
||||||
|
if (len > selector_max_cols)
|
||||||
|
selector_max_cols = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
if (start >= selector_lines)
|
||||||
|
start = selector_lines - 1;
|
||||||
|
|
||||||
|
offs_col = - selector_max_cols - 4;
|
||||||
|
size_cols = selector_max_cols + 4;
|
||||||
|
|
||||||
|
if (selector_lines > rows - 10) {
|
||||||
|
int title_lines = count_lines(title);
|
||||||
|
offs_row = title_lines + 1;
|
||||||
|
size_rows = rows - 3 - title_lines;
|
||||||
|
lines = size_rows - 2;
|
||||||
|
} else {
|
||||||
|
offs_row = - selector_lines - 4;
|
||||||
|
size_rows = selector_lines + 2;
|
||||||
|
lines = selector_lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start > lines) {
|
||||||
|
selector = lines;
|
||||||
|
selector_offset = start - lines;
|
||||||
|
} else {
|
||||||
|
selector = start;
|
||||||
|
selector_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title));
|
||||||
|
|
||||||
|
console_print_box_at(selectors, selector, offs_col, offs_row,
|
||||||
|
size_cols, size_rows, 0, lines);
|
||||||
|
|
||||||
|
do {
|
||||||
|
k = console_get_keystroke();
|
||||||
|
|
||||||
|
if (k.ScanCode == SCAN_ESC) {
|
||||||
|
selector = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k.ScanCode == SCAN_UP) {
|
||||||
|
if (selector > 0)
|
||||||
|
selector--;
|
||||||
|
else if (selector_offset > 0)
|
||||||
|
selector_offset--;
|
||||||
|
} else if (k.ScanCode == SCAN_DOWN) {
|
||||||
|
if (selector < lines - 1)
|
||||||
|
selector++;
|
||||||
|
else if (selector_offset < (selector_lines - lines))
|
||||||
|
selector_offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
console_print_box_at(&selectors[selector_offset], selector,
|
||||||
|
offs_col, offs_row,
|
||||||
|
size_cols, size_rows, 0, lines);
|
||||||
|
} while (!(k.ScanCode == SCAN_NULL
|
||||||
|
&& k.UnicodeChar == CHAR_CARRIAGE_RETURN));
|
||||||
|
|
||||||
|
uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (selector < 0)
|
||||||
|
/* ESC pressed */
|
||||||
|
return selector;
|
||||||
|
return selector + selector_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
console_yes_no(CHAR16 *str_arr[])
|
||||||
|
{
|
||||||
|
return console_select(str_arr, (CHAR16 *[]){ L"No", L"Yes", NULL }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_alertbox(CHAR16 **title)
|
||||||
|
{
|
||||||
|
console_select(title, (CHAR16 *[]){ L"OK", 0 }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_errorbox(CHAR16 *err)
|
||||||
|
{
|
||||||
|
CHAR16 **err_arr = (CHAR16 *[]){
|
||||||
|
L"ERROR",
|
||||||
|
L"",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
err_arr[2] = err;
|
||||||
|
|
||||||
|
console_alertbox(err_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_notify(CHAR16 *string)
|
||||||
|
{
|
||||||
|
CHAR16 **str_arr = (CHAR16 *[]){
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
|
||||||
|
str_arr[0] = string;
|
||||||
|
|
||||||
|
console_alertbox(str_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
||||||
|
|
||||||
|
/* Copy of gnu-efi-3.0 with the added secure boot strings */
|
||||||
|
static struct {
|
||||||
|
EFI_STATUS Code;
|
||||||
|
WCHAR *Desc;
|
||||||
|
} error_table[] = {
|
||||||
|
{ EFI_SUCCESS, L"Success"},
|
||||||
|
{ EFI_LOAD_ERROR, L"Load Error"},
|
||||||
|
{ EFI_INVALID_PARAMETER, L"Invalid Parameter"},
|
||||||
|
{ EFI_UNSUPPORTED, L"Unsupported"},
|
||||||
|
{ EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"},
|
||||||
|
{ EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"},
|
||||||
|
{ EFI_NOT_READY, L"Not Ready"},
|
||||||
|
{ EFI_DEVICE_ERROR, L"Device Error"},
|
||||||
|
{ EFI_WRITE_PROTECTED, L"Write Protected"},
|
||||||
|
{ EFI_OUT_OF_RESOURCES, L"Out of Resources"},
|
||||||
|
{ EFI_VOLUME_CORRUPTED, L"Volume Corrupt"},
|
||||||
|
{ EFI_VOLUME_FULL, L"Volume Full"},
|
||||||
|
{ EFI_NO_MEDIA, L"No Media"},
|
||||||
|
{ EFI_MEDIA_CHANGED, L"Media changed"},
|
||||||
|
{ EFI_NOT_FOUND, L"Not Found"},
|
||||||
|
{ EFI_ACCESS_DENIED, L"Access Denied"},
|
||||||
|
{ EFI_NO_RESPONSE, L"No Response"},
|
||||||
|
{ EFI_NO_MAPPING, L"No mapping"},
|
||||||
|
{ EFI_TIMEOUT, L"Time out"},
|
||||||
|
{ EFI_NOT_STARTED, L"Not started"},
|
||||||
|
{ EFI_ALREADY_STARTED, L"Already started"},
|
||||||
|
{ EFI_ABORTED, L"Aborted"},
|
||||||
|
{ EFI_ICMP_ERROR, L"ICMP Error"},
|
||||||
|
{ EFI_TFTP_ERROR, L"TFTP Error"},
|
||||||
|
{ EFI_PROTOCOL_ERROR, L"Protocol Error"},
|
||||||
|
{ EFI_INCOMPATIBLE_VERSION, L"Incompatible Version"},
|
||||||
|
{ EFI_SECURITY_VIOLATION, L"Security Violation"},
|
||||||
|
|
||||||
|
// warnings
|
||||||
|
{ EFI_WARN_UNKOWN_GLYPH, L"Warning Unknown Glyph"},
|
||||||
|
{ EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"},
|
||||||
|
{ EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"},
|
||||||
|
{ EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"},
|
||||||
|
{ 0, NULL}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
static CHAR16 *
|
||||||
|
err_string (
|
||||||
|
IN EFI_STATUS Status
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
for (Index = 0; error_table[Index].Desc; Index +=1) {
|
||||||
|
if (error_table[Index].Code == Status) {
|
||||||
|
return error_table[Index].Desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
console_error(CHAR16 *err, EFI_STATUS status)
|
||||||
|
{
|
||||||
|
CHAR16 **err_arr = (CHAR16 *[]){
|
||||||
|
L"ERROR",
|
||||||
|
L"",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
};
|
||||||
|
CHAR16 str[512];
|
||||||
|
|
||||||
|
SPrint(str, sizeof(str), L"%s: (%d) %s", err, status, err_string(status));
|
||||||
|
|
||||||
|
err_arr[2] = str;
|
||||||
|
|
||||||
|
console_alertbox(err_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_reset(void)
|
||||||
|
{
|
||||||
|
SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut;
|
||||||
|
|
||||||
|
uefi_call_wrapper(co->Reset, 2, co, TRUE);
|
||||||
|
/* set mode 0 - required to be 80x25 */
|
||||||
|
uefi_call_wrapper(co->SetMode, 2, co, 0);
|
||||||
|
uefi_call_wrapper(co->ClearScreen, 1, co);
|
||||||
|
}
|
127
lib/execute.c
Normal file
127
lib/execute.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*
|
||||||
|
* --
|
||||||
|
*
|
||||||
|
* generate_path is a cut and paste from
|
||||||
|
*
|
||||||
|
* git://github.com/mjg59/shim.git
|
||||||
|
*
|
||||||
|
* Code Copyright 2012 Red Hat, Inc <mjg@redhat.com>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include <guid.h>
|
||||||
|
#include <execute.h>
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName)
|
||||||
|
{
|
||||||
|
unsigned int pathlen;
|
||||||
|
EFI_STATUS efi_status = EFI_SUCCESS;
|
||||||
|
CHAR16 *devpathstr = DevicePathToStr(li->FilePath),
|
||||||
|
*found = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < StrLen(devpathstr); i++) {
|
||||||
|
if (devpathstr[i] == '/')
|
||||||
|
devpathstr[i] = '\\';
|
||||||
|
if (devpathstr[i] == '\\')
|
||||||
|
found = &devpathstr[i];
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
pathlen = 0;
|
||||||
|
} else {
|
||||||
|
while (*(found - 1) == '\\')
|
||||||
|
--found;
|
||||||
|
*found = '\0';
|
||||||
|
pathlen = StrLen(devpathstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name[0] != '\\')
|
||||||
|
pathlen++;
|
||||||
|
|
||||||
|
*PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16));
|
||||||
|
|
||||||
|
if (!*PathName) {
|
||||||
|
Print(L"Failed to allocate path buffer\n");
|
||||||
|
efi_status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
StrCpy(*PathName, devpathstr);
|
||||||
|
|
||||||
|
if (name[0] != '\\')
|
||||||
|
StrCat(*PathName, L"\\");
|
||||||
|
StrCat(*PathName, name);
|
||||||
|
|
||||||
|
*path = FileDevicePath(li->DeviceHandle, *PathName);
|
||||||
|
|
||||||
|
error:
|
||||||
|
FreePool(devpathstr);
|
||||||
|
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
execute(EFI_HANDLE image, CHAR16 *name)
|
||||||
|
{
|
||||||
|
EFI_STATUS status;
|
||||||
|
EFI_HANDLE h;
|
||||||
|
EFI_LOADED_IMAGE *li;
|
||||||
|
EFI_DEVICE_PATH *devpath;
|
||||||
|
CHAR16 *PathName;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
|
||||||
|
&IMAGE_PROTOCOL, &li);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
|
||||||
|
status = generate_path(name, li, &devpath, &PathName);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image,
|
||||||
|
devpath, NULL, 0, &h);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->StartImage, 3, h, NULL, NULL);
|
||||||
|
uefi_call_wrapper(BS->UnloadImage, 1, h);
|
||||||
|
|
||||||
|
out:
|
||||||
|
FreePool(PathName);
|
||||||
|
FreePool(devpath);
|
||||||
|
return status;
|
||||||
|
}
|
47
lib/guid.c
Normal file
47
lib/guid.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <guid.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef BUILD_EFI
|
||||||
|
/* EFI has %g for this, so it's only needed in platform c */
|
||||||
|
const char *guid_to_str(EFI_GUID *guid)
|
||||||
|
{
|
||||||
|
static char str[256];
|
||||||
|
|
||||||
|
sprintf(str, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
|
||||||
|
guid->Data1, guid->Data2, guid->Data3,
|
||||||
|
guid->Data4[0], guid->Data4[1], guid->Data4[2],
|
||||||
|
guid->Data4[3], guid->Data4[4], guid->Data4[5],
|
||||||
|
guid->Data4[6], guid->Data4[7]);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void str_to_guid(const char *str, EFI_GUID *guid)
|
||||||
|
{
|
||||||
|
sscanf(str, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
|
||||||
|
&guid->Data1, &guid->Data2, &guid->Data3,
|
||||||
|
guid->Data4, guid->Data4 + 1, guid->Data4 + 2,
|
||||||
|
guid->Data4 + 3, guid->Data4 + 4, guid->Data4 + 5,
|
||||||
|
guid->Data4 + 6, guid->Data4 + 7);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* all the necessary guids */
|
||||||
|
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_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 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 } };
|
391
lib/security_policy.c
Normal file
391
lib/security_policy.c
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*
|
||||||
|
* Install and remove a platform security2 override policy
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include <guid.h>
|
||||||
|
#include <sha256.h>
|
||||||
|
#include <variables.h>
|
||||||
|
#include <simple_file.h>
|
||||||
|
#include <errors.h>
|
||||||
|
|
||||||
|
#include <security_policy.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See the UEFI Platform Initialization manual (Vol2: DXE) for this
|
||||||
|
*/
|
||||||
|
struct _EFI_SECURITY2_PROTOCOL;
|
||||||
|
struct _EFI_SECURITY_PROTOCOL;
|
||||||
|
typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL;
|
||||||
|
typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL;
|
||||||
|
typedef EFI_DEVICE_PATH EFI_DEVICE_PATH_PROTOCOL;
|
||||||
|
|
||||||
|
typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) (
|
||||||
|
const EFI_SECURITY_PROTOCOL *This,
|
||||||
|
UINT32 AuthenticationStatus,
|
||||||
|
const EFI_DEVICE_PATH_PROTOCOL *File
|
||||||
|
);
|
||||||
|
typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) (
|
||||||
|
const EFI_SECURITY2_PROTOCOL *This,
|
||||||
|
const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
|
VOID *FileBuffer,
|
||||||
|
UINTN FileSize,
|
||||||
|
BOOLEAN BootPolicy
|
||||||
|
);
|
||||||
|
|
||||||
|
struct _EFI_SECURITY2_PROTOCOL {
|
||||||
|
EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _EFI_SECURITY_PROTOCOL {
|
||||||
|
EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static UINT8 *security_policy_esl = NULL;
|
||||||
|
static UINTN security_policy_esl_len;
|
||||||
|
|
||||||
|
static EFI_STATUS
|
||||||
|
security_policy_check_mok(void *data, UINTN len)
|
||||||
|
{
|
||||||
|
EFI_STATUS status;
|
||||||
|
UINT8 hash[SHA256_DIGEST_SIZE];
|
||||||
|
UINT32 attr;
|
||||||
|
UINT8 *VarData;
|
||||||
|
UINTN VarLen;
|
||||||
|
|
||||||
|
/* first check is MokSBState. If we're in insecure mode, boot
|
||||||
|
* anyway regardless of dbx contents */
|
||||||
|
status = get_variable_attr(L"MokSBState", &VarData, &VarLen,
|
||||||
|
MOK_OWNER, &attr);
|
||||||
|
if (status == EFI_SUCCESS) {
|
||||||
|
UINT8 MokSBState = VarData[0];
|
||||||
|
|
||||||
|
FreePool(VarData);
|
||||||
|
if ((attr & EFI_VARIABLE_RUNTIME_ACCESS) == 0
|
||||||
|
&& MokSBState)
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = sha256_get_pecoff_digest_mem(data, len, hash);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (find_in_variable_esl(L"dbx", SIG_DB, hash, SHA256_DIGEST_SIZE)
|
||||||
|
== EFI_SUCCESS)
|
||||||
|
/* MOK list cannot override dbx */
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
|
||||||
|
status = get_variable_attr(L"MokList", &VarData, &VarLen, MOK_OWNER,
|
||||||
|
&attr);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
goto check_tmplist;
|
||||||
|
|
||||||
|
FreePool(VarData);
|
||||||
|
|
||||||
|
if (attr & EFI_VARIABLE_RUNTIME_ACCESS)
|
||||||
|
goto check_tmplist;
|
||||||
|
|
||||||
|
if (find_in_variable_esl(L"MokList", MOK_OWNER, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS)
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
check_tmplist:
|
||||||
|
if (security_policy_esl
|
||||||
|
&& find_in_esl(security_policy_esl, security_policy_esl_len, hash,
|
||||||
|
SHA256_DIGEST_SIZE) == EFI_SUCCESS)
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL;
|
||||||
|
static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL;
|
||||||
|
|
||||||
|
static EFI_STATUS thunk_security_policy_authentication(
|
||||||
|
const EFI_SECURITY_PROTOCOL *This,
|
||||||
|
UINT32 AuthenticationStatus,
|
||||||
|
const EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||||
|
)
|
||||||
|
__attribute__((unused));
|
||||||
|
|
||||||
|
static EFI_STATUS thunk_security2_policy_authentication(
|
||||||
|
const EFI_SECURITY2_PROTOCOL *This,
|
||||||
|
const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
|
VOID *FileBuffer,
|
||||||
|
UINTN FileSize,
|
||||||
|
BOOLEAN BootPolicy
|
||||||
|
)
|
||||||
|
__attribute__((unused));
|
||||||
|
|
||||||
|
static __attribute__((used)) EFI_STATUS
|
||||||
|
security2_policy_authentication (
|
||||||
|
const EFI_SECURITY2_PROTOCOL *This,
|
||||||
|
const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
|
VOID *FileBuffer,
|
||||||
|
UINTN FileSize,
|
||||||
|
BOOLEAN BootPolicy
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS status, auth;
|
||||||
|
|
||||||
|
/* Chain original security policy */
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer,
|
||||||
|
FileSize, BootPolicy);
|
||||||
|
|
||||||
|
/* if OK, don't bother with MOK check */
|
||||||
|
if (status == EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
auth = security_policy_check_mok(FileBuffer, FileSize);
|
||||||
|
|
||||||
|
if (auth == EFI_SECURITY_VIOLATION || auth == EFI_ACCESS_DENIED)
|
||||||
|
/* return previous status, which is the correct one
|
||||||
|
* for the platform: may be either EFI_ACCESS_DENIED
|
||||||
|
* or EFI_SECURITY_VIOLATION */
|
||||||
|
return status;
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __attribute__((used)) EFI_STATUS
|
||||||
|
security_policy_authentication (
|
||||||
|
const EFI_SECURITY_PROTOCOL *This,
|
||||||
|
UINT32 AuthenticationStatus,
|
||||||
|
const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS status, fail_status;
|
||||||
|
EFI_DEVICE_PATH *DevPath
|
||||||
|
= DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst),
|
||||||
|
*OrigDevPath = DevPath;
|
||||||
|
EFI_HANDLE h;
|
||||||
|
EFI_FILE *f;
|
||||||
|
VOID *FileBuffer;
|
||||||
|
UINTN FileSize;
|
||||||
|
CHAR16* DevPathStr;
|
||||||
|
|
||||||
|
/* Chain original security policy */
|
||||||
|
status = uefi_call_wrapper(esfas, 3, 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)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* capture failure status: may be either EFI_ACCESS_DENIED or
|
||||||
|
* EFI_SECURITY_VIOLATION */
|
||||||
|
fail_status = status;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->LocateDevicePath, 3,
|
||||||
|
&SIMPLE_FS_PROTOCOL, &DevPath, &h);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
DevPathStr = DevicePathToStr(DevPath);
|
||||||
|
|
||||||
|
status = simple_file_open_by_handle(h, DevPathStr, &f,
|
||||||
|
EFI_FILE_MODE_READ);
|
||||||
|
FreePool(DevPathStr);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = simple_file_read_all(f, &FileSize, &FileBuffer);
|
||||||
|
simple_file_close(f);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
status = security_policy_check_mok(FileBuffer, FileSize);
|
||||||
|
FreePool(FileBuffer);
|
||||||
|
|
||||||
|
if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION)
|
||||||
|
/* return what the platform originally said */
|
||||||
|
status = fail_status;
|
||||||
|
out:
|
||||||
|
FreePool(OrigDevPath);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Nasty: ELF and EFI have different calling conventions. Here is the map for
|
||||||
|
* calling ELF -> EFI
|
||||||
|
*
|
||||||
|
* 1) rdi -> rcx (32 saved)
|
||||||
|
* 2) rsi -> rdx (32 saved)
|
||||||
|
* 3) rdx -> r8 ( 32 saved)
|
||||||
|
* 4) rcx -> r9 (32 saved)
|
||||||
|
* 5) r8 -> 32(%rsp) (48 saved)
|
||||||
|
* 6) r9 -> 40(%rsp) (48 saved)
|
||||||
|
* 7) pad+0(%rsp) -> 48(%rsp) (64 saved)
|
||||||
|
* 8) pad+8(%rsp) -> 56(%rsp) (64 saved)
|
||||||
|
* 9) pad+16(%rsp) -> 64(%rsp) (80 saved)
|
||||||
|
* 10) pad+24(%rsp) -> 72(%rsp) (80 saved)
|
||||||
|
* 11) pad+32(%rsp) -> 80(%rsp) (96 saved)
|
||||||
|
|
||||||
|
*
|
||||||
|
* So for a five argument callback, the map is ignore the first two arguments
|
||||||
|
* and then map (EFI -> ELF) assuming pad = 0.
|
||||||
|
*
|
||||||
|
* ARG4 -> ARG1
|
||||||
|
* ARG3 -> ARG2
|
||||||
|
* ARG5 -> ARG3
|
||||||
|
* ARG6 -> ARG4
|
||||||
|
* ARG11 -> ARG5
|
||||||
|
*
|
||||||
|
* Calling conventions also differ over volatile and preserved registers in
|
||||||
|
* MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile .
|
||||||
|
* In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling
|
||||||
|
* function and the called function is required to preserve their values.
|
||||||
|
*
|
||||||
|
* This means when accepting a function callback from MS -> ELF, we have to do
|
||||||
|
* separate preservation on %rdi, %rsi before swizzling the arguments and
|
||||||
|
* handing off to the ELF function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
asm (
|
||||||
|
".type security2_policy_authentication,@function\n"
|
||||||
|
"thunk_security2_policy_authentication:\n\t"
|
||||||
|
"mov 0x28(%rsp), %r10 # ARG5\n\t"
|
||||||
|
"push %rdi\n\t"
|
||||||
|
"push %rsi\n\t"
|
||||||
|
"mov %r10, %rdi\n\t"
|
||||||
|
"subq $8, %rsp # space for storing stack pad\n\t"
|
||||||
|
"mov $0x08, %rax\n\t"
|
||||||
|
"mov $0x10, %r10\n\t"
|
||||||
|
"and %rsp, %rax\n\t"
|
||||||
|
"cmovnz %rax, %r11\n\t"
|
||||||
|
"cmovz %r10, %r11\n\t"
|
||||||
|
"subq %r11, %rsp\n\t"
|
||||||
|
"addq $8, %r11\n\t"
|
||||||
|
"mov %r11, (%rsp)\n\t"
|
||||||
|
"# five argument swizzle\n\t"
|
||||||
|
"mov %rdi, %r10\n\t"
|
||||||
|
"mov %rcx, %rdi\n\t"
|
||||||
|
"mov %rdx, %rsi\n\t"
|
||||||
|
"mov %r8, %rdx\n\t"
|
||||||
|
"mov %r9, %rcx\n\t"
|
||||||
|
"mov %r10, %r8\n\t"
|
||||||
|
"callq security2_policy_authentication@PLT\n\t"
|
||||||
|
"mov (%rsp), %r11\n\t"
|
||||||
|
"addq %r11, %rsp\n\t"
|
||||||
|
"pop %rsi\n\t"
|
||||||
|
"pop %rdi\n\t"
|
||||||
|
"ret\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
asm (
|
||||||
|
".type security_policy_authentication,@function\n"
|
||||||
|
"thunk_security_policy_authentication:\n\t"
|
||||||
|
"push %rdi\n\t"
|
||||||
|
"push %rsi\n\t"
|
||||||
|
"subq $8, %rsp # space for storing stack pad\n\t"
|
||||||
|
"mov $0x08, %rax\n\t"
|
||||||
|
"mov $0x10, %r10\n\t"
|
||||||
|
"and %rsp, %rax\n\t"
|
||||||
|
"cmovnz %rax, %r11\n\t"
|
||||||
|
"cmovz %r10, %r11\n\t"
|
||||||
|
"subq %r11, %rsp\n\t"
|
||||||
|
"addq $8, %r11\n\t"
|
||||||
|
"mov %r11, (%rsp)\n\t"
|
||||||
|
"# three argument swizzle\n\t"
|
||||||
|
"mov %rcx, %rdi\n\t"
|
||||||
|
"mov %rdx, %rsi\n\t"
|
||||||
|
"mov %r8, %rdx\n\t"
|
||||||
|
"callq security_policy_authentication@PLT\n\t"
|
||||||
|
"mov (%rsp), %r11\n\t"
|
||||||
|
"addq %r11, %rsp\n\t"
|
||||||
|
"pop %rsi\n\t"
|
||||||
|
"pop %rdi\n\t"
|
||||||
|
"ret\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
security_policy_install(void)
|
||||||
|
{
|
||||||
|
EFI_SECURITY_PROTOCOL *security_protocol;
|
||||||
|
EFI_SECURITY2_PROTOCOL *security2_protocol = NULL;
|
||||||
|
EFI_STATUS status;
|
||||||
|
|
||||||
|
if (esfas)
|
||||||
|
/* Already Installed */
|
||||||
|
return EFI_ALREADY_STARTED;
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
&security2_protocol);
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->LocateProtocol, 3,
|
||||||
|
&SECURITY_PROTOCOL_GUID, NULL,
|
||||||
|
&security_protocol);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
/* This one is mandatory, so there's a serious problem */
|
||||||
|
return status;
|
||||||
|
|
||||||
|
if (security2_protocol) {
|
||||||
|
es2fa = security2_protocol->FileAuthentication;
|
||||||
|
security2_protocol->FileAuthentication =
|
||||||
|
thunk_security2_policy_authentication;
|
||||||
|
}
|
||||||
|
|
||||||
|
esfas = security_protocol->FileAuthenticationState;
|
||||||
|
security_protocol->FileAuthenticationState =
|
||||||
|
thunk_security_policy_authentication;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
security_policy_uninstall(void)
|
||||||
|
{
|
||||||
|
EFI_STATUS status;
|
||||||
|
|
||||||
|
if (esfas) {
|
||||||
|
EFI_SECURITY_PROTOCOL *security_protocol;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->LocateProtocol, 3,
|
||||||
|
&SECURITY_PROTOCOL_GUID, NULL,
|
||||||
|
&security_protocol);
|
||||||
|
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
security_protocol->FileAuthenticationState = esfas;
|
||||||
|
esfas = NULL;
|
||||||
|
} else {
|
||||||
|
/* nothing installed */
|
||||||
|
return EFI_NOT_STARTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (es2fa) {
|
||||||
|
EFI_SECURITY2_PROTOCOL *security2_protocol;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->LocateProtocol, 3,
|
||||||
|
&SECURITY2_PROTOCOL_GUID, NULL,
|
||||||
|
&security2_protocol);
|
||||||
|
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
security2_protocol->FileAuthentication = es2fa;
|
||||||
|
es2fa = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
security_protocol_set_hashes(unsigned char *esl, int len)
|
||||||
|
{
|
||||||
|
security_policy_esl = esl;
|
||||||
|
security_policy_esl_len = len;
|
||||||
|
}
|
57
lib/shell.c
Normal file
57
lib/shell.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*
|
||||||
|
* misc shell helper functions
|
||||||
|
*/
|
||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include <shell.h>
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV)
|
||||||
|
{
|
||||||
|
int i, count = 1;
|
||||||
|
EFI_STATUS 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < info->LoadOptionsSize; i += 2) {
|
||||||
|
CHAR16 *c = (CHAR16 *)(info->LoadOptions + i);
|
||||||
|
if (*c == L' ' && *(c+1) != '\0') {
|
||||||
|
(*argc)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(*argc)++; /* we counted spaces, so add one for initial */
|
||||||
|
|
||||||
|
*ARGV = AllocatePool(*argc * sizeof(*ARGV));
|
||||||
|
if (!*ARGV) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
(*ARGV)[0] = (CHAR16 *)info->LoadOptions;
|
||||||
|
for (i = 0; i < info->LoadOptionsSize; i += 2) {
|
||||||
|
CHAR16 *c = (CHAR16 *)(info->LoadOptions + i);
|
||||||
|
if (*c == L' ') {
|
||||||
|
*c = L'\0';
|
||||||
|
if (*(c + 1) == '\0')
|
||||||
|
/* strip trailing space */
|
||||||
|
break;
|
||||||
|
start = c + 1;
|
||||||
|
(*ARGV)[count++] = start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
501
lib/simple_file.c
Normal file
501
lib/simple_file.c
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode)
|
||||||
|
{
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
EFI_FILE_IO_INTERFACE *drive;
|
||||||
|
EFI_FILE *root;
|
||||||
|
|
||||||
|
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
|
||||||
|
&SIMPLE_FS_PROTOCOL, &drive);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
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);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
efi_status = uefi_call_wrapper(root->Open, 5, root, file, name,
|
||||||
|
mode, 0);
|
||||||
|
|
||||||
|
error:
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode)
|
||||||
|
{
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
EFI_HANDLE device;
|
||||||
|
EFI_LOADED_IMAGE *li;
|
||||||
|
EFI_DEVICE_PATH *loadpath = NULL;
|
||||||
|
CHAR16 *PathName = NULL;
|
||||||
|
|
||||||
|
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image,
|
||||||
|
&IMAGE_PROTOCOL, &li);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS)
|
||||||
|
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);
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
device = li->DeviceHandle;
|
||||||
|
|
||||||
|
efi_status = simple_file_open_by_handle(device, PathName, file, mode);
|
||||||
|
|
||||||
|
FreePool(PathName);
|
||||||
|
FreePool(loadpath);
|
||||||
|
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((fi->Attribute & EFI_FILE_DIRECTORY) == 0) {
|
||||||
|
Print(L"Not a directory %s\n", name);
|
||||||
|
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)
|
||||||
|
break;
|
||||||
|
(*count)++;
|
||||||
|
size += len;
|
||||||
|
}
|
||||||
|
uefi_call_wrapper(file->SetPosition, 2, file, 0);
|
||||||
|
|
||||||
|
char *ptr = AllocatePool(size);
|
||||||
|
*entries = (EFI_FILE_INFO *)ptr;
|
||||||
|
if (!*entries)
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < *count; i++) {
|
||||||
|
int len = size;
|
||||||
|
uefi_call_wrapper(file->Read, 3, file, &len, ptr);
|
||||||
|
ptr += len;
|
||||||
|
size -= len;
|
||||||
|
}
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
out:
|
||||||
|
simple_file_close(file);
|
||||||
|
if (status != EFI_SUCCESS && *entries) {
|
||||||
|
FreePool(*entries);
|
||||||
|
*entries = NULL;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **entries,
|
||||||
|
int *count)
|
||||||
|
{
|
||||||
|
EFI_FILE *file;
|
||||||
|
EFI_STATUS 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return simple_dir_read_all_by_handle(image, file, name, entries, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer)
|
||||||
|
{
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
EFI_FILE_INFO *fi;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
*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");
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = fi->FileSize;
|
||||||
|
|
||||||
|
*buffer = AllocatePool(*size);
|
||||||
|
if (!*buffer) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
CHAR16 **entries;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol,
|
||||||
|
&SIMPLE_FS_PROTOCOL, NULL, &count, &vol_handles);
|
||||||
|
|
||||||
|
if (!count || !vol_handles)
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
|
||||||
|
entries = AllocatePool(sizeof(CHAR16 *) * (count+1));
|
||||||
|
if (!entries)
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
char buf[4096];
|
||||||
|
UINTN size = sizeof(buf);
|
||||||
|
EFI_FILE_SYSTEM_INFO *fi = (void *)buf;
|
||||||
|
EFI_FILE *root;
|
||||||
|
CHAR16 *name;
|
||||||
|
EFI_FILE_IO_INTERFACE *drive;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(BS->HandleProtocol, 3,
|
||||||
|
vol_handles[i],
|
||||||
|
&SIMPLE_FS_PROTOCOL, &drive);
|
||||||
|
if (status != EFI_SUCCESS || !drive)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = uefi_call_wrapper(root->GetInfo, 4, root, &FS_INFO,
|
||||||
|
&size, fi);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
name = fi->VolumeLabel;
|
||||||
|
|
||||||
|
if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0)
|
||||||
|
name = DevicePathToStr(DevicePathFromHandle(vol_handles[i]));
|
||||||
|
|
||||||
|
entries[i] = AllocatePool((StrLen(name) + 2) * sizeof(CHAR16));
|
||||||
|
if (!entries[i])
|
||||||
|
break;
|
||||||
|
StrCpy(entries[i], name);
|
||||||
|
}
|
||||||
|
entries[i] = NULL;
|
||||||
|
|
||||||
|
val = console_select(title, entries, 0);
|
||||||
|
|
||||||
|
if (val >= 0) {
|
||||||
|
*selected = AllocatePool((StrLen(entries[val]) + 1) * sizeof(CHAR16));
|
||||||
|
if (*selected) {
|
||||||
|
StrCpy(*selected , entries[val]);
|
||||||
|
}
|
||||||
|
*h = vol_handles[val];
|
||||||
|
} else {
|
||||||
|
*selected = NULL;
|
||||||
|
*h = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
if (entries[i])
|
||||||
|
FreePool(entries[i]);
|
||||||
|
}
|
||||||
|
FreePool(entries);
|
||||||
|
FreePool(vol_handles);
|
||||||
|
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter,
|
||||||
|
CHAR16 ***result, int *count, EFI_FILE_INFO **entries)
|
||||||
|
{
|
||||||
|
EFI_STATUS status;
|
||||||
|
int tot, offs = StrLen(filter), i, c, filtercount = 1;
|
||||||
|
EFI_FILE_INFO *next;
|
||||||
|
void *ptr;
|
||||||
|
CHAR16 *newfilter = AllocatePool((StrLen(filter) + 1) * sizeof(CHAR16)),
|
||||||
|
**filterarr;
|
||||||
|
|
||||||
|
if (!newfilter)
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
|
/* just in case efi ever stops writeable strings */
|
||||||
|
StrCpy(newfilter, filter);
|
||||||
|
|
||||||
|
for (i = 0; i < offs; i++) {
|
||||||
|
if (filter[i] == '|')
|
||||||
|
filtercount++;
|
||||||
|
}
|
||||||
|
filterarr = AllocatePool(filtercount * sizeof(void *));
|
||||||
|
if (!filterarr)
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
c = 0;
|
||||||
|
filterarr[c++] = newfilter;
|
||||||
|
for (i = 0; i < offs; i++) {
|
||||||
|
if (filter[i] == '|') {
|
||||||
|
newfilter[i] = '\0';
|
||||||
|
filterarr[c++] = &newfilter[i+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
|
||||||
|
status = simple_dir_read_all(image, name, entries, &tot);
|
||||||
|
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
goto out;
|
||||||
|
ptr = next = *entries;
|
||||||
|
|
||||||
|
for (i = 0; i < tot; i++) {
|
||||||
|
int len = StrLen(next->FileName);
|
||||||
|
|
||||||
|
for (c = 0; c < filtercount; c++) {
|
||||||
|
offs = StrLen(filterarr[c]);
|
||||||
|
|
||||||
|
if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0
|
||||||
|
|| (next->Attribute & EFI_FILE_DIRECTORY)) {
|
||||||
|
(*count)++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
|
||||||
|
next = ptr;
|
||||||
|
}
|
||||||
|
if (*count)
|
||||||
|
*result = AllocatePool(((*count) + 1) * sizeof(void *));
|
||||||
|
else
|
||||||
|
*result = AllocatePool(2 * sizeof(void *));
|
||||||
|
|
||||||
|
*count = 0;
|
||||||
|
ptr = next = *entries;
|
||||||
|
|
||||||
|
for (i = 0; i < tot; i++) {
|
||||||
|
int len = StrLen(next->FileName);
|
||||||
|
|
||||||
|
if (StrCmp(next->FileName, L".") == 0)
|
||||||
|
/* ignore . directory */
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
if (next->Attribute & EFI_FILE_DIRECTORY) {
|
||||||
|
(*result)[(*count)] = next->FileName;
|
||||||
|
(*result)[(*count)][len] = '/';
|
||||||
|
(*result)[(*count)++][len + 1] = '\0';
|
||||||
|
goto next;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (c = 0; c < filtercount; c++) {
|
||||||
|
offs = StrLen(filterarr[c]);
|
||||||
|
|
||||||
|
if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) {
|
||||||
|
(*result)[(*count)++] = next->FileName;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next:
|
||||||
|
if (StrCmp(next->FileName, L"../") == 0) {
|
||||||
|
/* place .. directory first */
|
||||||
|
CHAR16 *tmp = (*result)[(*count) - 1];
|
||||||
|
|
||||||
|
(*result)[(*count) - 1] = (*result)[0];
|
||||||
|
(*result)[0] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16);
|
||||||
|
next = ptr;
|
||||||
|
}
|
||||||
|
if (*count == 0) {
|
||||||
|
/* no entries at all ... can happen because top level dir has no . or .. */
|
||||||
|
(*result)[(*count)++] = L"./";
|
||||||
|
}
|
||||||
|
(*result)[*count] = NULL;
|
||||||
|
status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (status != EFI_SUCCESS) {
|
||||||
|
if (*entries)
|
||||||
|
FreePool(*entries);
|
||||||
|
*entries = NULL;
|
||||||
|
if (*result)
|
||||||
|
FreePool(*result);
|
||||||
|
*result = NULL;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
|
||||||
|
CHAR16 *filter, CHAR16 **result)
|
||||||
|
{
|
||||||
|
EFI_STATUS status;
|
||||||
|
CHAR16 **entries;
|
||||||
|
EFI_FILE_INFO *dmp;
|
||||||
|
int count, select, len;
|
||||||
|
CHAR16 *newname, *selected;
|
||||||
|
|
||||||
|
*result = NULL;
|
||||||
|
if (!name)
|
||||||
|
name = L"\\";
|
||||||
|
if (!filter)
|
||||||
|
filter = L"";
|
||||||
|
if (!*im) {
|
||||||
|
EFI_HANDLE h;
|
||||||
|
CHAR16 *volname;
|
||||||
|
|
||||||
|
simple_volume_selector(title, &volname, &h);
|
||||||
|
if (!volname)
|
||||||
|
return;
|
||||||
|
FreePool(volname);
|
||||||
|
*im = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
select = console_select(title, entries, 0);
|
||||||
|
if (select < 0)
|
||||||
|
/* ESC key */
|
||||||
|
goto out_free;
|
||||||
|
selected = entries[select];
|
||||||
|
FreePool(entries);
|
||||||
|
entries = NULL;
|
||||||
|
/* note that memory used by selected is valid until dmp is freed */
|
||||||
|
len = StrLen(selected);
|
||||||
|
if (selected[len - 1] == '/') {
|
||||||
|
CHAR16 *newname;
|
||||||
|
|
||||||
|
/* stay where we are */
|
||||||
|
if (StrCmp(selected, L"./") == 0) {
|
||||||
|
FreePool(dmp);
|
||||||
|
goto redo;
|
||||||
|
} else if (StrCmp(selected, L"../") == 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = StrLen(name) - 1;
|
||||||
|
|
||||||
|
|
||||||
|
for (i = StrLen(name); i > 0; --i) {
|
||||||
|
if (name[i] == '\\')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 0)
|
||||||
|
i = 1;
|
||||||
|
|
||||||
|
if (StrCmp(name, L"\\") != 0
|
||||||
|
&& StrCmp(&name[i], L"..") != 0) {
|
||||||
|
name[i] = '\0';
|
||||||
|
FreePool(dmp);
|
||||||
|
goto redo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
/* remove trailing / */
|
||||||
|
newname[StrLen(newname) - 1] = '\0';
|
||||||
|
|
||||||
|
FreePool(dmp);
|
||||||
|
FreePool(name);
|
||||||
|
name = newname;
|
||||||
|
|
||||||
|
goto redo;
|
||||||
|
}
|
||||||
|
*result = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16));
|
||||||
|
if (*result) {
|
||||||
|
StrCpy(*result, name);
|
||||||
|
if (name[StrLen(name) - 1] != '\\')
|
||||||
|
StrCat(*result, L"\\");
|
||||||
|
StrCat(*result, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_free:
|
||||||
|
FreePool(dmp);
|
||||||
|
if (entries)
|
||||||
|
FreePool(entries);
|
||||||
|
out_free_name:
|
||||||
|
FreePool(name);
|
||||||
|
}
|
340
lib/variables.c
Normal file
340
lib/variables.c
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012 <James.Bottomley@HansenPartnership.com>
|
||||||
|
*
|
||||||
|
* see COPYING file
|
||||||
|
*
|
||||||
|
* Portions of this file are a direct cut and paste from Tianocore
|
||||||
|
* (http://tianocore.sf.net)
|
||||||
|
*
|
||||||
|
* SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* 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 <sha256.h>
|
||||||
|
#include <errors.h>
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner,
|
||||||
|
void **out, int *outlen)
|
||||||
|
{
|
||||||
|
*outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
|
||||||
|
|
||||||
|
*out = AllocateZeroPool(*outlen);
|
||||||
|
if (!*out)
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
|
EFI_SIGNATURE_LIST *sl = *out;
|
||||||
|
|
||||||
|
sl->SignatureHeaderSize = 0;
|
||||||
|
sl->SignatureType = *type;
|
||||||
|
sl->SignatureSize = cert_len + sizeof(EFI_GUID);
|
||||||
|
sl->SignatureListSize = *outlen;
|
||||||
|
|
||||||
|
EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST);
|
||||||
|
|
||||||
|
if (owner)
|
||||||
|
sd->SignatureOwner = *owner;
|
||||||
|
|
||||||
|
CopyMem(sd->SignatureData, cert, cert_len);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Payload != NULL) && (PayloadSize != 0)) {
|
||||||
|
CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);
|
||||||
|
|
||||||
|
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 0
|
||||||
|
if (Payload != NULL) {
|
||||||
|
FreePool(Payload);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*DataSize = DescriptorSize + PayloadSize;
|
||||||
|
*Data = NewData;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner,
|
||||||
|
UINT32 options, int createtimebased)
|
||||||
|
{
|
||||||
|
EFI_SIGNATURE_LIST *Cert;
|
||||||
|
UINTN DataSize;
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
|
||||||
|
/* Microsoft request: Bugs in some UEFI platforms mean that PK or any
|
||||||
|
* other secure variable can be updated or deleted programmatically,
|
||||||
|
* so prevent */
|
||||||
|
if (!variable_is_setupmode())
|
||||||
|
return EFI_SECURITY_VIOLATION;
|
||||||
|
|
||||||
|
if (createtimebased) {
|
||||||
|
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);
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSize = ds;
|
||||||
|
} else {
|
||||||
|
/* we expect an efi signature list rather than creating it */
|
||||||
|
Cert = (EFI_SIGNATURE_LIST *)Data;
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64
|
||||||
|
GetOSIndications(void)
|
||||||
|
{
|
||||||
|
UINT64 indications;
|
||||||
|
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)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return indications;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
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)
|
||||||
|
return efi_status;
|
||||||
|
|
||||||
|
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, NULL);
|
||||||
|
/* does not return */
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner,
|
||||||
|
UINT32 *attributes)
|
||||||
|
{
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
|
||||||
|
*len = 0;
|
||||||
|
|
||||||
|
efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner,
|
||||||
|
NULL, len, NULL);
|
||||||
|
if (efi_status != EFI_BUFFER_TOO_SMALL)
|
||||||
|
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) {
|
||||||
|
FreePool(*data);
|
||||||
|
*data = NULL;
|
||||||
|
}
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner)
|
||||||
|
{
|
||||||
|
return get_variable_attr(var, data, len, owner, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen)
|
||||||
|
{
|
||||||
|
EFI_SIGNATURE_LIST *CertList;
|
||||||
|
|
||||||
|
certlist_for_each_certentry(CertList, Data, DataSize, DataSize) {
|
||||||
|
if (CertList->SignatureSize != keylen + sizeof(EFI_GUID))
|
||||||
|
continue;
|
||||||
|
EFI_SIGNATURE_DATA *Cert;
|
||||||
|
|
||||||
|
certentry_for_each_cert(Cert, CertList)
|
||||||
|
if (CompareMem (Cert->SignatureData, key, keylen) == 0)
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen)
|
||||||
|
{
|
||||||
|
UINTN DataSize;
|
||||||
|
UINT8 *Data;
|
||||||
|
EFI_STATUS status;
|
||||||
|
|
||||||
|
status = get_variable(var, &Data, &DataSize, owner);
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = find_in_esl(Data, DataSize, key, keylen);
|
||||||
|
|
||||||
|
FreePool(Data);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
variable_is_setupmode(void)
|
||||||
|
{
|
||||||
|
/* set to 1 because we return true if SetupMode doesn't exist */
|
||||||
|
UINT8 SetupMode = 1;
|
||||||
|
UINTN DataSize = sizeof(SetupMode);
|
||||||
|
|
||||||
|
uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL,
|
||||||
|
&DataSize, &SetupMode);
|
||||||
|
|
||||||
|
return SetupMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
variable_is_secureboot(void)
|
||||||
|
{
|
||||||
|
/* return false if variable doesn't exist */
|
||||||
|
UINT8 SecureBoot = 0;
|
||||||
|
UINTN DataSize;
|
||||||
|
|
||||||
|
DataSize = sizeof(SecureBoot);
|
||||||
|
uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL,
|
||||||
|
&DataSize, &SecureBoot);
|
||||||
|
|
||||||
|
return SecureBoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
variable_enroll_hash(CHAR16 *var, EFI_GUID owner,
|
||||||
|
UINT8 hash[SHA256_DIGEST_SIZE])
|
||||||
|
{
|
||||||
|
EFI_STATUS status;
|
||||||
|
|
||||||
|
if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE)
|
||||||
|
== EFI_SUCCESS)
|
||||||
|
/* hash already present */
|
||||||
|
return EFI_ALREADY_STARTED;
|
||||||
|
|
||||||
|
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));
|
||||||
|
l->SignatureType = EFI_CERT_SHA256_GUID;
|
||||||
|
l->SignatureListSize = sizeof(sig);
|
||||||
|
l->SignatureSize = 16 +32; /* UEFI defined */
|
||||||
|
CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE);
|
||||||
|
d->SignatureOwner = MOK_OWNER;
|
||||||
|
|
||||||
|
if (CompareGuid(&owner, &SIG_DB) == 0)
|
||||||
|
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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user