Merge branch 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI changes from Ingo Molnar: "The main changes in this cycle were: - further EFI code generalization to make it more workable for ARM64 - various extensions, such as 64-bit framebuffer address support, UEFI v2.5 EFI_PROPERTIES_TABLE support - code modularization simplifications and cleanups - new debugging parameters - various fixes and smaller additions" * 'core-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits) efi: Fix warning of int-to-pointer-cast on x86 32-bit builds efi: Use correct type for struct efi_memory_map::phys_map x86/efi: Fix kernel panic when CONFIG_DEBUG_VIRTUAL is enabled efi: Add "efi_fake_mem" boot option x86/efi: Rename print_efi_memmap() to efi_print_memmap() efi: Auto-load the efi-pstore module efi: Introduce EFI_NX_PE_DATA bit and set it from properties table efi: Add support for UEFIv2.5 Properties table efi: Add EFI_MEMORY_MORE_RELIABLE support to efi_md_typeattr_format() efifb: Add support for 64-bit frame buffer addresses efi/arm64: Clean up efi_get_fdt_params() interface arm64: Use core efi=debug instead of uefi_debug command line parameter efi/x86: Move efi=debug option parsing to core drivers/firmware: Make efi/esrt.c driver explicitly non-modular efi: Use the generic efi.memmap instead of 'memmap' acpi/apei: Use appropriate pgprot_t to map GHES memory arm64, acpi/apei: Implement arch_apei_get_mem_attributes() arm64/mm: Add PROT_DEVICE_nGnRnE and PROT_NORMAL_WT acpi, x86: Implement arch_apei_get_mem_attributes() efi, x86: Rearrange efi_mem_attributes() ...
This commit is contained in:
commit
f5a8160c1e
|
@ -60,5 +60,3 @@ linux,uefi-mmap-desc-ver | 32-bit | Version of the mmap descriptor format.
|
|||
--------------------------------------------------------------------------------
|
||||
linux,uefi-stub-kern-ver | string | Copy of linux_banner from build.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
For verbose debug messages, specify 'uefi_debug' on the kernel command line.
|
||||
|
|
|
@ -1094,6 +1094,21 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
you are really sure that your UEFI does sane gc and
|
||||
fulfills the spec otherwise your board may brick.
|
||||
|
||||
efi_fake_mem= nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86]
|
||||
Add arbitrary attribute to specific memory range by
|
||||
updating original EFI memory map.
|
||||
Region of memory which aa attribute is added to is
|
||||
from ss to ss+nn.
|
||||
If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
|
||||
is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
|
||||
attribute is added to range 0x100000000-0x180000000 and
|
||||
0x10a0000000-0x1120000000.
|
||||
|
||||
Using this parameter you can do debugging of EFI memmap
|
||||
related feature. For example, you can do debugging of
|
||||
Address Range Mirroring feature even if your box
|
||||
doesn't support it.
|
||||
|
||||
eisa_irq_edge= [PARISC,HW]
|
||||
See header of drivers/parisc/eisa.c.
|
||||
|
||||
|
|
|
@ -92,4 +92,9 @@ static inline const char *acpi_get_enable_method(int cpu)
|
|||
{
|
||||
return acpi_psci_present() ? "psci" : NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI
|
||||
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
|
||||
#endif
|
||||
|
||||
#endif /*_ASM_ACPI_H*/
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
#define MT_DEVICE_GRE 2
|
||||
#define MT_NORMAL_NC 3
|
||||
#define MT_NORMAL 4
|
||||
#define MT_NORMAL_WT 5
|
||||
|
||||
/*
|
||||
* Memory types for Stage-2 translation
|
||||
|
|
|
@ -60,8 +60,10 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
|
|||
#define PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
|
||||
#define PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
|
||||
|
||||
#define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRnE))
|
||||
#define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
|
||||
#define PROT_NORMAL_NC (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_NC))
|
||||
#define PROT_NORMAL_WT (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL_WT))
|
||||
#define PROT_NORMAL (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_NORMAL))
|
||||
|
||||
#define PROT_SECT_DEVICE_nGnRE (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_DEVICE_nGnRE))
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
#include <asm/cpu_ops.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI
|
||||
# include <linux/efi.h>
|
||||
# include <asm/pgtable.h>
|
||||
#endif
|
||||
|
||||
int acpi_noirq = 1; /* skip ACPI IRQ initialization */
|
||||
int acpi_disabled = 1;
|
||||
EXPORT_SYMBOL(acpi_disabled);
|
||||
|
@ -230,3 +235,27 @@ void __init acpi_gic_init(void)
|
|||
|
||||
early_acpi_os_unmap_memory((char *)table, tbl_size);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI
|
||||
pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
|
||||
{
|
||||
/*
|
||||
* According to "Table 8 Map: EFI memory types to AArch64 memory
|
||||
* types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is
|
||||
* mapped to a corresponding MAIR attribute encoding.
|
||||
* The EFI memory attribute advises all possible capabilities
|
||||
* of a memory region. We use the most efficient capability.
|
||||
*/
|
||||
|
||||
u64 attr;
|
||||
|
||||
attr = efi_mem_attributes(addr);
|
||||
if (attr & EFI_MEMORY_WB)
|
||||
return PAGE_KERNEL;
|
||||
if (attr & EFI_MEMORY_WT)
|
||||
return __pgprot(PROT_NORMAL_WT);
|
||||
if (attr & EFI_MEMORY_WC)
|
||||
return __pgprot(PROT_NORMAL_NC);
|
||||
return __pgprot(PROT_DEVICE_nGnRnE);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -51,15 +51,6 @@ static struct mm_struct efi_mm = {
|
|||
INIT_MM_CONTEXT(efi_mm)
|
||||
};
|
||||
|
||||
static int uefi_debug __initdata;
|
||||
static int __init uefi_debug_setup(char *str)
|
||||
{
|
||||
uefi_debug = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("uefi_debug", uefi_debug_setup);
|
||||
|
||||
static int __init is_normal_ram(efi_memory_desc_t *md)
|
||||
{
|
||||
if (md->attribute & EFI_MEMORY_WB)
|
||||
|
@ -171,14 +162,14 @@ static __init void reserve_regions(void)
|
|||
efi_memory_desc_t *md;
|
||||
u64 paddr, npages, size;
|
||||
|
||||
if (uefi_debug)
|
||||
if (efi_enabled(EFI_DBG))
|
||||
pr_info("Processing EFI memory map:\n");
|
||||
|
||||
for_each_efi_memory_desc(&memmap, md) {
|
||||
paddr = md->phys_addr;
|
||||
npages = md->num_pages;
|
||||
|
||||
if (uefi_debug) {
|
||||
if (efi_enabled(EFI_DBG)) {
|
||||
char buf[64];
|
||||
|
||||
pr_info(" 0x%012llx-0x%012llx %s",
|
||||
|
@ -194,11 +185,11 @@ static __init void reserve_regions(void)
|
|||
|
||||
if (is_reserve_region(md)) {
|
||||
memblock_reserve(paddr, size);
|
||||
if (uefi_debug)
|
||||
if (efi_enabled(EFI_DBG))
|
||||
pr_cont("*");
|
||||
}
|
||||
|
||||
if (uefi_debug)
|
||||
if (efi_enabled(EFI_DBG))
|
||||
pr_cont("\n");
|
||||
}
|
||||
|
||||
|
@ -210,14 +201,14 @@ void __init efi_init(void)
|
|||
struct efi_fdt_params params;
|
||||
|
||||
/* Grab UEFI information placed in FDT by stub */
|
||||
if (!efi_get_fdt_params(¶ms, uefi_debug))
|
||||
if (!efi_get_fdt_params(¶ms))
|
||||
return;
|
||||
|
||||
efi_system_table = params.system_table;
|
||||
|
||||
memblock_reserve(params.mmap & PAGE_MASK,
|
||||
PAGE_ALIGN(params.mmap_size + (params.mmap & ~PAGE_MASK)));
|
||||
memmap.phys_map = (void *)params.mmap;
|
||||
memmap.phys_map = params.mmap;
|
||||
memmap.map = early_memremap(params.mmap, params.mmap_size);
|
||||
memmap.map_end = memmap.map + params.mmap_size;
|
||||
memmap.desc_size = params.desc_size;
|
||||
|
@ -291,7 +282,7 @@ static int __init arm64_enable_runtime_services(void)
|
|||
pr_info("Remapping and enabling EFI services.\n");
|
||||
|
||||
mapsize = memmap.map_end - memmap.map;
|
||||
memmap.map = (__force void *)ioremap_cache((phys_addr_t)memmap.phys_map,
|
||||
memmap.map = (__force void *)ioremap_cache(memmap.phys_map,
|
||||
mapsize);
|
||||
if (!memmap.map) {
|
||||
pr_err("Failed to remap EFI memory map\n");
|
||||
|
|
|
@ -163,12 +163,14 @@ ENTRY(__cpu_setup)
|
|||
* DEVICE_GRE 010 00001100
|
||||
* NORMAL_NC 011 01000100
|
||||
* NORMAL 100 11111111
|
||||
* NORMAL_WT 101 10111011
|
||||
*/
|
||||
ldr x5, =MAIR(0x00, MT_DEVICE_nGnRnE) | \
|
||||
MAIR(0x04, MT_DEVICE_nGnRE) | \
|
||||
MAIR(0x0c, MT_DEVICE_GRE) | \
|
||||
MAIR(0x44, MT_NORMAL_NC) | \
|
||||
MAIR(0xff, MT_NORMAL)
|
||||
MAIR(0xff, MT_NORMAL) | \
|
||||
MAIR(0xbb, MT_NORMAL_WT)
|
||||
msr mair_el1, x5
|
||||
/*
|
||||
* Prepare SCTLR
|
||||
|
|
|
@ -624,7 +624,7 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
|
|||
static efi_status_t
|
||||
__gop_query32(struct efi_graphics_output_protocol_32 *gop32,
|
||||
struct efi_graphics_output_mode_info **info,
|
||||
unsigned long *size, u32 *fb_base)
|
||||
unsigned long *size, u64 *fb_base)
|
||||
{
|
||||
struct efi_graphics_output_protocol_mode_32 *mode;
|
||||
efi_status_t status;
|
||||
|
@ -650,7 +650,8 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
|
|||
unsigned long nr_gops;
|
||||
u16 width, height;
|
||||
u32 pixels_per_scan_line;
|
||||
u32 fb_base;
|
||||
u32 ext_lfb_base;
|
||||
u64 fb_base;
|
||||
struct efi_pixel_bitmask pixel_info;
|
||||
int pixel_format;
|
||||
efi_status_t status;
|
||||
|
@ -667,7 +668,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
|
|||
bool conout_found = false;
|
||||
void *dummy = NULL;
|
||||
u32 h = handles[i];
|
||||
u32 current_fb_base;
|
||||
u64 current_fb_base;
|
||||
|
||||
status = efi_call_early(handle_protocol, h,
|
||||
proto, (void **)&gop32);
|
||||
|
@ -715,6 +716,13 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
|
|||
si->lfb_width = width;
|
||||
si->lfb_height = height;
|
||||
si->lfb_base = fb_base;
|
||||
|
||||
ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
|
||||
if (ext_lfb_base) {
|
||||
si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
|
||||
si->ext_lfb_base = ext_lfb_base;
|
||||
}
|
||||
|
||||
si->pages = 1;
|
||||
|
||||
setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
|
||||
|
@ -729,7 +737,7 @@ out:
|
|||
static efi_status_t
|
||||
__gop_query64(struct efi_graphics_output_protocol_64 *gop64,
|
||||
struct efi_graphics_output_mode_info **info,
|
||||
unsigned long *size, u32 *fb_base)
|
||||
unsigned long *size, u64 *fb_base)
|
||||
{
|
||||
struct efi_graphics_output_protocol_mode_64 *mode;
|
||||
efi_status_t status;
|
||||
|
@ -755,7 +763,8 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
|
|||
unsigned long nr_gops;
|
||||
u16 width, height;
|
||||
u32 pixels_per_scan_line;
|
||||
u32 fb_base;
|
||||
u32 ext_lfb_base;
|
||||
u64 fb_base;
|
||||
struct efi_pixel_bitmask pixel_info;
|
||||
int pixel_format;
|
||||
efi_status_t status;
|
||||
|
@ -772,7 +781,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
|
|||
bool conout_found = false;
|
||||
void *dummy = NULL;
|
||||
u64 h = handles[i];
|
||||
u32 current_fb_base;
|
||||
u64 current_fb_base;
|
||||
|
||||
status = efi_call_early(handle_protocol, h,
|
||||
proto, (void **)&gop64);
|
||||
|
@ -820,6 +829,13 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
|
|||
si->lfb_width = width;
|
||||
si->lfb_height = height;
|
||||
si->lfb_base = fb_base;
|
||||
|
||||
ext_lfb_base = (u64)(unsigned long)fb_base >> 32;
|
||||
if (ext_lfb_base) {
|
||||
si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
|
||||
si->ext_lfb_base = ext_lfb_base;
|
||||
}
|
||||
|
||||
si->pages = 1;
|
||||
|
||||
setup_pixel_info(si, pixels_per_scan_line, pixel_info, pixel_format);
|
||||
|
|
|
@ -154,7 +154,7 @@ extra_header_fields:
|
|||
#else
|
||||
.quad 0 # ImageBase
|
||||
#endif
|
||||
.long CONFIG_PHYSICAL_ALIGN # SectionAlignment
|
||||
.long 0x20 # SectionAlignment
|
||||
.long 0x20 # FileAlignment
|
||||
.word 0 # MajorOperatingSystemVersion
|
||||
.word 0 # MinorOperatingSystemVersion
|
||||
|
|
|
@ -32,6 +32,10 @@
|
|||
#include <asm/mpspec.h>
|
||||
#include <asm/realmode.h>
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI
|
||||
# include <asm/pgtable_types.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int acpi_lapic;
|
||||
extern int acpi_ioapic;
|
||||
|
@ -147,4 +151,23 @@ extern int x86_acpi_numa_init(void);
|
|||
|
||||
#define acpi_unlazy_tlb(x) leave_mm(x)
|
||||
|
||||
#ifdef CONFIG_ACPI_APEI
|
||||
static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
|
||||
{
|
||||
/*
|
||||
* We currently have no way to look up the EFI memory map
|
||||
* attributes for a region in a consistent way, because the
|
||||
* memmap is discarded after efi_free_boot_services(). So if
|
||||
* you call efi_mem_attributes() during boot and at runtime,
|
||||
* you could theoretically see different attributes.
|
||||
*
|
||||
* Since we are yet to see any x86 platforms that require
|
||||
* anything other than PAGE_KERNEL (some arm64 platforms
|
||||
* require the equivalent of PAGE_KERNEL_NOCACHE), return that
|
||||
* until we know differently.
|
||||
*/
|
||||
return PAGE_KERNEL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_ACPI_H */
|
||||
|
|
|
@ -105,6 +105,7 @@ extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
|
|||
extern int __init efi_memblock_x86_reserve_range(void);
|
||||
extern pgd_t * __init efi_call_phys_prolog(void);
|
||||
extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
|
||||
extern void __init efi_print_memmap(void);
|
||||
extern void __init efi_unmap_memmap(void);
|
||||
extern void __init efi_memory_uc(u64 addr, unsigned long size);
|
||||
extern void __init efi_map_region(efi_memory_desc_t *md);
|
||||
|
|
|
@ -1079,8 +1079,10 @@ void __init setup_arch(char **cmdline_p)
|
|||
memblock_set_current_limit(ISA_END_ADDRESS);
|
||||
memblock_x86_fill();
|
||||
|
||||
if (efi_enabled(EFI_BOOT))
|
||||
if (efi_enabled(EFI_BOOT)) {
|
||||
efi_fake_memmap();
|
||||
efi_find_mirror();
|
||||
}
|
||||
|
||||
/*
|
||||
* The EFI specification says that boot service code won't be called
|
||||
|
|
|
@ -647,9 +647,12 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
|
|||
for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
|
||||
set_pte(&pbase[i], pfn_pte(pfn, canon_pgprot(ref_prot)));
|
||||
|
||||
if (pfn_range_is_mapped(PFN_DOWN(__pa(address)),
|
||||
PFN_DOWN(__pa(address)) + 1))
|
||||
split_page_count(level);
|
||||
if (virt_addr_valid(address)) {
|
||||
unsigned long pfn = PFN_DOWN(__pa(address));
|
||||
|
||||
if (pfn_range_is_mapped(pfn, pfn + 1))
|
||||
split_page_count(level);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install the new, split up pagetable.
|
||||
|
|
|
@ -50,11 +50,16 @@ void __init efi_bgrt_init(void)
|
|||
bgrt_tab->version);
|
||||
return;
|
||||
}
|
||||
if (bgrt_tab->status != 1) {
|
||||
pr_err("Ignoring BGRT: invalid status %u (expected 1)\n",
|
||||
if (bgrt_tab->status & 0xfe) {
|
||||
pr_err("Ignoring BGRT: reserved status bits are non-zero %u\n",
|
||||
bgrt_tab->status);
|
||||
return;
|
||||
}
|
||||
if (bgrt_tab->status != 1) {
|
||||
pr_debug("Ignoring BGRT: invalid status %u (expected 1)\n",
|
||||
bgrt_tab->status);
|
||||
return;
|
||||
}
|
||||
if (bgrt_tab->image_type != 0) {
|
||||
pr_err("Ignoring BGRT: invalid image type %u (expected 0)\n",
|
||||
bgrt_tab->image_type);
|
||||
|
|
|
@ -194,7 +194,7 @@ static void __init do_add_efi_memmap(void)
|
|||
int __init efi_memblock_x86_reserve_range(void)
|
||||
{
|
||||
struct efi_info *e = &boot_params.efi_info;
|
||||
unsigned long pmap;
|
||||
phys_addr_t pmap;
|
||||
|
||||
if (efi_enabled(EFI_PARAVIRT))
|
||||
return 0;
|
||||
|
@ -209,7 +209,7 @@ int __init efi_memblock_x86_reserve_range(void)
|
|||
#else
|
||||
pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32));
|
||||
#endif
|
||||
memmap.phys_map = (void *)pmap;
|
||||
memmap.phys_map = pmap;
|
||||
memmap.nr_map = e->efi_memmap_size /
|
||||
e->efi_memdesc_size;
|
||||
memmap.desc_size = e->efi_memdesc_size;
|
||||
|
@ -222,7 +222,7 @@ int __init efi_memblock_x86_reserve_range(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __init print_efi_memmap(void)
|
||||
void __init efi_print_memmap(void)
|
||||
{
|
||||
#ifdef EFI_DEBUG
|
||||
efi_memory_desc_t *md;
|
||||
|
@ -524,7 +524,7 @@ void __init efi_init(void)
|
|||
return;
|
||||
|
||||
if (efi_enabled(EFI_DBG))
|
||||
print_efi_memmap();
|
||||
efi_print_memmap();
|
||||
|
||||
efi_esrt_init();
|
||||
}
|
||||
|
@ -1017,24 +1017,6 @@ u32 efi_mem_type(unsigned long phys_addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
u64 efi_mem_attributes(unsigned long phys_addr)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
void *p;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP))
|
||||
return 0;
|
||||
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
if ((md->phys_addr <= phys_addr) &&
|
||||
(phys_addr < (md->phys_addr +
|
||||
(md->num_pages << EFI_PAGE_SHIFT))))
|
||||
return md->attribute;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init arch_parse_efi_cmdline(char *str)
|
||||
{
|
||||
if (!str) {
|
||||
|
@ -1044,8 +1026,6 @@ static int __init arch_parse_efi_cmdline(char *str)
|
|||
|
||||
if (parse_option_str(str, "old_map"))
|
||||
set_bit(EFI_OLD_MEMMAP, &efi.flags);
|
||||
if (parse_option_str(str, "debug"))
|
||||
set_bit(EFI_DBG, &efi.flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -157,11 +157,15 @@ static void __iomem *ghes_ioremap_pfn_nmi(u64 pfn)
|
|||
|
||||
static void __iomem *ghes_ioremap_pfn_irq(u64 pfn)
|
||||
{
|
||||
unsigned long vaddr;
|
||||
unsigned long vaddr, paddr;
|
||||
pgprot_t prot;
|
||||
|
||||
vaddr = (unsigned long)GHES_IOREMAP_IRQ_PAGE(ghes_ioremap_area->addr);
|
||||
ioremap_page_range(vaddr, vaddr + PAGE_SIZE,
|
||||
pfn << PAGE_SHIFT, PAGE_KERNEL);
|
||||
|
||||
paddr = pfn << PAGE_SHIFT;
|
||||
prot = arch_apei_get_mem_attribute(paddr);
|
||||
|
||||
ioremap_page_range(vaddr, vaddr + PAGE_SIZE, paddr, prot);
|
||||
|
||||
return (void __iomem *)vaddr;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,28 @@ config EFI_RUNTIME_MAP
|
|||
|
||||
See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
|
||||
|
||||
config EFI_FAKE_MEMMAP
|
||||
bool "Enable EFI fake memory map"
|
||||
depends on EFI && X86
|
||||
default n
|
||||
help
|
||||
Saying Y here will enable "efi_fake_mem" boot option.
|
||||
By specifying this parameter, you can add arbitrary attribute
|
||||
to specific memory range by updating original (firmware provided)
|
||||
EFI memmap.
|
||||
This is useful for debugging of EFI memmap related feature.
|
||||
e.g. Address Range Mirroring feature.
|
||||
|
||||
config EFI_MAX_FAKE_MEM
|
||||
int "maximum allowable number of ranges in efi_fake_mem boot option"
|
||||
depends on EFI_FAKE_MEMMAP
|
||||
range 1 128
|
||||
default 8
|
||||
help
|
||||
Maximum allowable number of ranges in efi_fake_mem boot option.
|
||||
Ranges can be set up to this value using comma-separated list.
|
||||
The default value is 8.
|
||||
|
||||
config EFI_PARAMS_FROM_FDT
|
||||
bool
|
||||
help
|
||||
|
|
|
@ -9,3 +9,4 @@ obj-$(CONFIG_UEFI_CPER) += cper.o
|
|||
obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
|
||||
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
|
||||
obj-$(CONFIG_EFI_STUB) += libstub/
|
||||
obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
|
||||
|
|
|
@ -400,3 +400,4 @@ module_exit(efivars_pstore_exit);
|
|||
|
||||
MODULE_DESCRIPTION("EFI variable backend for pstore");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:efivars");
|
||||
|
|
|
@ -26,20 +26,21 @@
|
|||
#include <linux/platform_device.h>
|
||||
|
||||
struct efi __read_mostly efi = {
|
||||
.mps = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi20 = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios3 = EFI_INVALID_TABLE_ADDR,
|
||||
.sal_systab = EFI_INVALID_TABLE_ADDR,
|
||||
.boot_info = EFI_INVALID_TABLE_ADDR,
|
||||
.hcdp = EFI_INVALID_TABLE_ADDR,
|
||||
.uga = EFI_INVALID_TABLE_ADDR,
|
||||
.uv_systab = EFI_INVALID_TABLE_ADDR,
|
||||
.fw_vendor = EFI_INVALID_TABLE_ADDR,
|
||||
.runtime = EFI_INVALID_TABLE_ADDR,
|
||||
.config_table = EFI_INVALID_TABLE_ADDR,
|
||||
.esrt = EFI_INVALID_TABLE_ADDR,
|
||||
.mps = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi20 = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios3 = EFI_INVALID_TABLE_ADDR,
|
||||
.sal_systab = EFI_INVALID_TABLE_ADDR,
|
||||
.boot_info = EFI_INVALID_TABLE_ADDR,
|
||||
.hcdp = EFI_INVALID_TABLE_ADDR,
|
||||
.uga = EFI_INVALID_TABLE_ADDR,
|
||||
.uv_systab = EFI_INVALID_TABLE_ADDR,
|
||||
.fw_vendor = EFI_INVALID_TABLE_ADDR,
|
||||
.runtime = EFI_INVALID_TABLE_ADDR,
|
||||
.config_table = EFI_INVALID_TABLE_ADDR,
|
||||
.esrt = EFI_INVALID_TABLE_ADDR,
|
||||
.properties_table = EFI_INVALID_TABLE_ADDR,
|
||||
};
|
||||
EXPORT_SYMBOL(efi);
|
||||
|
||||
|
@ -63,6 +64,9 @@ static int __init parse_efi_cmdline(char *str)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (parse_option_str(str, "debug"))
|
||||
set_bit(EFI_DBG, &efi.flags);
|
||||
|
||||
if (parse_option_str(str, "noruntime"))
|
||||
disable_runtime = true;
|
||||
|
||||
|
@ -250,7 +254,7 @@ subsys_initcall(efisubsys_init);
|
|||
int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
|
||||
{
|
||||
struct efi_memory_map *map = efi.memmap;
|
||||
void *p, *e;
|
||||
phys_addr_t p, e;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP)) {
|
||||
pr_err_once("EFI_MEMMAP is not enabled.\n");
|
||||
|
@ -282,10 +286,10 @@ int __init efi_mem_desc_lookup(u64 phys_addr, efi_memory_desc_t *out_md)
|
|||
* So just always get our own virtual map on the CPU.
|
||||
*
|
||||
*/
|
||||
md = early_memremap((phys_addr_t)p, sizeof (*md));
|
||||
md = early_memremap(p, sizeof (*md));
|
||||
if (!md) {
|
||||
pr_err_once("early_memremap(%p, %zu) failed.\n",
|
||||
p, sizeof (*md));
|
||||
pr_err_once("early_memremap(%pa, %zu) failed.\n",
|
||||
&p, sizeof (*md));
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -362,6 +366,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
|
|||
{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
|
||||
{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
|
||||
{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
|
||||
{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
|
||||
{NULL_GUID, NULL, NULL},
|
||||
};
|
||||
|
||||
|
@ -421,6 +426,24 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
|
|||
}
|
||||
pr_cont("\n");
|
||||
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
||||
|
||||
/* Parse the EFI Properties table if it exists */
|
||||
if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
|
||||
efi_properties_table_t *tbl;
|
||||
|
||||
tbl = early_memremap(efi.properties_table, sizeof(*tbl));
|
||||
if (tbl == NULL) {
|
||||
pr_err("Could not map Properties table!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (tbl->memory_protection_attribute &
|
||||
EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA)
|
||||
set_bit(EFI_NX_PE_DATA, &efi.flags);
|
||||
|
||||
early_memunmap(tbl, sizeof(*tbl));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -489,7 +512,6 @@ static __initdata struct {
|
|||
};
|
||||
|
||||
struct param_info {
|
||||
int verbose;
|
||||
int found;
|
||||
void *params;
|
||||
};
|
||||
|
@ -520,21 +542,20 @@ static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
|
|||
else
|
||||
*(u64 *)dest = val;
|
||||
|
||||
if (info->verbose)
|
||||
if (efi_enabled(EFI_DBG))
|
||||
pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
|
||||
dt_params[i].size * 2, val);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
|
||||
int __init efi_get_fdt_params(struct efi_fdt_params *params)
|
||||
{
|
||||
struct param_info info;
|
||||
int ret;
|
||||
|
||||
pr_info("Getting EFI parameters from FDT:\n");
|
||||
|
||||
info.verbose = verbose;
|
||||
info.found = 0;
|
||||
info.params = params;
|
||||
|
||||
|
@ -588,16 +609,19 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
|
|||
|
||||
attr = md->attribute;
|
||||
if (attr & ~(EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT |
|
||||
EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP |
|
||||
EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME))
|
||||
EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_RO |
|
||||
EFI_MEMORY_WP | EFI_MEMORY_RP | EFI_MEMORY_XP |
|
||||
EFI_MEMORY_RUNTIME | EFI_MEMORY_MORE_RELIABLE))
|
||||
snprintf(pos, size, "|attr=0x%016llx]",
|
||||
(unsigned long long)attr);
|
||||
else
|
||||
snprintf(pos, size, "|%3s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
|
||||
snprintf(pos, size, "|%3s|%2s|%2s|%2s|%2s|%2s|%3s|%2s|%2s|%2s|%2s]",
|
||||
attr & EFI_MEMORY_RUNTIME ? "RUN" : "",
|
||||
attr & EFI_MEMORY_MORE_RELIABLE ? "MR" : "",
|
||||
attr & EFI_MEMORY_XP ? "XP" : "",
|
||||
attr & EFI_MEMORY_RP ? "RP" : "",
|
||||
attr & EFI_MEMORY_WP ? "WP" : "",
|
||||
attr & EFI_MEMORY_RO ? "RO" : "",
|
||||
attr & EFI_MEMORY_UCE ? "UCE" : "",
|
||||
attr & EFI_MEMORY_WB ? "WB" : "",
|
||||
attr & EFI_MEMORY_WT ? "WT" : "",
|
||||
|
@ -605,3 +629,36 @@ char * __init efi_md_typeattr_format(char *buf, size_t size,
|
|||
attr & EFI_MEMORY_UC ? "UC" : "");
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* efi_mem_attributes - lookup memmap attributes for physical address
|
||||
* @phys_addr: the physical address to lookup
|
||||
*
|
||||
* Search in the EFI memory map for the region covering
|
||||
* @phys_addr. Returns the EFI memory attributes if the region
|
||||
* was found in the memory map, 0 otherwise.
|
||||
*
|
||||
* Despite being marked __weak, most architectures should *not*
|
||||
* override this function. It is __weak solely for the benefit
|
||||
* of ia64 which has a funky EFI memory map that doesn't work
|
||||
* the same way as other architectures.
|
||||
*/
|
||||
u64 __weak efi_mem_attributes(unsigned long phys_addr)
|
||||
{
|
||||
struct efi_memory_map *map;
|
||||
efi_memory_desc_t *md;
|
||||
void *p;
|
||||
|
||||
if (!efi_enabled(EFI_MEMMAP))
|
||||
return 0;
|
||||
|
||||
map = efi.memmap;
|
||||
for (p = map->map; p < map->map_end; p += map->desc_size) {
|
||||
md = p;
|
||||
if ((md->phys_addr <= phys_addr) &&
|
||||
(phys_addr < (md->phys_addr +
|
||||
(md->num_pages << EFI_PAGE_SHIFT))))
|
||||
return md->attribute;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <linux/kobject.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
@ -450,22 +449,10 @@ err:
|
|||
esrt = NULL;
|
||||
return error;
|
||||
}
|
||||
device_initcall(esrt_sysfs_init);
|
||||
|
||||
static void __exit esrt_sysfs_exit(void)
|
||||
{
|
||||
pr_debug("esrt-sysfs: unloading.\n");
|
||||
cleanup_entry_list();
|
||||
kset_unregister(esrt_kset);
|
||||
sysfs_remove_group(esrt_kobj, &esrt_attr_group);
|
||||
kfree(esrt);
|
||||
esrt = NULL;
|
||||
kobject_del(esrt_kobj);
|
||||
kobject_put(esrt_kobj);
|
||||
}
|
||||
|
||||
module_init(esrt_sysfs_init);
|
||||
module_exit(esrt_sysfs_exit);
|
||||
|
||||
/*
|
||||
MODULE_AUTHOR("Peter Jones <pjones@redhat.com>");
|
||||
MODULE_DESCRIPTION("EFI System Resource Table support");
|
||||
MODULE_LICENSE("GPL");
|
||||
*/
|
||||
|
|
238
drivers/firmware/efi/fake_mem.c
Normal file
238
drivers/firmware/efi/fake_mem.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* fake_mem.c
|
||||
*
|
||||
* Copyright (C) 2015 FUJITSU LIMITED
|
||||
* Author: Taku Izumi <izumi.taku@jp.fujitsu.com>
|
||||
*
|
||||
* This code introduces new boot option named "efi_fake_mem"
|
||||
* By specifying this parameter, you can add arbitrary attribute to
|
||||
* specific memory range by updating original (firmware provided) EFI
|
||||
* memmap.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in
|
||||
* the file called "COPYING".
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/sort.h>
|
||||
#include <asm/efi.h>
|
||||
|
||||
#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM
|
||||
|
||||
struct fake_mem {
|
||||
struct range range;
|
||||
u64 attribute;
|
||||
};
|
||||
static struct fake_mem fake_mems[EFI_MAX_FAKEMEM];
|
||||
static int nr_fake_mem;
|
||||
|
||||
static int __init cmp_fake_mem(const void *x1, const void *x2)
|
||||
{
|
||||
const struct fake_mem *m1 = x1;
|
||||
const struct fake_mem *m2 = x2;
|
||||
|
||||
if (m1->range.start < m2->range.start)
|
||||
return -1;
|
||||
if (m1->range.start > m2->range.start)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init efi_fake_memmap(void)
|
||||
{
|
||||
u64 start, end, m_start, m_end, m_attr;
|
||||
int new_nr_map = memmap.nr_map;
|
||||
efi_memory_desc_t *md;
|
||||
phys_addr_t new_memmap_phy;
|
||||
void *new_memmap;
|
||||
void *old, *new;
|
||||
int i;
|
||||
|
||||
if (!nr_fake_mem || !efi_enabled(EFI_MEMMAP))
|
||||
return;
|
||||
|
||||
/* count up the number of EFI memory descriptor */
|
||||
for (old = memmap.map; old < memmap.map_end; old += memmap.desc_size) {
|
||||
md = old;
|
||||
start = md->phys_addr;
|
||||
end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
|
||||
|
||||
for (i = 0; i < nr_fake_mem; i++) {
|
||||
/* modifying range */
|
||||
m_start = fake_mems[i].range.start;
|
||||
m_end = fake_mems[i].range.end;
|
||||
|
||||
if (m_start <= start) {
|
||||
/* split into 2 parts */
|
||||
if (start < m_end && m_end < end)
|
||||
new_nr_map++;
|
||||
}
|
||||
if (start < m_start && m_start < end) {
|
||||
/* split into 3 parts */
|
||||
if (m_end < end)
|
||||
new_nr_map += 2;
|
||||
/* split into 2 parts */
|
||||
if (end <= m_end)
|
||||
new_nr_map++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate memory for new EFI memmap */
|
||||
new_memmap_phy = memblock_alloc(memmap.desc_size * new_nr_map,
|
||||
PAGE_SIZE);
|
||||
if (!new_memmap_phy)
|
||||
return;
|
||||
|
||||
/* create new EFI memmap */
|
||||
new_memmap = early_memremap(new_memmap_phy,
|
||||
memmap.desc_size * new_nr_map);
|
||||
if (!new_memmap) {
|
||||
memblock_free(new_memmap_phy, memmap.desc_size * new_nr_map);
|
||||
return;
|
||||
}
|
||||
|
||||
for (old = memmap.map, new = new_memmap;
|
||||
old < memmap.map_end;
|
||||
old += memmap.desc_size, new += memmap.desc_size) {
|
||||
|
||||
/* copy original EFI memory descriptor */
|
||||
memcpy(new, old, memmap.desc_size);
|
||||
md = new;
|
||||
start = md->phys_addr;
|
||||
end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
|
||||
|
||||
for (i = 0; i < nr_fake_mem; i++) {
|
||||
/* modifying range */
|
||||
m_start = fake_mems[i].range.start;
|
||||
m_end = fake_mems[i].range.end;
|
||||
m_attr = fake_mems[i].attribute;
|
||||
|
||||
if (m_start <= start && end <= m_end)
|
||||
md->attribute |= m_attr;
|
||||
|
||||
if (m_start <= start &&
|
||||
(start < m_end && m_end < end)) {
|
||||
/* first part */
|
||||
md->attribute |= m_attr;
|
||||
md->num_pages = (m_end - md->phys_addr + 1) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
/* latter part */
|
||||
new += memmap.desc_size;
|
||||
memcpy(new, old, memmap.desc_size);
|
||||
md = new;
|
||||
md->phys_addr = m_end + 1;
|
||||
md->num_pages = (end - md->phys_addr + 1) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
if ((start < m_start && m_start < end) && m_end < end) {
|
||||
/* first part */
|
||||
md->num_pages = (m_start - md->phys_addr) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
/* middle part */
|
||||
new += memmap.desc_size;
|
||||
memcpy(new, old, memmap.desc_size);
|
||||
md = new;
|
||||
md->attribute |= m_attr;
|
||||
md->phys_addr = m_start;
|
||||
md->num_pages = (m_end - m_start + 1) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
/* last part */
|
||||
new += memmap.desc_size;
|
||||
memcpy(new, old, memmap.desc_size);
|
||||
md = new;
|
||||
md->phys_addr = m_end + 1;
|
||||
md->num_pages = (end - m_end) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
}
|
||||
|
||||
if ((start < m_start && m_start < end) &&
|
||||
(end <= m_end)) {
|
||||
/* first part */
|
||||
md->num_pages = (m_start - md->phys_addr) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
/* latter part */
|
||||
new += memmap.desc_size;
|
||||
memcpy(new, old, memmap.desc_size);
|
||||
md = new;
|
||||
md->phys_addr = m_start;
|
||||
md->num_pages = (end - md->phys_addr + 1) >>
|
||||
EFI_PAGE_SHIFT;
|
||||
md->attribute |= m_attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* swap into new EFI memmap */
|
||||
efi_unmap_memmap();
|
||||
memmap.map = new_memmap;
|
||||
memmap.phys_map = new_memmap_phy;
|
||||
memmap.nr_map = new_nr_map;
|
||||
memmap.map_end = memmap.map + memmap.nr_map * memmap.desc_size;
|
||||
set_bit(EFI_MEMMAP, &efi.flags);
|
||||
|
||||
/* print new EFI memmap */
|
||||
efi_print_memmap();
|
||||
}
|
||||
|
||||
static int __init setup_fake_mem(char *p)
|
||||
{
|
||||
u64 start = 0, mem_size = 0, attribute = 0;
|
||||
int i;
|
||||
|
||||
if (!p)
|
||||
return -EINVAL;
|
||||
|
||||
while (*p != '\0') {
|
||||
mem_size = memparse(p, &p);
|
||||
if (*p == '@')
|
||||
start = memparse(p+1, &p);
|
||||
else
|
||||
break;
|
||||
|
||||
if (*p == ':')
|
||||
attribute = simple_strtoull(p+1, &p, 0);
|
||||
else
|
||||
break;
|
||||
|
||||
if (nr_fake_mem >= EFI_MAX_FAKEMEM)
|
||||
break;
|
||||
|
||||
fake_mems[nr_fake_mem].range.start = start;
|
||||
fake_mems[nr_fake_mem].range.end = start + mem_size - 1;
|
||||
fake_mems[nr_fake_mem].attribute = attribute;
|
||||
nr_fake_mem++;
|
||||
|
||||
if (*p == ',')
|
||||
p++;
|
||||
}
|
||||
|
||||
sort(fake_mems, nr_fake_mem, sizeof(struct fake_mem),
|
||||
cmp_fake_mem, NULL);
|
||||
|
||||
for (i = 0; i < nr_fake_mem; i++)
|
||||
pr_info("efi_fake_mem: add attr=0x%016llx to [mem 0x%016llx-0x%016llx]",
|
||||
fake_mems[i].attribute, fake_mems[i].range.start,
|
||||
fake_mems[i].range.end);
|
||||
|
||||
return *p == '\0' ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
early_param("efi_fake_mem", setup_fake_mem);
|
|
@ -114,6 +114,20 @@ static int efifb_setup(char *options)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline bool fb_base_is_valid(void)
|
||||
{
|
||||
if (screen_info.lfb_base)
|
||||
return true;
|
||||
|
||||
if (!(screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE))
|
||||
return false;
|
||||
|
||||
if (screen_info.ext_lfb_base)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int efifb_probe(struct platform_device *dev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
|
@ -141,7 +155,7 @@ static int efifb_probe(struct platform_device *dev)
|
|||
screen_info.lfb_depth = 32;
|
||||
if (!screen_info.pages)
|
||||
screen_info.pages = 1;
|
||||
if (!screen_info.lfb_base) {
|
||||
if (!fb_base_is_valid()) {
|
||||
printk(KERN_DEBUG "efifb: invalid framebuffer address\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -160,6 +174,14 @@ static int efifb_probe(struct platform_device *dev)
|
|||
}
|
||||
|
||||
efifb_fix.smem_start = screen_info.lfb_base;
|
||||
|
||||
if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE) {
|
||||
u64 ext_lfb_base;
|
||||
|
||||
ext_lfb_base = (u64)(unsigned long)screen_info.ext_lfb_base << 32;
|
||||
efifb_fix.smem_start |= ext_lfb_base;
|
||||
}
|
||||
|
||||
efifb_defined.bits_per_pixel = screen_info.lfb_depth;
|
||||
efifb_defined.xres = screen_info.lfb_width;
|
||||
efifb_defined.yres = screen_info.lfb_height;
|
||||
|
|
|
@ -99,6 +99,7 @@ typedef struct {
|
|||
#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
|
||||
#define EFI_MEMORY_MORE_RELIABLE \
|
||||
((u64)0x0000000000010000ULL) /* higher reliability */
|
||||
#define EFI_MEMORY_RO ((u64)0x0000000000020000ULL) /* read-only */
|
||||
#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
|
||||
#define EFI_MEMORY_DESCRIPTOR_VERSION 1
|
||||
|
||||
|
@ -595,6 +596,9 @@ void efi_native_runtime_setup(void);
|
|||
#define DEVICE_TREE_GUID \
|
||||
EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
|
||||
|
||||
#define EFI_PROPERTIES_TABLE_GUID \
|
||||
EFI_GUID( 0x880aaca3, 0x4adc, 0x4a04, 0x90, 0x79, 0xb7, 0x47, 0x34, 0x08, 0x25, 0xe5 )
|
||||
|
||||
typedef struct {
|
||||
efi_guid_t guid;
|
||||
u64 table;
|
||||
|
@ -676,7 +680,7 @@ typedef struct {
|
|||
} efi_system_table_t;
|
||||
|
||||
struct efi_memory_map {
|
||||
void *phys_map;
|
||||
phys_addr_t phys_map;
|
||||
void *map;
|
||||
void *map_end;
|
||||
int nr_map;
|
||||
|
@ -808,6 +812,15 @@ typedef struct _efi_file_io_interface {
|
|||
#define EFI_FILE_MODE_WRITE 0x0000000000000002
|
||||
#define EFI_FILE_MODE_CREATE 0x8000000000000000
|
||||
|
||||
typedef struct {
|
||||
u32 version;
|
||||
u32 length;
|
||||
u64 memory_protection_attribute;
|
||||
} efi_properties_table_t;
|
||||
|
||||
#define EFI_PROPERTIES_TABLE_VERSION 0x00010000
|
||||
#define EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA 0x1
|
||||
|
||||
#define EFI_INVALID_TABLE_ADDR (~0UL)
|
||||
|
||||
/*
|
||||
|
@ -830,6 +843,7 @@ extern struct efi {
|
|||
unsigned long runtime; /* runtime table */
|
||||
unsigned long config_table; /* config tables */
|
||||
unsigned long esrt; /* ESRT table */
|
||||
unsigned long properties_table; /* properties table */
|
||||
efi_get_time_t *get_time;
|
||||
efi_set_time_t *set_time;
|
||||
efi_get_wakeup_time_t *get_wakeup_time;
|
||||
|
@ -901,13 +915,19 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,
|
|||
struct resource *data_resource, struct resource *bss_resource);
|
||||
extern void efi_get_time(struct timespec *now);
|
||||
extern void efi_reserve_boot_services(void);
|
||||
extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose);
|
||||
extern int efi_get_fdt_params(struct efi_fdt_params *params);
|
||||
extern struct efi_memory_map memmap;
|
||||
extern struct kobject *efi_kobj;
|
||||
|
||||
extern int efi_reboot_quirk_mode;
|
||||
extern bool efi_poweroff_required(void);
|
||||
|
||||
#ifdef CONFIG_EFI_FAKE_MEMMAP
|
||||
extern void __init efi_fake_memmap(void);
|
||||
#else
|
||||
static inline void efi_fake_memmap(void) { }
|
||||
#endif
|
||||
|
||||
/* Iterate through an efi_memory_map */
|
||||
#define for_each_efi_memory_desc(m, md) \
|
||||
for ((md) = (m)->map; \
|
||||
|
@ -959,6 +979,7 @@ extern int __init efi_setup_pcdp_console(char *);
|
|||
#define EFI_PARAVIRT 6 /* Access is via a paravirt interface */
|
||||
#define EFI_ARCH_1 7 /* First arch-specific bit */
|
||||
#define EFI_DBG 8 /* Print additional debug info at runtime */
|
||||
#define EFI_NX_PE_DATA 9 /* Can runtime data regions be mapped non-executable? */
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
/*
|
||||
|
|
|
@ -43,7 +43,8 @@ struct screen_info {
|
|||
__u16 pages; /* 0x32 */
|
||||
__u16 vesa_attributes; /* 0x34 */
|
||||
__u32 capabilities; /* 0x36 */
|
||||
__u8 _reserved[6]; /* 0x3a */
|
||||
__u32 ext_lfb_base; /* 0x3a */
|
||||
__u8 _reserved[2]; /* 0x3e */
|
||||
} __attribute__((packed));
|
||||
|
||||
#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
|
||||
|
@ -69,6 +70,6 @@ struct screen_info {
|
|||
#define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */
|
||||
|
||||
#define VIDEO_CAPABILITY_SKIP_QUIRKS (1 << 0)
|
||||
|
||||
#define VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit */
|
||||
|
||||
#endif /* _UAPI_SCREEN_INFO_H */
|
||||
|
|
Loading…
Reference in a new issue