2017-11-01 22:08:43 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
2008-10-23 13:26:29 +08:00
|
|
|
#ifndef _ASM_X86_BOOTPARAM_H
|
|
|
|
#define _ASM_X86_BOOTPARAM_H
|
2007-07-12 03:18:35 +08:00
|
|
|
|
2013-01-28 02:43:28 +08:00
|
|
|
/* setup_data types */
|
|
|
|
#define SETUP_NONE 0
|
|
|
|
#define SETUP_E820_EXT 1
|
|
|
|
#define SETUP_DTB 2
|
|
|
|
#define SETUP_PCI 3
|
2013-12-20 18:02:19 +08:00
|
|
|
#define SETUP_EFI 4
|
x86/efi: Retrieve and assign Apple device properties
Apple's EFI drivers supply device properties which are needed to support
Macs optimally. They contain vital information which cannot be obtained
any other way (e.g. Thunderbolt Device ROM). They're also used to convey
the current device state so that OS drivers can pick up where EFI
drivers left (e.g. GPU mode setting).
There's an EFI driver dubbed "AAPL,PathProperties" which implements a
per-device key/value store. Other EFI drivers populate it using a custom
protocol. The macOS bootloader /System/Library/CoreServices/boot.efi
retrieves the properties with the same protocol. The kernel extension
AppleACPIPlatform.kext subsequently merges them into the I/O Kit
registry (see ioreg(8)) where they can be queried by other kernel
extensions and user space.
This commit extends the efistub to retrieve the device properties before
ExitBootServices is called. It assigns them to devices in an fs_initcall
so that they can be queried with the API in <linux/property.h>.
Note that the device properties will only be available if the kernel is
booted with the efistub. Distros should adjust their installers to
always use the efistub on Macs. grub with the "linux" directive will not
work unless the functionality of this commit is duplicated in grub.
(The "linuxefi" directive should work but is not included upstream as of
this writing.)
The custom protocol has GUID 91BD12FE-F6C3-44FB-A5B7-5122AB303AE0 and
looks like this:
typedef struct {
unsigned long version; /* 0x10000 */
efi_status_t (*get) (
IN struct apple_properties_protocol *this,
IN struct efi_dev_path *device,
IN efi_char16_t *property_name,
OUT void *buffer,
IN OUT u32 *buffer_len);
/* EFI_SUCCESS, EFI_NOT_FOUND, EFI_BUFFER_TOO_SMALL */
efi_status_t (*set) (
IN struct apple_properties_protocol *this,
IN struct efi_dev_path *device,
IN efi_char16_t *property_name,
IN void *property_value,
IN u32 property_value_len);
/* allocates copies of property name and value */
/* EFI_SUCCESS, EFI_OUT_OF_RESOURCES */
efi_status_t (*del) (
IN struct apple_properties_protocol *this,
IN struct efi_dev_path *device,
IN efi_char16_t *property_name);
/* EFI_SUCCESS, EFI_NOT_FOUND */
efi_status_t (*get_all) (
IN struct apple_properties_protocol *this,
OUT void *buffer,
IN OUT u32 *buffer_len);
/* EFI_SUCCESS, EFI_BUFFER_TOO_SMALL */
} apple_properties_protocol;
Thanks to Pedro Vilaça for this blog post which was helpful in reverse
engineering Apple's EFI drivers and bootloader:
https://reverse.put.as/2016/06/25/apple-efi-firmware-passwords-and-the-scbo-myth/
If someone at Apple is reading this, please note there's a memory leak
in your implementation of the del() function as the property struct is
freed but the name and value allocations are not.
Neither the macOS bootloader nor Apple's EFI drivers check the protocol
version, but we do to avoid breakage if it's ever changed. It's been the
same since at least OS X 10.6 (2009).
The get_all() function conveniently fills a buffer with all properties
in marshalled form which can be passed to the kernel as a setup_data
payload. The number of device properties is dynamic and can change
between a first invocation of get_all() (to determine the buffer size)
and a second invocation (to retrieve the actual buffer), hence the
peculiar loop which does not finish until the buffer size settles.
The macOS bootloader does the same.
The setup_data payload is later on unmarshalled in an fs_initcall. The
idea is that most buses instantiate devices in "subsys" initcall level
and drivers are usually bound to these devices in "device" initcall
level, so we assign the properties in-between, i.e. in "fs" initcall
level.
This assumes that devices to which properties pertain are instantiated
from a "subsys" initcall or earlier. That should always be the case
since on macOS, AppleACPIPlatformExpert::matchEFIDevicePath() only
supports ACPI and PCI nodes and we've fully scanned those buses during
"subsys" initcall level.
The second assumption is that properties are only needed from a "device"
initcall or later. Seems reasonable to me, but should this ever not work
out, an alternative approach would be to store the property sets e.g. in
a btree early during boot. Then whenever device_add() is called, an EFI
Device Path would have to be constructed for the newly added device,
and looked up in the btree. That way, the property set could be assigned
to the device immediately on instantiation. And this would also work for
devices instantiated in a deferred fashion. It seems like this approach
would be more complicated and require more code. That doesn't seem
justified without a specific use case.
For comparison, the strategy on macOS is to assign properties to objects
in the ACPI namespace (AppleACPIPlatformExpert::mergeEFIProperties()).
That approach is definitely wrong as it fails for devices not present in
the namespace: The NHI EFI driver supplies properties for attached
Thunderbolt devices, yet on Macs with Thunderbolt 1 only one device
level behind the host controller is described in the namespace.
Consequently macOS cannot assign properties for chained devices. With
Thunderbolt 2 they started to describe three device levels behind host
controllers in the namespace but this grossly inflates the SSDT and
still fails if the user daisy-chained more than three devices.
We copy the property names and values from the setup_data payload to
swappable virtual memory and afterwards make the payload available to
the page allocator. This is just for the sake of good housekeeping, it
wouldn't occupy a meaningful amount of physical memory (4444 bytes on my
machine). Only the payload is freed, not the setup_data header since
otherwise we'd break the list linkage and we cannot safely update the
predecessor's ->next link because there's no locking for the list.
The payload is currently not passed on to kexec'ed kernels, same for PCI
ROMs retrieved by setup_efi_pci(). This can be added later if there is
demand by amending setup_efi_state(). The payload can then no longer be
made available to the page allocator of course.
Tested-by: Lukas Wunner <lukas@wunner.de> [MacBookPro9,1]
Tested-by: Pierre Moreau <pierre.morrow@free.fr> [MacBookPro11,3]
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
Cc: Andreas Noever <andreas.noever@gmail.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Pedro Vilaça <reverser@put.as>
Cc: Peter Jones <pjones@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: grub-devel@gnu.org
Cc: linux-efi@vger.kernel.org
Link: http://lkml.kernel.org/r/20161112213237.8804-9-matt@codeblueprint.co.uk
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2016-11-13 05:32:36 +08:00
|
|
|
#define SETUP_APPLE_PROPERTIES 5
|
2013-01-28 02:43:28 +08:00
|
|
|
|
|
|
|
/* ram_size flags */
|
|
|
|
#define RAMDISK_IMAGE_START_MASK 0x07FF
|
|
|
|
#define RAMDISK_PROMPT_FLAG 0x8000
|
|
|
|
#define RAMDISK_LOAD_FLAG 0x4000
|
|
|
|
|
|
|
|
/* loadflags */
|
|
|
|
#define LOADED_HIGH (1<<0)
|
2015-04-01 18:49:52 +08:00
|
|
|
#define KASLR_FLAG (1<<1)
|
2013-01-28 02:43:28 +08:00
|
|
|
#define QUIET_FLAG (1<<5)
|
|
|
|
#define KEEP_SEGMENTS (1<<6)
|
|
|
|
#define CAN_USE_HEAP (1<<7)
|
|
|
|
|
|
|
|
/* xloadflags */
|
|
|
|
#define XLF_KERNEL_64 (1<<0)
|
|
|
|
#define XLF_CAN_BE_LOADED_ABOVE_4G (1<<1)
|
|
|
|
#define XLF_EFI_HANDOVER_32 (1<<2)
|
|
|
|
#define XLF_EFI_HANDOVER_64 (1<<3)
|
2013-12-20 18:02:20 +08:00
|
|
|
#define XLF_EFI_KEXEC (1<<4)
|
2013-01-28 02:43:28 +08:00
|
|
|
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
|
2007-07-12 03:18:35 +08:00
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/screen_info.h>
|
|
|
|
#include <linux/apm_bios.h>
|
|
|
|
#include <linux/edd.h>
|
2007-07-19 08:19:30 +08:00
|
|
|
#include <asm/ist.h>
|
2007-07-12 03:18:35 +08:00
|
|
|
#include <video/edid.h>
|
|
|
|
|
2008-03-28 10:49:44 +08:00
|
|
|
/* extensible setup data list node */
|
|
|
|
struct setup_data {
|
2008-05-02 19:14:20 +08:00
|
|
|
__u64 next;
|
|
|
|
__u32 type;
|
|
|
|
__u32 len;
|
|
|
|
__u8 data[0];
|
2008-03-28 10:49:44 +08:00
|
|
|
};
|
|
|
|
|
2007-07-12 03:18:35 +08:00
|
|
|
struct setup_header {
|
2007-10-22 08:56:19 +08:00
|
|
|
__u8 setup_sects;
|
|
|
|
__u16 root_flags;
|
|
|
|
__u32 syssize;
|
|
|
|
__u16 ram_size;
|
|
|
|
__u16 vid_mode;
|
|
|
|
__u16 root_dev;
|
|
|
|
__u16 boot_flag;
|
|
|
|
__u16 jump;
|
|
|
|
__u32 header;
|
|
|
|
__u16 version;
|
|
|
|
__u32 realmode_swtch;
|
2017-02-22 02:36:39 +08:00
|
|
|
__u16 start_sys_seg;
|
2007-10-22 08:56:19 +08:00
|
|
|
__u16 kernel_version;
|
|
|
|
__u8 type_of_loader;
|
|
|
|
__u8 loadflags;
|
|
|
|
__u16 setup_move_size;
|
|
|
|
__u32 code32_start;
|
|
|
|
__u32 ramdisk_image;
|
|
|
|
__u32 ramdisk_size;
|
|
|
|
__u32 bootsect_kludge;
|
|
|
|
__u16 heap_end_ptr;
|
2009-05-08 07:54:11 +08:00
|
|
|
__u8 ext_loader_ver;
|
|
|
|
__u8 ext_loader_type;
|
2007-10-22 08:56:19 +08:00
|
|
|
__u32 cmd_line_ptr;
|
|
|
|
__u32 initrd_addr_max;
|
|
|
|
__u32 kernel_alignment;
|
|
|
|
__u8 relocatable_kernel;
|
2013-01-28 02:43:28 +08:00
|
|
|
__u8 min_alignment;
|
|
|
|
__u16 xloadflags;
|
2007-10-22 08:56:19 +08:00
|
|
|
__u32 cmdline_size;
|
|
|
|
__u32 hardware_subarch;
|
|
|
|
__u64 hardware_subarch_data;
|
2008-03-28 10:49:44 +08:00
|
|
|
__u32 payload_offset;
|
|
|
|
__u32 payload_length;
|
|
|
|
__u64 setup_data;
|
2011-08-27 16:35:45 +08:00
|
|
|
__u64 pref_address;
|
|
|
|
__u32 init_size;
|
2012-07-19 17:23:48 +08:00
|
|
|
__u32 handover_offset;
|
2007-07-12 03:18:35 +08:00
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
struct sys_desc_table {
|
2007-10-22 08:56:19 +08:00
|
|
|
__u16 length;
|
|
|
|
__u8 table[14];
|
2007-07-12 03:18:35 +08:00
|
|
|
};
|
|
|
|
|
2010-06-19 05:46:53 +08:00
|
|
|
/* Gleaned from OFW's set-parameters in cpu/x86/pc/linux.fth */
|
|
|
|
struct olpc_ofw_header {
|
|
|
|
__u32 ofw_magic; /* OFW signature */
|
|
|
|
__u32 ofw_version;
|
|
|
|
__u32 cif_handler; /* callback into OFW */
|
|
|
|
__u32 irq_desc_table;
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
2007-07-12 03:18:35 +08:00
|
|
|
struct efi_info {
|
2008-01-30 20:31:19 +08:00
|
|
|
__u32 efi_loader_signature;
|
2007-10-22 08:56:19 +08:00
|
|
|
__u32 efi_systab;
|
|
|
|
__u32 efi_memdesc_size;
|
|
|
|
__u32 efi_memdesc_version;
|
|
|
|
__u32 efi_memmap;
|
|
|
|
__u32 efi_memmap_size;
|
2008-01-30 20:31:19 +08:00
|
|
|
__u32 efi_systab_hi;
|
|
|
|
__u32 efi_memmap_hi;
|
2007-07-12 03:18:35 +08:00
|
|
|
};
|
|
|
|
|
2017-01-29 19:56:13 +08:00
|
|
|
/*
|
|
|
|
* This is the maximum number of entries in struct boot_params::e820_table
|
|
|
|
* (the zeropage), which is part of the x86 boot protocol ABI:
|
|
|
|
*/
|
|
|
|
#define E820_MAX_ENTRIES_ZEROPAGE 128
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The E820 memory region entry of the boot protocol ABI:
|
|
|
|
*/
|
|
|
|
struct boot_e820_entry {
|
|
|
|
__u64 addr;
|
|
|
|
__u64 size;
|
|
|
|
__u32 type;
|
|
|
|
} __attribute__((packed));
|
|
|
|
|
2007-07-12 03:18:35 +08:00
|
|
|
/* The so-called "zeropage" */
|
|
|
|
struct boot_params {
|
|
|
|
struct screen_info screen_info; /* 0x000 */
|
|
|
|
struct apm_bios_info apm_bios_info; /* 0x040 */
|
x86, intel_txt: Intel TXT boot support
This patch adds kernel configuration and boot support for Intel Trusted
Execution Technology (Intel TXT).
Intel's technology for safer computing, Intel Trusted Execution
Technology (Intel TXT), defines platform-level enhancements that
provide the building blocks for creating trusted platforms.
Intel TXT was formerly known by the code name LaGrande Technology (LT).
Intel TXT in Brief:
o Provides dynamic root of trust for measurement (DRTM)
o Data protection in case of improper shutdown
o Measurement and verification of launched environment
Intel TXT is part of the vPro(TM) brand and is also available some
non-vPro systems. It is currently available on desktop systems based on
the Q35, X38, Q45, and Q43 Express chipsets (e.g. Dell Optiplex 755, HP
dc7800, etc.) and mobile systems based on the GM45, PM45, and GS45
Express chipsets.
For more information, see http://www.intel.com/technology/security/.
This site also has a link to the Intel TXT MLE Developers Manual, which
has been updated for the new released platforms.
A much more complete description of how these patches support TXT, how to
configure a system for it, etc. is in the Documentation/intel_txt.txt file
in this patch.
This patch provides the TXT support routines for complete functionality,
documentation for TXT support and for the changes to the boot_params structure,
and boot detection of a TXT launch. Attempts to shutdown (reboot, Sx) the system
will result in platform resets; subsequent patches will support these shutdown modes
properly.
Documentation/intel_txt.txt | 210 +++++++++++++++++++++
Documentation/x86/zero-page.txt | 1
arch/x86/include/asm/bootparam.h | 3
arch/x86/include/asm/fixmap.h | 3
arch/x86/include/asm/tboot.h | 197 ++++++++++++++++++++
arch/x86/kernel/Makefile | 1
arch/x86/kernel/setup.c | 4
arch/x86/kernel/tboot.c | 379 +++++++++++++++++++++++++++++++++++++++
security/Kconfig | 30 +++
9 files changed, 827 insertions(+), 1 deletion(-)
Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>
Signed-off-by: Shane Wang <shane.wang@intel.com>
Signed-off-by: Gang Wei <gang.wei@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
2009-07-01 10:30:59 +08:00
|
|
|
__u8 _pad2[4]; /* 0x054 */
|
|
|
|
__u64 tboot_addr; /* 0x058 */
|
2007-07-19 08:19:30 +08:00
|
|
|
struct ist_info ist_info; /* 0x060 */
|
2007-10-22 08:56:19 +08:00
|
|
|
__u8 _pad3[16]; /* 0x070 */
|
|
|
|
__u8 hd0_info[16]; /* obsolete! */ /* 0x080 */
|
|
|
|
__u8 hd1_info[16]; /* obsolete! */ /* 0x090 */
|
2015-07-21 00:23:50 +08:00
|
|
|
struct sys_desc_table sys_desc_table; /* obsolete! */ /* 0x0a0 */
|
2010-06-19 05:46:53 +08:00
|
|
|
struct olpc_ofw_header olpc_ofw_header; /* 0x0b0 */
|
2013-01-28 02:43:28 +08:00
|
|
|
__u32 ext_ramdisk_image; /* 0x0c0 */
|
|
|
|
__u32 ext_ramdisk_size; /* 0x0c4 */
|
|
|
|
__u32 ext_cmd_line_ptr; /* 0x0c8 */
|
|
|
|
__u8 _pad4[116]; /* 0x0cc */
|
2007-07-12 03:18:35 +08:00
|
|
|
struct edid_info edid_info; /* 0x140 */
|
|
|
|
struct efi_info efi_info; /* 0x1c0 */
|
2007-10-22 08:56:19 +08:00
|
|
|
__u32 alt_mem_k; /* 0x1e0 */
|
|
|
|
__u32 scratch; /* Scratch field! */ /* 0x1e4 */
|
|
|
|
__u8 e820_entries; /* 0x1e8 */
|
|
|
|
__u8 eddbuf_entries; /* 0x1e9 */
|
|
|
|
__u8 edd_mbr_sig_buf_entries; /* 0x1ea */
|
2012-04-14 03:08:26 +08:00
|
|
|
__u8 kbd_status; /* 0x1eb */
|
2017-02-06 19:22:43 +08:00
|
|
|
__u8 secure_boot; /* 0x1ec */
|
|
|
|
__u8 _pad5[2]; /* 0x1ed */
|
2013-01-28 02:43:28 +08:00
|
|
|
/*
|
|
|
|
* The sentinel is set to a nonzero value (0xff) in header.S.
|
|
|
|
*
|
|
|
|
* A bootloader is supposed to only take setup_header and put
|
|
|
|
* it into a clean boot_params buffer. If it turns out that
|
|
|
|
* it is clumsy or too generous with the buffer, it most
|
|
|
|
* probably will pick up the sentinel variable too. The fact
|
|
|
|
* that this variable then is still 0xff will let kernel
|
|
|
|
* know that some variables in boot_params are invalid and
|
|
|
|
* kernel should zero out certain portions of boot_params.
|
|
|
|
*/
|
|
|
|
__u8 sentinel; /* 0x1ef */
|
|
|
|
__u8 _pad6[1]; /* 0x1f0 */
|
2007-07-12 03:18:35 +08:00
|
|
|
struct setup_header hdr; /* setup header */ /* 0x1f1 */
|
2007-10-22 08:56:19 +08:00
|
|
|
__u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)];
|
|
|
|
__u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */
|
2017-01-29 19:56:13 +08:00
|
|
|
struct boot_e820_entry e820_table[E820_MAX_ENTRIES_ZEROPAGE]; /* 0x2d0 */
|
2007-10-22 08:56:19 +08:00
|
|
|
__u8 _pad8[48]; /* 0xcd0 */
|
2007-07-12 03:18:35 +08:00
|
|
|
struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */
|
2007-10-22 08:56:19 +08:00
|
|
|
__u8 _pad9[276]; /* 0xeec */
|
2007-07-12 03:18:35 +08:00
|
|
|
} __attribute__((packed));
|
|
|
|
|
2016-04-14 08:04:31 +08:00
|
|
|
/**
|
|
|
|
* enum x86_hardware_subarch - x86 hardware subarchitecture
|
|
|
|
*
|
|
|
|
* The x86 hardware_subarch and hardware_subarch_data were added as of the x86
|
|
|
|
* boot protocol 2.07 to help distinguish and support custom x86 boot
|
|
|
|
* sequences. This enum represents accepted values for the x86
|
|
|
|
* hardware_subarch. Custom x86 boot sequences (not X86_SUBARCH_PC) do not
|
|
|
|
* have or simply *cannot* make use of natural stubs like BIOS or EFI, the
|
|
|
|
* hardware_subarch can be used on the Linux entry path to revector to a
|
|
|
|
* subarchitecture stub when needed. This subarchitecture stub can be used to
|
|
|
|
* set up Linux boot parameters or for special care to account for nonstandard
|
|
|
|
* handling of page tables.
|
|
|
|
*
|
|
|
|
* These enums should only ever be used by x86 code, and the code that uses
|
|
|
|
* it should be well contained and compartamentalized.
|
|
|
|
*
|
|
|
|
* KVM and Xen HVM do not have a subarch as these are expected to follow
|
|
|
|
* standard x86 boot entries. If there is a genuine need for "hypervisor" type
|
|
|
|
* that should be considered separately in the future. Future guest types
|
|
|
|
* should seriously consider working with standard x86 boot stubs such as
|
|
|
|
* the BIOS or EFI boot stubs.
|
|
|
|
*
|
|
|
|
* WARNING: this enum is only used for legacy hacks, for platform features that
|
|
|
|
* are not easily enumerated or discoverable. You should not ever use
|
|
|
|
* this for new features.
|
|
|
|
*
|
|
|
|
* @X86_SUBARCH_PC: Should be used if the hardware is enumerable using standard
|
|
|
|
* PC mechanisms (PCI, ACPI) and doesn't need a special boot flow.
|
2017-08-17 01:31:57 +08:00
|
|
|
* @X86_SUBARCH_LGUEST: Used for x86 hypervisor demo, lguest, deprecated
|
2016-04-14 08:04:31 +08:00
|
|
|
* @X86_SUBARCH_XEN: Used for Xen guest types which follow the PV boot path,
|
|
|
|
* which start at asm startup_xen() entry point and later jump to the C
|
|
|
|
* xen_start_kernel() entry point. Both domU and dom0 type of guests are
|
|
|
|
* currently supportd through this PV boot path.
|
|
|
|
* @X86_SUBARCH_INTEL_MID: Used for Intel MID (Mobile Internet Device) platform
|
|
|
|
* systems which do not have the PCI legacy interfaces.
|
|
|
|
* @X86_SUBARCH_CE4100: Used for Intel CE media processor (CE4100) SoC for
|
|
|
|
* for settop boxes and media devices, the use of a subarch for CE4100
|
|
|
|
* is more of a hack...
|
|
|
|
*/
|
|
|
|
enum x86_hardware_subarch {
|
2009-08-29 05:52:47 +08:00
|
|
|
X86_SUBARCH_PC = 0,
|
|
|
|
X86_SUBARCH_LGUEST,
|
|
|
|
X86_SUBARCH_XEN,
|
2013-10-18 06:35:29 +08:00
|
|
|
X86_SUBARCH_INTEL_MID,
|
2010-11-10 04:08:04 +08:00
|
|
|
X86_SUBARCH_CE4100,
|
2009-08-29 05:52:47 +08:00
|
|
|
X86_NR_SUBARCHS,
|
|
|
|
};
|
|
|
|
|
2013-01-28 02:43:28 +08:00
|
|
|
#endif /* __ASSEMBLY__ */
|
2009-08-29 05:52:47 +08:00
|
|
|
|
2008-10-23 13:26:29 +08:00
|
|
|
#endif /* _ASM_X86_BOOTPARAM_H */
|