Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d42b3a29 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 EFI update from Peter Anvin:
 "EFI tree, from Matt Fleming.  Most of the patches are the new efivarfs
  filesystem by Matt Garrett & co.  The balance are support for EFI
  wallclock in the absence of a hardware-specific driver, and various
  fixes and cleanups."

* 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits)
  efivarfs: Make efivarfs_fill_super() static
  x86, efi: Check table header length in efi_bgrt_init()
  efivarfs: Use query_variable_info() to limit kmalloc()
  efivarfs: Fix return value of efivarfs_file_write()
  efivarfs: Return a consistent error when efivarfs_get_inode() fails
  efivarfs: Make 'datasize' unsigned long
  efivarfs: Add unique magic number
  efivarfs: Replace magic number with sizeof(attributes)
  efivarfs: Return an error if we fail to read a variable
  efi: Clarify GUID length calculations
  efivarfs: Implement exclusive access for {get,set}_variable
  efivarfs: efivarfs_fill_super() ensure we clean up correctly on error
  efivarfs: efivarfs_fill_super() ensure we free our temporary name
  efivarfs: efivarfs_fill_super() fix inode reference counts
  efivarfs: efivarfs_create() ensure we drop our reference on inode on error
  efivarfs: efivarfs_file_read ensure we free data in error paths
  x86-64/efi: Use EFI to deal with platform wall clock (again)
  x86/kernel: remove tboot 1:1 page table creation code
  x86, efi: 1:1 pagetable mapping for virtual EFI calls
  x86, mm: Include the entire kernel memory map in trampoline_pgd
  ...
parents 18dd0bf2 e83af1f1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ dnotify_test.c
	- example program for dnotify
ecryptfs.txt
	- docs on eCryptfs: stacked cryptographic filesystem for Linux.
efivarfs.txt
	- info for the efivarfs filesystem.
exofs.txt
	- info, usage, mount options, design about EXOFS.
ext2.txt
+16 −0
Original line number Diff line number Diff line

efivarfs - a (U)EFI variable filesystem

The efivarfs filesystem was created to address the shortcomings of
using entries in sysfs to maintain EFI variables. The old sysfs EFI
variables code only supported variables of up to 1024 bytes. This
limitation existed in version 0.99 of the EFI specification, but was
removed before any full releases. Since variables can now be larger
than a single page, sysfs isn't the best interface for this.

Variables can be created, deleted and modified with the efivarfs
filesystem.

efivarfs is typically mounted like this,

	mount -t efivarfs none /sys/firmware/efi/efivars
+21 −7
Original line number Diff line number Diff line
@@ -69,23 +69,37 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
	efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3),		\
		  (u64)(a4), (u64)(a5), (u64)(a6))

extern unsigned long efi_call_virt_prelog(void);
extern void efi_call_virt_epilog(unsigned long);

#define efi_callx(x, func, ...)					\
	({							\
		efi_status_t __status;				\
		unsigned long __pgd;				\
								\
		__pgd = efi_call_virt_prelog();			\
		__status = efi_call##x(func, __VA_ARGS__);	\
		efi_call_virt_epilog(__pgd);			\
		__status;					\
	})

#define efi_call_virt0(f)				\
	efi_call0((void *)(efi.systab->runtime->f))
	efi_callx(0, (void *)(efi.systab->runtime->f))
#define efi_call_virt1(f, a1)					\
	efi_call1((void *)(efi.systab->runtime->f), (u64)(a1))
	efi_callx(1, (void *)(efi.systab->runtime->f), (u64)(a1))
