xref: /OK3568_Linux_fs/kernel/arch/x86/platform/efi/efi_32.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Extensible Firmware Interface
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Based on Extensible Firmware Interface Specification version 1.0
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 1999 VA Linux Systems
8*4882a593Smuzhiyun  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
9*4882a593Smuzhiyun  * Copyright (C) 1999-2002 Hewlett-Packard Co.
10*4882a593Smuzhiyun  *	David Mosberger-Tang <davidm@hpl.hp.com>
11*4882a593Smuzhiyun  *	Stephane Eranian <eranian@hpl.hp.com>
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * All EFI Runtime Services are not implemented yet as EFI only
14*4882a593Smuzhiyun  * supports physical mode addressing on SoftSDV. This is to be fixed
15*4882a593Smuzhiyun  * in a future version.  --drummond 1999-07-20
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * Implemented EFI runtime services and virtual mode calls.  --davidm
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  * Goutham Rao: <goutham.rao@intel.com>
20*4882a593Smuzhiyun  *	Skip non-WB memory and ignore empty memory ranges.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include <linux/kernel.h>
24*4882a593Smuzhiyun #include <linux/types.h>
25*4882a593Smuzhiyun #include <linux/ioport.h>
26*4882a593Smuzhiyun #include <linux/efi.h>
27*4882a593Smuzhiyun #include <linux/pgtable.h>
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include <asm/io.h>
30*4882a593Smuzhiyun #include <asm/desc.h>
31*4882a593Smuzhiyun #include <asm/page.h>
32*4882a593Smuzhiyun #include <asm/set_memory.h>
33*4882a593Smuzhiyun #include <asm/tlbflush.h>
34*4882a593Smuzhiyun #include <asm/efi.h>
35*4882a593Smuzhiyun 
efi_map_region(efi_memory_desc_t * md)36*4882a593Smuzhiyun void __init efi_map_region(efi_memory_desc_t *md)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	u64 start_pfn, end_pfn, end;
39*4882a593Smuzhiyun 	unsigned long size;
40*4882a593Smuzhiyun 	void *va;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	start_pfn	= PFN_DOWN(md->phys_addr);
43*4882a593Smuzhiyun 	size		= md->num_pages << PAGE_SHIFT;
44*4882a593Smuzhiyun 	end		= md->phys_addr + size;
45*4882a593Smuzhiyun 	end_pfn 	= PFN_UP(end);
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	if (pfn_range_is_mapped(start_pfn, end_pfn)) {
48*4882a593Smuzhiyun 		va = __va(md->phys_addr);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 		if (!(md->attribute & EFI_MEMORY_WB))
51*4882a593Smuzhiyun 			set_memory_uc((unsigned long)va, md->num_pages);
52*4882a593Smuzhiyun 	} else {
53*4882a593Smuzhiyun 		va = ioremap_cache(md->phys_addr, size);
54*4882a593Smuzhiyun 	}
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	md->virt_addr = (unsigned long)va;
57*4882a593Smuzhiyun 	if (!va)
58*4882a593Smuzhiyun 		pr_err("ioremap of 0x%llX failed!\n", md->phys_addr);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun  * To make EFI call EFI runtime service in physical addressing mode we need
63*4882a593Smuzhiyun  * prolog/epilog before/after the invocation to claim the EFI runtime service
64*4882a593Smuzhiyun  * handler exclusively and to duplicate a memory mapping in low memory space,
65*4882a593Smuzhiyun  * say 0 - 3G.
66*4882a593Smuzhiyun  */
67*4882a593Smuzhiyun 
efi_alloc_page_tables(void)68*4882a593Smuzhiyun int __init efi_alloc_page_tables(void)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	return 0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
efi_sync_low_kernel_mappings(void)73*4882a593Smuzhiyun void efi_sync_low_kernel_mappings(void) {}
74*4882a593Smuzhiyun 
efi_dump_pagetable(void)75*4882a593Smuzhiyun void __init efi_dump_pagetable(void)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun #ifdef CONFIG_EFI_PGT_DUMP
78*4882a593Smuzhiyun 	ptdump_walk_pgd_level(NULL, &init_mm);
79*4882a593Smuzhiyun #endif
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
efi_setup_page_tables(unsigned long pa_memmap,unsigned num_pages)82*4882a593Smuzhiyun int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	return 0;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
efi_map_region_fixed(efi_memory_desc_t * md)87*4882a593Smuzhiyun void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
parse_efi_setup(u64 phys_addr,u32 data_len)88*4882a593Smuzhiyun void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun efi_status_t efi_call_svam(efi_runtime_services_t * const *,
91*4882a593Smuzhiyun 			   u32, u32, u32, void *, u32);
92*4882a593Smuzhiyun 
efi_set_virtual_address_map(unsigned long memory_map_size,unsigned long descriptor_size,u32 descriptor_version,efi_memory_desc_t * virtual_map,unsigned long systab_phys)93*4882a593Smuzhiyun efi_status_t __init efi_set_virtual_address_map(unsigned long memory_map_size,
94*4882a593Smuzhiyun 						unsigned long descriptor_size,
95*4882a593Smuzhiyun 						u32 descriptor_version,
96*4882a593Smuzhiyun 						efi_memory_desc_t *virtual_map,
97*4882a593Smuzhiyun 						unsigned long systab_phys)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	const efi_system_table_t *systab = (efi_system_table_t *)systab_phys;
100*4882a593Smuzhiyun 	struct desc_ptr gdt_descr;
101*4882a593Smuzhiyun 	efi_status_t status;
102*4882a593Smuzhiyun 	unsigned long flags;
103*4882a593Smuzhiyun 	pgd_t *save_pgd;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	/* Current pgd is swapper_pg_dir, we'll restore it later: */
106*4882a593Smuzhiyun 	save_pgd = swapper_pg_dir;
107*4882a593Smuzhiyun 	load_cr3(initial_page_table);
108*4882a593Smuzhiyun 	__flush_tlb_all();
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	gdt_descr.address = get_cpu_gdt_paddr(0);
111*4882a593Smuzhiyun 	gdt_descr.size = GDT_SIZE - 1;
112*4882a593Smuzhiyun 	load_gdt(&gdt_descr);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/* Disable interrupts around EFI calls: */
115*4882a593Smuzhiyun 	local_irq_save(flags);
116*4882a593Smuzhiyun 	status = efi_call_svam(&systab->runtime,
117*4882a593Smuzhiyun 			       memory_map_size, descriptor_size,
118*4882a593Smuzhiyun 			       descriptor_version, virtual_map,
119*4882a593Smuzhiyun 			       __pa(&efi.runtime));
120*4882a593Smuzhiyun 	local_irq_restore(flags);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	load_fixmap_gdt(0);
123*4882a593Smuzhiyun 	load_cr3(save_pgd);
124*4882a593Smuzhiyun 	__flush_tlb_all();
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	return status;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
efi_runtime_update_mappings(void)129*4882a593Smuzhiyun void __init efi_runtime_update_mappings(void)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	if (__supported_pte_mask & _PAGE_NX) {
132*4882a593Smuzhiyun 		efi_memory_desc_t *md;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 		/* Make EFI runtime service code area executable */
135*4882a593Smuzhiyun 		for_each_efi_memory_desc(md) {
136*4882a593Smuzhiyun 			if (md->type != EFI_RUNTIME_SERVICES_CODE)
137*4882a593Smuzhiyun 				continue;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 			set_memory_x(md->virt_addr, md->num_pages);
140*4882a593Smuzhiyun 		}
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun }
143