#define efi_call_virt2(f, a1, a2)					\
	efi_call2((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
	efi_callx(2, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
#define efi_call_virt3(f, a1, a2, a3)					\
	efi_call3((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
	efi_callx(3, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
		  (u64)(a3))
#define efi_call_virt4(f, a1, a2, a3, a4)				\
	efi_call4((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
	efi_callx(4, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
		  (u64)(a3), (u64)(a4))
#define efi_call_virt5(f, a1, a2, a3, a4, a5)				\
	efi_call5((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
	efi_callx(5, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
		  (u64)(a3), (u64)(a4), (u64)(a5))
#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)			\
	efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
	efi_callx(6, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
		  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))

extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
+5 −73
Original line number Diff line number Diff line
@@ -103,71 +103,13 @@ void __init tboot_probe(void)
	pr_debug("tboot_size: 0x%x\n", tboot->tboot_size);
}

static pgd_t *tboot_pg_dir;
static struct mm_struct tboot_mm = {
	.mm_rb          = RB_ROOT,
	.pgd            = swapper_pg_dir,
	.mm_users       = ATOMIC_INIT(2),
	.mm_count       = ATOMIC_INIT(1),
	.mmap_sem       = __RWSEM_INITIALIZER(init_mm.mmap_sem),
	.page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
	.mmlist         = LIST_HEAD_INIT(init_mm.mmlist),
};

static inline void switch_to_tboot_pt(void)
{
	write_cr3(virt_to_phys(tboot_pg_dir));
}

static int map_tboot_page(unsigned long vaddr, unsigned long pfn,
			  pgprot_t prot)
{
	pgd_t *pgd;
	pud_t *pud;
	pmd_t *pmd;
	pte_t *pte;

	pgd = pgd_offset(&tboot_mm, vaddr);
	pud = pud_alloc(&tboot_mm, pgd, vaddr);
	if (!pud)
		return -1;
	pmd = pmd_alloc(&tboot_mm, pud, vaddr);
	if (!pmd)
		return -1;
	pte = pte_alloc_map(&tboot_mm, NULL, pmd, vaddr);
	if (!pte)
		return -1;
	set_pte_at(&tboot_mm, vaddr, pte, pfn_pte(pfn, prot));
	pte_unmap(pte);
	return 0;
}

static int map_tboot_pages(unsigned long vaddr, unsigned long start_pfn,
			   unsigned long nr)
{
	/* Reuse the original kernel mapping */
	tboot_pg_dir = pgd_alloc(&tboot_mm);
	if (!tboot_pg_dir)
		return -1;

	for (; nr > 0; nr--, vaddr += PAGE_SIZE, start_pfn++) {
		if (map_tboot_page(vaddr, start_pfn, PAGE_KERNEL_EXEC))
			return -1;
	}

	return 0;
}

static void tboot_create_trampoline(void)
{
	u32 map_base, map_size;

	/* Create identity map for tboot shutdown code. */
	map_base = PFN_DOWN(tboot->tboot_base);
	map_size = PFN_UP(tboot->tboot_size);
	if (map_tboot_pages(map_base << PAGE_SHIFT, map_base, map_size))
		panic("tboot: Error mapping tboot pages (mfns) @ 0x%x, 0x%x\n",
		      map_base, map_size);
#ifdef CONFIG_X86_32
	load_cr3(initial_page_table);
#else
	write_cr3(real_mode_header->trampoline_pgd);
#endif
}

#ifdef CONFIG_ACPI_SLEEP
@@ -225,14 +167,6 @@ void tboot_shutdown(u32 shutdown_type)
	if (!tboot_enabled())
		return;

	/*
	 * if we're being called before the 1:1 mapping is set up then just
	 * return and let the normal shutdown happen; this should only be
	 * due to very early panic()
	 */
	if (!tboot_pg_dir)
		return;

	/* if this is S3 then set regions to MAC */
	if (shutdown_type == TB_SHUTDOWN_S3)
		if (tboot_setup_sleep())
@@ -343,8 +277,6 @@ static __init int tboot_late_init(void)
	if (!tboot_enabled())
		return 0;

	tboot_create_trampoline();

	atomic_set(&ap_wfs_count, 0);
	register_hotcpu_notifier(&tboot_cpu_notifier);

+8 −1
Original line number Diff line number Diff line
@@ -108,13 +108,13 @@ void sync_global_pgds(unsigned long start, unsigned long end)
	for (address = start; address <= end; address += PGDIR_SIZE) {
		const pgd_t *pgd_ref = pgd_offset_k(address);
		struct page *page;
		pgd_t *pgd;

		if (pgd_none(*pgd_ref))
			continue;

		spin_lock(&pgd_lock);
		list_for_each_entry(page, &pgd_list, lru) {
			pgd_t *pgd;
			spinlock_t *pgt_lock;

			pgd = (pgd_t *)page_address(page) + pgd_index(address);
@@ -130,6 +130,13 @@ void sync_global_pgds(unsigned long start, unsigned long end)

			spin_unlock(pgt_lock);
		}

		pgd = __va(real_mode_header->trampoline_pgd);
		pgd += pgd_index(address);

		if (pgd_none(*pgd))
			set_pgd(pgd, *pgd_ref);

		spin_unlock(&pgd_lock);
	}
}
Loading