[PATCH v2 0/5] Make commonly useful UEFI functions common
This set breaks out some common code from x86/ia64 EFI support code and puts it into drivers/firmware/efi. First it takes the definition of the global efi data structure and moves it into global efi.c. Then it implements a common version of efi_config_init(). Secondly it breaks the efi_lookup_mapped_addr() function out of x86 and places it in global efi.c, for shared use with future ARM patches. IA64 code compile tested only. Leif Lindholm (5): ia64: add early_memremap() alias for early_ioremap() efi: provide a generic efi_config_init() efi: x86: use common code for (U)EFI configuration scanning efi: ia64: use common code for (U)EFI configuration scanning efi: x86: make efi_lookup_mapped_addr() a common function arch/ia64/include/asm/io.h |1 + arch/ia64/kernel/efi.c | 54 - arch/x86/platform/efi/efi.c | 126 --- drivers/firmware/efi/efi.c | 138 +++ include/linux/efi.h |8 +++ 5 files changed, 168 insertions(+), 159 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/5] efi: provide a generic efi_config_init()
Common to (U)EFI support on all platforms is the global efi data structure, and the code that parses the System Table to locate addresses to populate that structure with. This patch adds both of these to the global EFI driver code. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi.c | 106 include/linux/efi.h|7 +++ 2 files changed, 113 insertions(+) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 5145fa3..4fa944a 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -18,6 +18,20 @@ #include linux/init.h #include linux/device.h #include linux/efi.h +#include linux/io.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, + .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, +}; +EXPORT_SYMBOL(efi); static struct kobject *efi_kobj; static struct kobject *efivars_kobj; @@ -132,3 +146,95 @@ err_put: } subsys_initcall(efisubsys_init); + + +static __initdata efi_config_table_type_t common_tables[] = { + {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, + {ACPI_TABLE_GUID, ACPI, efi.acpi}, + {HCDP_TABLE_GUID, HCDP, efi.hcdp}, + {MPS_TABLE_GUID, MPS, efi.mps}, + {SAL_SYSTEM_TABLE_GUID, SALsystab, efi.sal_systab}, + {SMBIOS_TABLE_GUID, SMBIOS, efi.smbios}, + {UGA_IO_PROTOCOL_GUID, UGA, efi.uga}, + {NULL_GUID, NULL, 0}, +}; + +static __init int match_config_table(efi_guid_t *guid, +unsigned long table, +efi_config_table_type_t *table_types) +{ + u8 str[38]; + int i; + + if (table_types) { + efi_guid_unparse(guid, str); + + for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { + efi_guid_unparse(table_types[i].guid, str); + + if (!efi_guidcmp(*guid, table_types[i].guid)) { + *(table_types[i].ptr) = table; + pr_cont( %s=0x%lx , + table_types[i].name, table); + return 1; + } + } + } + + return 0; +} + +int __init efi_config_init(efi_config_table_type_t *arch_tables) +{ + void *config_tables, *tablep; + int i, sz; + + if (efi_enabled(EFI_64BIT)) + sz = sizeof(efi_config_table_64_t); + else + sz = sizeof(efi_config_table_32_t); + + /* +* Let's see what config tables the firmware passed to us. +*/ + config_tables = early_memremap(efi.systab-tables, + efi.systab-nr_tables * sz); + if (config_tables == NULL) { + pr_err(Could not map Configuration table!\n); + return -ENOMEM; + } + + tablep = config_tables; + pr_info(); + for (i = 0; i efi.systab-nr_tables; i++) { + efi_guid_t guid; + unsigned long table; + + if (efi_enabled(EFI_64BIT)) { + u64 table64; + guid = ((efi_config_table_64_t *)tablep)-guid; + table64 = ((efi_config_table_64_t *)tablep)-table; + table = table64; +#ifndef CONFIG_64BIT + if (table64 32) { + pr_cont(\n); + pr_err(Table located above 4GB, disabling EFI.\n); + early_iounmap(config_tables, + efi.systab-nr_tables * sz); + return -EINVAL; + } +#endif + } else { + guid = ((efi_config_table_32_t *)tablep)-guid; + table = ((efi_config_table_32_t *)tablep)-table; + } + + if (!match_config_table(guid, table, common_tables)) + match_config_table(guid, table, arch_tables); + + tablep += sz; + } + pr_cont(\n); + early_iounmap(config_tables, efi.systab-nr_tables * sz); + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 5f8f176..09d9e42 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -404,6 +404,12 @@ typedef struct { unsigned long table; } efi_config_table_t; +typedef struct { + efi_guid_t guid; + const char *name; + unsigned long *ptr; +} efi_config_table_type_t; + #define EFI_SYSTEM_TABLE_SIGNATURE ((u64
[PATCH v2 4/5] efi: ia64: use common code for (U)EFI configuration scanning
This patch makes ia64 use the new common code for configuration table scanning. It also removes the local definition of the global efi data structure. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/ia64/kernel/efi.c | 54 ++-- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 51bce59..da5b462 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -44,10 +44,15 @@ #define EFI_DEBUG 0 +static __initdata unsigned long palo_phys; + +static __initdata efi_config_table_type_t arch_tables[] = { + {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, PALO, palo_phys}, + {NULL_GUID, NULL, 0}, +}; + extern efi_status_t efi_call_phys (void *, ...); -struct efi efi; -EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; @@ -423,9 +428,9 @@ static u8 __init palo_checksum(u8 *buffer, u32 length) * Parse and handle PALO table which is published at: * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf */ -static void __init handle_palo(unsigned long palo_phys) +static void __init handle_palo(unsigned long phys_addr) { - struct palo_table *palo = __va(palo_phys); + struct palo_table *palo = __va(phys_addr); u8 checksum; if (strncmp(palo-signature, PALO_SIG, sizeof(PALO_SIG) - 1)) { @@ -467,12 +472,10 @@ void __init efi_init (void) { void *efi_map_start, *efi_map_end; - efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; char *cp, vendor[100] = unknown; int i; - unsigned long palo_phys; /* * It's too early to be able to use the standard kernel command line @@ -514,8 +517,6 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x); - config_tables = __va(efi.systab-tables); - /* Show what we know for posterity */ c16 = __va(efi.systab-fw_vendor); if (c16) { @@ -528,43 +529,10 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - efi.mps= EFI_INVALID_TABLE_ADDR; - efi.acpi = EFI_INVALID_TABLE_ADDR; - efi.acpi20 = EFI_INVALID_TABLE_ADDR; - efi.smbios = EFI_INVALID_TABLE_ADDR; - efi.sal_systab = EFI_INVALID_TABLE_ADDR; - efi.boot_info = EFI_INVALID_TABLE_ADDR; - efi.hcdp = EFI_INVALID_TABLE_ADDR; - efi.uga= EFI_INVALID_TABLE_ADDR; - palo_phys = EFI_INVALID_TABLE_ADDR; - for (i = 0; i (int) efi.systab-nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = config_tables[i].table; - printk( MPS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = config_tables[i].table; - printk( ACPI 2.0=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = config_tables[i].table; - printk( ACPI=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = config_tables[i].table; - printk( SMBIOS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { - efi.sal_systab = config_tables[i].table; - printk( SALsystab=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = config_tables[i].table; - printk( HCDP=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, -PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) { - palo_phys = config_tables[i].table; - printk( PALO=0x%lx, config_tables[i].table); - } - } - printk(\n); + if (efi_config_init(arch_tables) != 0) + return; if (palo_phys != EFI_INVALID_TABLE_ADDR) handle_palo(palo_phys); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 5/5] efi: x86: make efi_lookup_mapped_addr() a common function
efi_lookup_mapped_addr() is a handy utility for other platforms than x86. Move it from arch/x86 to drivers/firmware. Add memmap pointer to global efi structure, and initialise it on x86. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 30 ++ drivers/firmware/efi/efi.c | 32 include/linux/efi.h |1 + 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ed2be58..fbc1d70 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -393,6 +393,8 @@ int __init efi_memblock_x86_reserve_range(void) memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); + efi.memmap = memmap; + return 0; } @@ -736,34 +738,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md-num_pages EFI_PAGE_SHIFT; - u64 end = md-phys_addr + size; - if (!(md-attribute EFI_MEMORY_RUNTIME) - md-type != EFI_BOOT_SERVICES_CODE - md-type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md-virt_addr) - continue; - if (phys_addr = md-phys_addr phys_addr end) { - phys_addr += md-virt_addr - md-phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - void efi_memory_uc(u64 addr, unsigned long size) { unsigned long page_shift = 1UL EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 4fa944a..afdd1c0 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -148,6 +148,38 @@ err_put: subsys_initcall(efisubsys_init); +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + struct efi_memory_map *map; + void *p; + map = efi.memmap; + if (!map) + return NULL; + if (WARN_ON(!map-map)) + return NULL; + for (p = map-map; p map-map_end; p += map-desc_size) { + efi_memory_desc_t *md = p; + u64 size = md-num_pages EFI_PAGE_SHIFT; + u64 end = md-phys_addr + size; + if (!(md-attribute EFI_MEMORY_RUNTIME) + md-type != EFI_BOOT_SERVICES_CODE + md-type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md-virt_addr) + continue; + if (phys_addr = md-phys_addr phys_addr end) { + phys_addr += md-virt_addr - md-phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} + static __initdata efi_config_table_type_t common_tables[] = { {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, {ACPI_TABLE_GUID, ACPI, efi.acpi}, diff --git a/include/linux/efi.h b/include/linux/efi.h index 09d9e42..c084b6d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -558,6 +558,7 @@ extern struct efi { efi_get_next_high_mono_count_t *get_next_high_mono_count; efi_reset_system_t *reset_system; efi_set_virtual_address_map_t *set_virtual_address_map; + struct efi_memory_map *memmap; } efi; static inline int -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 3/5] efi: x86: use common code for (U)EFI configuration scanning
This patch makes x86 use the new common code for configuration table scanning. It also removes the local definition of the global efi data structure. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 96 --- 1 file changed, 8 insertions(+), 88 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 90f6ed1..ed2be58 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -60,19 +60,6 @@ static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; -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, - .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, -}; -EXPORT_SYMBOL(efi); - struct efi_memory_map memmap; static struct efi efi_phys __initdata; @@ -80,6 +67,13 @@ static efi_system_table_t efi_systab __initdata; unsigned long x86_efi_facility; +static __initdata efi_config_table_type_t arch_tables[] = { +#ifdef CONFIG_X86_UV + {UV_SYSTEM_TABLE_GUID, UVsystab, efi.uv_systab}, +#endif + {NULL_GUID, NULL, 0}, +}; + /* * Returns 1 if 'facility' is enabled, 0 otherwise. */ @@ -578,80 +572,6 @@ static int __init efi_systab_init(void *phys) return 0; } -static int __init efi_config_init(u64 tables, int nr_tables) -{ - void *config_tables, *tablep; - int i, sz; - - if (efi_enabled(EFI_64BIT)) - sz = sizeof(efi_config_table_64_t); - else - sz = sizeof(efi_config_table_32_t); - - /* -* Let's see what config tables the firmware passed to us. -*/ - config_tables = early_ioremap(tables, nr_tables * sz); - if (config_tables == NULL) { - pr_err(Could not map Configuration table!\n); - return -ENOMEM; - } - - tablep = config_tables; - pr_info(); - for (i = 0; i efi.systab-nr_tables; i++) { - efi_guid_t guid; - unsigned long table; - - if (efi_enabled(EFI_64BIT)) { - u64 table64; - guid = ((efi_config_table_64_t *)tablep)-guid; - table64 = ((efi_config_table_64_t *)tablep)-table; - table = table64; -#ifdef CONFIG_X86_32 - if (table64 32) { - pr_cont(\n); - pr_err(Table located above 4GB, disabling EFI.\n); - early_iounmap(config_tables, - efi.systab-nr_tables * sz); - return -EINVAL; - } -#endif - } else { - guid = ((efi_config_table_32_t *)tablep)-guid; - table = ((efi_config_table_32_t *)tablep)-table; - } - if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { - efi.mps = table; - pr_cont( MPS=0x%lx , table); - } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) { - efi.acpi20 = table; - pr_cont( ACPI 2.0=0x%lx , table); - } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) { - efi.acpi = table; - pr_cont( ACPI=0x%lx , table); - } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) { - efi.smbios = table; - pr_cont( SMBIOS=0x%lx , table); -#ifdef CONFIG_X86_UV - } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) { - efi.uv_systab = table; - pr_cont( UVsystab=0x%lx , table); -#endif - } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) { - efi.hcdp = table; - pr_cont( HCDP=0x%lx , table); - } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) { - efi.uga = table; - pr_cont( UGA=0x%lx , table); - } - tablep += sz; - } - pr_cont(\n); - early_iounmap(config_tables, efi.systab-nr_tables * sz); - return 0; -} - static int __init efi_runtime_init(void) { efi_runtime_services_t *runtime; @@ -745,7 +665,7 @@ void __init efi_init(void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - if (efi_config_init(efi.systab-tables, efi.systab-nr_tables)) + if (efi_config_init(arch_tables)) return; set_bit(EFI_CONFIG_TABLES, x86_efi_facility
[PATCH v2 1/5] ia64: add early_memremap() alias for early_ioremap()
early_ioremap() on IA64 chooses its mapping type based on the EFI memory map. This patch adds an alias early_memremap() to be used where the targeted location is memory rather than an i/o device. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/ia64/include/asm/io.h |1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 74a7cc3..0d2bcb3 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h @@ -424,6 +424,7 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size); extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); extern void iounmap (volatile void __iomem *addr); extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); +#define early_memremap(phys_addr, size)early_ioremap(phys_addr, size) extern void early_iounmap (volatile void __iomem *addr, unsigned long size); static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size) { -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 6/7] Add EFI stub for ARM
On Mon, Aug 05, 2013 at 03:11:49PM +0100, Dave Martin wrote: diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 75189f1..4c70b9e 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -122,19 +122,106 @@ .arm@ Always enter in ARM state start: .type start,#function - .rept 7 +#ifdef CONFIG_EFI_STUB + @ Magic MSDOS signature for PE/COFF + ADD opcode + .word 0x62805a4d What about BE32? The ARM bindings for UEFI specify that the processor must be in little-endian mode. In that case, the instruction is a coprocessor load, that loads from a random address to a coprocessor that almost certainly doesn't exist. This will probably fault. Since BE32 is only for older platforms (v6) and this is not easily solvable, it might be sensible to make the EFI stub support depend on !CPU_ENDIAN_BE32. Well, it would make more sense to make EFI_STUB depend on EFI and EFI depend on !CPU_ENDIAN_BE32. Which is something I can add to my next set of general ARM UEFI patches. Thanks. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 2/5] efi: provide a generic efi_config_init()
On Mon, Aug 05, 2013 at 01:15:40PM +0100, Matt Fleming wrote: +static __init int match_config_table(efi_guid_t *guid, +unsigned long table, +efi_config_table_type_t *table_types) +{ + u8 str[38]; Shouldn't this be 37? You get 36 bytes for your GUID, plus a trailing NUL? Either way, this should be a #define. The closest thing we have in include/linux/efi.h is EFI_VARIABLE_GUID_LEN. Perhaps we need a EFI_GUID_LEN that includes the trailing NUL? Err, yes. Don't recall where I decided on that now. I think EFI_VARIABLE_GUID_LEN + 1 makes enough sense. One thing I just noticed that's worth pointing out is that 'pr_fmt' isn't defined in drivers/firmware/efi/efi.c. Before your patch series you get, [0.00] efi: SMBIOS=0xbae41a98 ACPI=0xbac6f000 ACPI 2.0=0xbac6f000 MPS=0xfca90 and after, [0.00] SMBIOS=0xbae41a98 ACPI=0xbac6f000 ACPI 2.0=0xbac6f000 MPS=0xfca90 which isn't the end of the world, but it does mean that the error messages are now much less informative, e.g. I had completely missed that - sorry. Adding in new series. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 16/17] Add EFI stub for ARM
On Wed, Aug 07, 2013 at 07:05:54PM +0100, Dave Martin wrote: Is it possible for this allocation to fail -- i.e., because UEFI has put us in an unsuitable location which is within the first 128MB of RAM, such that we can't pick a suitable location without overlap? For the time being though, I think this is impossible because the decompressed Image can't exceed ~32MB (so the zImage should not exceed that either, and both can fit inside 128MB. It doesn't matter if UEFI's initial load location overlaps the decompressed Image). If UEFI put reserved regions with the first 128MB we're likely to be dead anyway, so we shouldn't assume we'll have to cope with that for now... There is no reason we would be dead unless we end up not being able to allocate regions for FDT and initrd within range. There could be some boot services region lying around, that will be reusable before we even jump to the decompressor. Or there could be some badly placed runtime code lying where it can safely remain. Are there additional kernel regions to worry about? + @ Save return values of efi_entry + stmfd sp!, {r0, r3} + bl cache_clean_flush + bl cache_off Why turn the cache off? Does that mean that EFI may launch images with the cache enabled? Yup. If so, are we guaranteed that VA=PA? Otherwise simply turning the MMU off is not safe. Yes, VA=PA is guaranteed. (Hmm, the UEFI spec seems to suggest yes for these questions) :) / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 1/5] ia64: add early_memremap() alias for early_ioremap()
early_ioremap() on IA64 chooses its mapping type based on the EFI memory map. This patch adds an alias early_memremap() to be used where the targeted location is memory rather than an i/o device. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Tony Luck tony.l...@intel.com --- arch/ia64/include/asm/io.h |1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 74a7cc3..0d2bcb3 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h @@ -424,6 +424,7 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size); extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); extern void iounmap (volatile void __iomem *addr); extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); +#define early_memremap(phys_addr, size)early_ioremap(phys_addr, size) extern void early_iounmap (volatile void __iomem *addr, unsigned long size); static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size) { -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 5/5] efi: x86: make efi_lookup_mapped_addr() a common function
efi_lookup_mapped_addr() is a handy utility for other platforms than x86. Move it from arch/x86 to drivers/firmware. Add memmap pointer to global efi structure, and initialise it on x86. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 30 ++ drivers/firmware/efi/efi.c | 32 include/linux/efi.h |1 + 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ed2be58..fbc1d70 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -393,6 +393,8 @@ int __init efi_memblock_x86_reserve_range(void) memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); + efi.memmap = memmap; + return 0; } @@ -736,34 +738,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md-num_pages EFI_PAGE_SHIFT; - u64 end = md-phys_addr + size; - if (!(md-attribute EFI_MEMORY_RUNTIME) - md-type != EFI_BOOT_SERVICES_CODE - md-type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md-virt_addr) - continue; - if (phys_addr = md-phys_addr phys_addr end) { - phys_addr += md-virt_addr - md-phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - void efi_memory_uc(u64 addr, unsigned long size) { unsigned long page_shift = 1UL EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index e1010d4..2e2fbde 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -150,6 +150,38 @@ err_put: subsys_initcall(efisubsys_init); +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + struct efi_memory_map *map; + void *p; + map = efi.memmap; + if (!map) + return NULL; + if (WARN_ON(!map-map)) + return NULL; + for (p = map-map; p map-map_end; p += map-desc_size) { + efi_memory_desc_t *md = p; + u64 size = md-num_pages EFI_PAGE_SHIFT; + u64 end = md-phys_addr + size; + if (!(md-attribute EFI_MEMORY_RUNTIME) + md-type != EFI_BOOT_SERVICES_CODE + md-type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md-virt_addr) + continue; + if (phys_addr = md-phys_addr phys_addr end) { + phys_addr += md-virt_addr - md-phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} + static __initdata efi_config_table_type_t common_tables[] = { {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, {ACPI_TABLE_GUID, ACPI, efi.acpi}, diff --git a/include/linux/efi.h b/include/linux/efi.h index 09d9e42..c084b6d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -558,6 +558,7 @@ extern struct efi { efi_get_next_high_mono_count_t *get_next_high_mono_count; efi_reset_system_t *reset_system; efi_set_virtual_address_map_t *set_virtual_address_map; + struct efi_memory_map *memmap; } efi; static inline int -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 0/5] Make commonly useful UEFI functions common
This set breaks out some common code from x86/ia64 EFI support code and puts it into drivers/firmware/efi. First it takes the definition of the global efi data structure and moves it into global efi.c. Then it implements a common version of efi_config_init(). Secondly it breaks the efi_lookup_mapped_addr() function out of x86 and places it in global efi.c, for shared use with future ARM patches. IA64 code compile tested only. Leif Lindholm (5): ia64: add early_memremap() alias for early_ioremap() efi: provide a generic efi_config_init() efi: x86: use common code for (U)EFI configuration scanning efi: ia64: use common code for (U)EFI configuration scanning efi: x86: make efi_lookup_mapped_addr() a common function arch/ia64/include/asm/io.h |1 + arch/ia64/kernel/efi.c | 54 - arch/x86/platform/efi/efi.c | 126 -- drivers/firmware/efi/efi.c | 140 +++ include/linux/efi.h |8 +++ 5 files changed, 170 insertions(+), 159 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 4/5] efi: ia64: use common code for (U)EFI configuration scanning
This patch makes ia64 use the new common code for configuration table scanning. It also removes the local definition of the global efi data structure. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Tony Luck tony.l...@intel.com --- arch/ia64/kernel/efi.c | 54 ++-- 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 51bce59..da5b462 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -44,10 +44,15 @@ #define EFI_DEBUG 0 +static __initdata unsigned long palo_phys; + +static __initdata efi_config_table_type_t arch_tables[] = { + {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, PALO, palo_phys}, + {NULL_GUID, NULL, 0}, +}; + extern efi_status_t efi_call_phys (void *, ...); -struct efi efi; -EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; @@ -423,9 +428,9 @@ static u8 __init palo_checksum(u8 *buffer, u32 length) * Parse and handle PALO table which is published at: * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf */ -static void __init handle_palo(unsigned long palo_phys) +static void __init handle_palo(unsigned long phys_addr) { - struct palo_table *palo = __va(palo_phys); + struct palo_table *palo = __va(phys_addr); u8 checksum; if (strncmp(palo-signature, PALO_SIG, sizeof(PALO_SIG) - 1)) { @@ -467,12 +472,10 @@ void __init efi_init (void) { void *efi_map_start, *efi_map_end; - efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; char *cp, vendor[100] = unknown; int i; - unsigned long palo_phys; /* * It's too early to be able to use the standard kernel command line @@ -514,8 +517,6 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x); - config_tables = __va(efi.systab-tables); - /* Show what we know for posterity */ c16 = __va(efi.systab-fw_vendor); if (c16) { @@ -528,43 +529,10 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - efi.mps= EFI_INVALID_TABLE_ADDR; - efi.acpi = EFI_INVALID_TABLE_ADDR; - efi.acpi20 = EFI_INVALID_TABLE_ADDR; - efi.smbios = EFI_INVALID_TABLE_ADDR; - efi.sal_systab = EFI_INVALID_TABLE_ADDR; - efi.boot_info = EFI_INVALID_TABLE_ADDR; - efi.hcdp = EFI_INVALID_TABLE_ADDR; - efi.uga= EFI_INVALID_TABLE_ADDR; - palo_phys = EFI_INVALID_TABLE_ADDR; - for (i = 0; i (int) efi.systab-nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = config_tables[i].table; - printk( MPS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = config_tables[i].table; - printk( ACPI 2.0=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = config_tables[i].table; - printk( ACPI=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = config_tables[i].table; - printk( SMBIOS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { - efi.sal_systab = config_tables[i].table; - printk( SALsystab=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = config_tables[i].table; - printk( HCDP=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, -PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) { - palo_phys = config_tables[i].table; - printk( PALO=0x%lx, config_tables[i].table); - } - } - printk(\n); + if (efi_config_init(arch_tables) != 0) + return; if (palo_phys != EFI_INVALID_TABLE_ADDR) handle_palo(palo_phys); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 3/5] efi: x86: use common code for (U)EFI configuration scanning
This patch makes x86 use the new common code for configuration table scanning. It also removes the local definition of the global efi data structure. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 96 --- 1 file changed, 8 insertions(+), 88 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 90f6ed1..ed2be58 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -60,19 +60,6 @@ static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; -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, - .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, -}; -EXPORT_SYMBOL(efi); - struct efi_memory_map memmap; static struct efi efi_phys __initdata; @@ -80,6 +67,13 @@ static efi_system_table_t efi_systab __initdata; unsigned long x86_efi_facility; +static __initdata efi_config_table_type_t arch_tables[] = { +#ifdef CONFIG_X86_UV + {UV_SYSTEM_TABLE_GUID, UVsystab, efi.uv_systab}, +#endif + {NULL_GUID, NULL, 0}, +}; + /* * Returns 1 if 'facility' is enabled, 0 otherwise. */ @@ -578,80 +572,6 @@ static int __init efi_systab_init(void *phys) return 0; } -static int __init efi_config_init(u64 tables, int nr_tables) -{ - void *config_tables, *tablep; - int i, sz; - - if (efi_enabled(EFI_64BIT)) - sz = sizeof(efi_config_table_64_t); - else - sz = sizeof(efi_config_table_32_t); - - /* -* Let's see what config tables the firmware passed to us. -*/ - config_tables = early_ioremap(tables, nr_tables * sz); - if (config_tables == NULL) { - pr_err(Could not map Configuration table!\n); - return -ENOMEM; - } - - tablep = config_tables; - pr_info(); - for (i = 0; i efi.systab-nr_tables; i++) { - efi_guid_t guid; - unsigned long table; - - if (efi_enabled(EFI_64BIT)) { - u64 table64; - guid = ((efi_config_table_64_t *)tablep)-guid; - table64 = ((efi_config_table_64_t *)tablep)-table; - table = table64; -#ifdef CONFIG_X86_32 - if (table64 32) { - pr_cont(\n); - pr_err(Table located above 4GB, disabling EFI.\n); - early_iounmap(config_tables, - efi.systab-nr_tables * sz); - return -EINVAL; - } -#endif - } else { - guid = ((efi_config_table_32_t *)tablep)-guid; - table = ((efi_config_table_32_t *)tablep)-table; - } - if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { - efi.mps = table; - pr_cont( MPS=0x%lx , table); - } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) { - efi.acpi20 = table; - pr_cont( ACPI 2.0=0x%lx , table); - } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) { - efi.acpi = table; - pr_cont( ACPI=0x%lx , table); - } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) { - efi.smbios = table; - pr_cont( SMBIOS=0x%lx , table); -#ifdef CONFIG_X86_UV - } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) { - efi.uv_systab = table; - pr_cont( UVsystab=0x%lx , table); -#endif - } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) { - efi.hcdp = table; - pr_cont( HCDP=0x%lx , table); - } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) { - efi.uga = table; - pr_cont( UGA=0x%lx , table); - } - tablep += sz; - } - pr_cont(\n); - early_iounmap(config_tables, efi.systab-nr_tables * sz); - return 0; -} - static int __init efi_runtime_init(void) { efi_runtime_services_t *runtime; @@ -745,7 +665,7 @@ void __init efi_init(void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - if (efi_config_init(efi.systab-tables, efi.systab-nr_tables)) + if (efi_config_init(arch_tables)) return; set_bit(EFI_CONFIG_TABLES, x86_efi_facility
[PATCH v3 2/5] efi: provide a generic efi_config_init()
Common to (U)EFI support on all platforms is the global efi data structure, and the code that parses the System Table to locate addresses to populate that structure with. This patch adds both of these to the global EFI driver code. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi.c | 108 include/linux/efi.h|7 +++ 2 files changed, 115 insertions(+) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 5145fa3..e1010d4 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -13,11 +13,27 @@ * This file is released under the GPLv2. */ +#define pr_fmt(fmt) KBUILD_MODNAME : fmt + #include linux/kobject.h #include linux/module.h #include linux/init.h #include linux/device.h #include linux/efi.h +#include linux/io.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, + .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, +}; +EXPORT_SYMBOL(efi); static struct kobject *efi_kobj; static struct kobject *efivars_kobj; @@ -132,3 +148,95 @@ err_put: } subsys_initcall(efisubsys_init); + + +static __initdata efi_config_table_type_t common_tables[] = { + {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, + {ACPI_TABLE_GUID, ACPI, efi.acpi}, + {HCDP_TABLE_GUID, HCDP, efi.hcdp}, + {MPS_TABLE_GUID, MPS, efi.mps}, + {SAL_SYSTEM_TABLE_GUID, SALsystab, efi.sal_systab}, + {SMBIOS_TABLE_GUID, SMBIOS, efi.smbios}, + {UGA_IO_PROTOCOL_GUID, UGA, efi.uga}, + {NULL_GUID, NULL, 0}, +}; + +static __init int match_config_table(efi_guid_t *guid, +unsigned long table, +efi_config_table_type_t *table_types) +{ + u8 str[EFI_VARIABLE_GUID_LEN + 1]; + int i; + + if (table_types) { + efi_guid_unparse(guid, str); + + for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { + efi_guid_unparse(table_types[i].guid, str); + + if (!efi_guidcmp(*guid, table_types[i].guid)) { + *(table_types[i].ptr) = table; + pr_cont( %s=0x%lx , + table_types[i].name, table); + return 1; + } + } + } + + return 0; +} + +int __init efi_config_init(efi_config_table_type_t *arch_tables) +{ + void *config_tables, *tablep; + int i, sz; + + if (efi_enabled(EFI_64BIT)) + sz = sizeof(efi_config_table_64_t); + else + sz = sizeof(efi_config_table_32_t); + + /* +* Let's see what config tables the firmware passed to us. +*/ + config_tables = early_memremap(efi.systab-tables, + efi.systab-nr_tables * sz); + if (config_tables == NULL) { + pr_err(Could not map Configuration table!\n); + return -ENOMEM; + } + + tablep = config_tables; + pr_info(); + for (i = 0; i efi.systab-nr_tables; i++) { + efi_guid_t guid; + unsigned long table; + + if (efi_enabled(EFI_64BIT)) { + u64 table64; + guid = ((efi_config_table_64_t *)tablep)-guid; + table64 = ((efi_config_table_64_t *)tablep)-table; + table = table64; +#ifndef CONFIG_64BIT + if (table64 32) { + pr_cont(\n); + pr_err(Table located above 4GB, disabling EFI.\n); + early_iounmap(config_tables, + efi.systab-nr_tables * sz); + return -EINVAL; + } +#endif + } else { + guid = ((efi_config_table_32_t *)tablep)-guid; + table = ((efi_config_table_32_t *)tablep)-table; + } + + if (!match_config_table(guid, table, common_tables)) + match_config_table(guid, table, arch_tables); + + tablep += sz; + } + pr_cont(\n); + early_iounmap(config_tables, efi.systab-nr_tables * sz); + return 0; +} diff --git a/include/linux/efi.h b/include/linux/efi.h index 5f8f176..09d9e42 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -404,6 +404,12 @@ typedef struct { unsigned long table; } efi_config_table_t; +typedef struct
Re: [PATCH v2 2/2] arm: add early_ioremap support
On Fri, Sep 06, 2013 at 05:14:49PM +0100, Catalin Marinas wrote: On Fri, Sep 06, 2013 at 10:19:18AM +0100, Leif Lindholm wrote: --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -877,6 +878,10 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); +#ifdef CONFIG_EARLY_IOREMAP + early_ioremap_init(); +#endif Better with a dummy early_ioremap_init() in the header when !CONFIG_EARLY_IOREMAP to avoid the #ifdef here. Ok, makes sense. --- /dev/null +++ b/arch/arm/mm/early_ioremap.c @@ -0,0 +1,271 @@ +/* + * early_ioremap() support for ARM + * + * Based on existing support in arch/x86/mm/ioremap.c At a very quick look, this looks really close to the x86 implementation. Any reason why this cannot be made generic and avoid duplication? Mainly that the bits that can be easily shared aren't really the interesting ones. Making it properly shared would require a rewrite of ARM kmap(). / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/4] Make commonly useful UEFI functions common
This set breaks out some common code from x86/ia64 EFI support code and puts it into drivers/firmware/efi. First it takes the definition of the global efi data structure and moves it into global efi.c. Then it implements a common version of efi_config_init(). Secondly it breaks the efi_lookup_mapped_addr() function out of x86 and places it in global efi.c, for shared use with future ARM patches. IA64 code compile tested only. Pardon the delay in getting this out - back to back conferences followed by a bad case of the man flu. Leif Lindholm (4): efi: provide a generic efi_config_init() efi: x86: use common code for (U)EFI configuration scanning efi: ia64: use common code for (U)EFI configuration scanning efi: x86: make efi_lookup_mapped_addr() a common function arch/ia64/include/asm/io.h |1 + arch/ia64/kernel/efi.c | 54 - arch/x86/platform/efi/efi.c | 124 +++ drivers/firmware/efi/efi.c | 136 +++ include/linux/efi.h |7 +++ 5 files changed, 163 insertions(+), 159 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/4] efi: x86: use common code for (U)EFI configuration scanning
This patch makes x86 use the new common code for EFI configuration table scanning. It also removes the local definition of the global efi data structure. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 96 --- 1 file changed, 8 insertions(+), 88 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 90f6ed1..ed2be58 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -60,19 +60,6 @@ static efi_char16_t efi_dummy_name[6] = { 'D', 'U', 'M', 'M', 'Y', 0 }; -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, - .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, -}; -EXPORT_SYMBOL(efi); - struct efi_memory_map memmap; static struct efi efi_phys __initdata; @@ -80,6 +67,13 @@ static efi_system_table_t efi_systab __initdata; unsigned long x86_efi_facility; +static __initdata efi_config_table_type_t arch_tables[] = { +#ifdef CONFIG_X86_UV + {UV_SYSTEM_TABLE_GUID, UVsystab, efi.uv_systab}, +#endif + {NULL_GUID, NULL, 0}, +}; + /* * Returns 1 if 'facility' is enabled, 0 otherwise. */ @@ -578,80 +572,6 @@ static int __init efi_systab_init(void *phys) return 0; } -static int __init efi_config_init(u64 tables, int nr_tables) -{ - void *config_tables, *tablep; - int i, sz; - - if (efi_enabled(EFI_64BIT)) - sz = sizeof(efi_config_table_64_t); - else - sz = sizeof(efi_config_table_32_t); - - /* -* Let's see what config tables the firmware passed to us. -*/ - config_tables = early_ioremap(tables, nr_tables * sz); - if (config_tables == NULL) { - pr_err(Could not map Configuration table!\n); - return -ENOMEM; - } - - tablep = config_tables; - pr_info(); - for (i = 0; i efi.systab-nr_tables; i++) { - efi_guid_t guid; - unsigned long table; - - if (efi_enabled(EFI_64BIT)) { - u64 table64; - guid = ((efi_config_table_64_t *)tablep)-guid; - table64 = ((efi_config_table_64_t *)tablep)-table; - table = table64; -#ifdef CONFIG_X86_32 - if (table64 32) { - pr_cont(\n); - pr_err(Table located above 4GB, disabling EFI.\n); - early_iounmap(config_tables, - efi.systab-nr_tables * sz); - return -EINVAL; - } -#endif - } else { - guid = ((efi_config_table_32_t *)tablep)-guid; - table = ((efi_config_table_32_t *)tablep)-table; - } - if (!efi_guidcmp(guid, MPS_TABLE_GUID)) { - efi.mps = table; - pr_cont( MPS=0x%lx , table); - } else if (!efi_guidcmp(guid, ACPI_20_TABLE_GUID)) { - efi.acpi20 = table; - pr_cont( ACPI 2.0=0x%lx , table); - } else if (!efi_guidcmp(guid, ACPI_TABLE_GUID)) { - efi.acpi = table; - pr_cont( ACPI=0x%lx , table); - } else if (!efi_guidcmp(guid, SMBIOS_TABLE_GUID)) { - efi.smbios = table; - pr_cont( SMBIOS=0x%lx , table); -#ifdef CONFIG_X86_UV - } else if (!efi_guidcmp(guid, UV_SYSTEM_TABLE_GUID)) { - efi.uv_systab = table; - pr_cont( UVsystab=0x%lx , table); -#endif - } else if (!efi_guidcmp(guid, HCDP_TABLE_GUID)) { - efi.hcdp = table; - pr_cont( HCDP=0x%lx , table); - } else if (!efi_guidcmp(guid, UGA_IO_PROTOCOL_GUID)) { - efi.uga = table; - pr_cont( UGA=0x%lx , table); - } - tablep += sz; - } - pr_cont(\n); - early_iounmap(config_tables, efi.systab-nr_tables * sz); - return 0; -} - static int __init efi_runtime_init(void) { efi_runtime_services_t *runtime; @@ -745,7 +665,7 @@ void __init efi_init(void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - if (efi_config_init(efi.systab-tables, efi.systab-nr_tables)) + if (efi_config_init(arch_tables)) return; set_bit(EFI_CONFIG_TABLES, x86_efi_facility
[PATCH 4/4] efi: x86: make efi_lookup_mapped_addr() a common function
efi_lookup_mapped_addr() is a handy utility for other platforms than x86. Move it from arch/x86 to drivers/firmware/efi. This function will be used by future ARM patches. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 28 drivers/firmware/efi/efi.c | 30 ++ 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ed2be58..3af9d36 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -736,34 +736,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md-num_pages EFI_PAGE_SHIFT; - u64 end = md-phys_addr + size; - if (!(md-attribute EFI_MEMORY_RUNTIME) - md-type != EFI_BOOT_SERVICES_CODE - md-type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md-virt_addr) - continue; - if (phys_addr = md-phys_addr phys_addr end) { - phys_addr += md-virt_addr - md-phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - void efi_memory_uc(u64 addr, unsigned long size) { unsigned long page_shift = 1UL EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 4fa944a..94f57c0 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -148,6 +148,36 @@ err_put: subsys_initcall(efisubsys_init); +#if defined(CONFIG_X86) +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + void *p; + if (WARN_ON(!memmap.map)) + return NULL; + for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { + efi_memory_desc_t *md = p; + u64 size = md-num_pages EFI_PAGE_SHIFT; + u64 end = md-phys_addr + size; + if (!(md-attribute EFI_MEMORY_RUNTIME) + md-type != EFI_BOOT_SERVICES_CODE + md-type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md-virt_addr) + continue; + if (phys_addr = md-phys_addr phys_addr end) { + phys_addr += md-virt_addr - md-phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} +#endif + static __initdata efi_config_table_type_t common_tables[] = { {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, {ACPI_TABLE_GUID, ACPI, efi.acpi}, -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/4] efi: provide a generic efi_config_init()
Common to (U)EFI support on all platforms is the global efi data structure, and the code that parses the System Table to locate addresses to populate that structure with. This patch adds both of these to the global EFI driver code. Since existing code for both x86 and ia64 contained handling of tables specific to the respective platform, efi_config_init() takes an optional pointer to a list of valid architecture-specific tables and pointers to populate on comparison hit. Patches removing the original platform-specific code and moving those platforms to using the below code follow later in the series. Note: use of early_memremap() instead of early_ioremap() for better semantic match for ARM support. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi.c | 106 include/linux/efi.h|7 +++ 2 files changed, 113 insertions(+) diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 5145fa3..4fa944a 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -18,6 +18,20 @@ #include linux/init.h #include linux/device.h #include linux/efi.h +#include linux/io.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, + .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, +}; +EXPORT_SYMBOL(efi); static struct kobject *efi_kobj; static struct kobject *efivars_kobj; @@ -132,3 +146,95 @@ err_put: } subsys_initcall(efisubsys_init); + + +static __initdata efi_config_table_type_t common_tables[] = { + {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, + {ACPI_TABLE_GUID, ACPI, efi.acpi}, + {HCDP_TABLE_GUID, HCDP, efi.hcdp}, + {MPS_TABLE_GUID, MPS, efi.mps}, + {SAL_SYSTEM_TABLE_GUID, SALsystab, efi.sal_systab}, + {SMBIOS_TABLE_GUID, SMBIOS, efi.smbios}, + {UGA_IO_PROTOCOL_GUID, UGA, efi.uga}, + {NULL_GUID, NULL, 0}, +}; + +static __init int match_config_table(efi_guid_t *guid, +unsigned long table, +efi_config_table_type_t *table_types) +{ + u8 str[38]; + int i; + + if (table_types) { + efi_guid_unparse(guid, str); + + for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) { + efi_guid_unparse(table_types[i].guid, str); + + if (!efi_guidcmp(*guid, table_types[i].guid)) { + *(table_types[i].ptr) = table; + pr_cont( %s=0x%lx , + table_types[i].name, table); + return 1; + } + } + } + + return 0; +} + +int __init efi_config_init(efi_config_table_type_t *arch_tables) +{ + void *config_tables, *tablep; + int i, sz; + + if (efi_enabled(EFI_64BIT)) + sz = sizeof(efi_config_table_64_t); + else + sz = sizeof(efi_config_table_32_t); + + /* +* Let's see what config tables the firmware passed to us. +*/ + config_tables = early_memremap(efi.systab-tables, + efi.systab-nr_tables * sz); + if (config_tables == NULL) { + pr_err(Could not map Configuration table!\n); + return -ENOMEM; + } + + tablep = config_tables; + pr_info(); + for (i = 0; i efi.systab-nr_tables; i++) { + efi_guid_t guid; + unsigned long table; + + if (efi_enabled(EFI_64BIT)) { + u64 table64; + guid = ((efi_config_table_64_t *)tablep)-guid; + table64 = ((efi_config_table_64_t *)tablep)-table; + table = table64; +#ifndef CONFIG_64BIT + if (table64 32) { + pr_cont(\n); + pr_err(Table located above 4GB, disabling EFI.\n); + early_iounmap(config_tables, + efi.systab-nr_tables * sz); + return -EINVAL; + } +#endif + } else { + guid = ((efi_config_table_32_t *)tablep)-guid; + table = ((efi_config_table_32_t *)tablep)-table; + } + + if (!match_config_table(guid, table, common_tables)) + match_config_table(guid, table, arch_tables); + + tablep += sz; + } + pr_cont(\n); + early_iounmap
[PATCH 3/4] efi: ia64: use common code for (U)EFI configuration scanning
This patch makes ia64 use the new common code for configuration table scanning. It also removes the local definition of the global efi data structure. Introduces an early_memremap() alias for early_ioremap(), which should be fine given that early_ioremap() parses the memory map for determining type of mapping anyway. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/ia64/include/asm/io.h |1 + arch/ia64/kernel/efi.c | 54 +--- 2 files changed, 12 insertions(+), 43 deletions(-) diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 74a7cc3..c439d28 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h @@ -424,6 +424,7 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size); extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); extern void iounmap (volatile void __iomem *addr); extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); +#define early_memremap(phys_addr, size)early_ioremap(phys_addr, size) extern void early_iounmap (volatile void __iomem *addr, unsigned long size); static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size) { diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 51bce59..da5b462 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -44,10 +44,15 @@ #define EFI_DEBUG 0 +static __initdata unsigned long palo_phys; + +static __initdata efi_config_table_type_t arch_tables[] = { + {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, PALO, palo_phys}, + {NULL_GUID, NULL, 0}, +}; + extern efi_status_t efi_call_phys (void *, ...); -struct efi efi; -EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; @@ -423,9 +428,9 @@ static u8 __init palo_checksum(u8 *buffer, u32 length) * Parse and handle PALO table which is published at: * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf */ -static void __init handle_palo(unsigned long palo_phys) +static void __init handle_palo(unsigned long phys_addr) { - struct palo_table *palo = __va(palo_phys); + struct palo_table *palo = __va(phys_addr); u8 checksum; if (strncmp(palo-signature, PALO_SIG, sizeof(PALO_SIG) - 1)) { @@ -467,12 +472,10 @@ void __init efi_init (void) { void *efi_map_start, *efi_map_end; - efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; char *cp, vendor[100] = unknown; int i; - unsigned long palo_phys; /* * It's too early to be able to use the standard kernel command line @@ -514,8 +517,6 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x); - config_tables = __va(efi.systab-tables); - /* Show what we know for posterity */ c16 = __va(efi.systab-fw_vendor); if (c16) { @@ -528,43 +529,10 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - efi.mps= EFI_INVALID_TABLE_ADDR; - efi.acpi = EFI_INVALID_TABLE_ADDR; - efi.acpi20 = EFI_INVALID_TABLE_ADDR; - efi.smbios = EFI_INVALID_TABLE_ADDR; - efi.sal_systab = EFI_INVALID_TABLE_ADDR; - efi.boot_info = EFI_INVALID_TABLE_ADDR; - efi.hcdp = EFI_INVALID_TABLE_ADDR; - efi.uga= EFI_INVALID_TABLE_ADDR; - palo_phys = EFI_INVALID_TABLE_ADDR; - for (i = 0; i (int) efi.systab-nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = config_tables[i].table; - printk( MPS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = config_tables[i].table; - printk( ACPI 2.0=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = config_tables[i].table; - printk( ACPI=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = config_tables[i].table; - printk( SMBIOS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { - efi.sal_systab = config_tables[i].table; - printk( SALsystab=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = config_tables[i].table; - printk( HCDP=0x
Re: [PATCH 1/4] efi: provide a generic efi_config_init()
On Tue, Jul 30, 2013 at 10:53:10AM -0700, Tony Luck wrote: On Tue, Jul 30, 2013 at 9:47 AM, Leif Lindholm leif.lindh...@linaro.org wrote: + /* +* Let's see what config tables the firmware passed to us. +*/ + config_tables = early_mememap(efi.systab-tables, + efi.systab-nr_tables * sz); Breaks bisection on ia64 ... you use early_mememap() here, but don't define it on ia64 until patch 3/4. So I get: Ugh, OK. So I guess the clean way to deal with that would be to make the memremap definition a separate patch? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/4] efi: x86: make efi_lookup_mapped_addr() a common function
On Wed, Jul 31, 2013 at 09:58:20AM +0100, Matt Fleming wrote: On 07/30/2013 05:47 PM, Leif Lindholm wrote: efi_lookup_mapped_addr() is a handy utility for other platforms than x86. Move it from arch/x86 to drivers/firmware/efi. This function will be used by future ARM patches. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 28 drivers/firmware/efi/efi.c | 30 ++ 2 files changed, 30 insertions(+), 28 deletions(-) [...] +#if defined(CONFIG_X86) +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + void *p; + if (WARN_ON(!memmap.map)) + return NULL; + for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { + efi_memory_desc_t *md = p; + u64 size = md-num_pages EFI_PAGE_SHIFT; + u64 end = md-phys_addr + size; + if (!(md-attribute EFI_MEMORY_RUNTIME) + md-type != EFI_BOOT_SERVICES_CODE + md-type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md-virt_addr) + continue; + if (phys_addr = md-phys_addr phys_addr end) { + phys_addr += md-virt_addr - md-phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} +#endif + If we hang a 'struct efi_memory_map' off of 'struct efi', can we get rid of this #ifdef? Sure. It would just be a small bit of wasted memory for IA64 (struct + code). On the flip side, having that on all platforms could lend itself to making a little bit more code common. Tony? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Is: Wrap-up Was: Re: EFI and multiboot2 devlopment work for Xen
On Mon, Nov 04, 2013 at 08:41:11PM +, Stefano Stabellini wrote: multiboot2 protocol requires some more changes. However, about 80% of code is ready. In this case Xen and modules are loaded by GRUB2 itself. It means that all images could be placed on any filesystem recognized by GRUB2. Options for Xen and modules are passed separately which simplifies command line editing in boot loader and parsing. multiboot2 protocol is very flexible and could be easily extended in the future if a need arises. Support for secure boot and shim loader could be added. However, it was not implemented yet. Probably linuxefi module could be used as a reference or even as a base for development. However, I do not know are there plans to support such solution by GRUB2 community. Currently, support for native PE images signatures and GPG signatures is under development for GRUB2 upstream. FYI on ARM it is possible to load a kernel as PE but at the same time passing additional info as where the initrd or other additional binaries have been loaded or even command line arguments. These info are passed from the bootloader to the kernel via Device Tree. Grant (CC'ed) might be able to add additional details on where the code actually lives. The code currently lives in unclean form in my development tree on git.linaro.org. We had a few items on the kernel boot protocol to sort out at last week's Linaro Connect, and if I hadn't been struck down with conference flu, I would probably have sent out the basic arm64 support by now. The method used (for the curious) is to simply register an FDT as a configuration table, and then look for that in the stub. That code should be trivially portable to 32-bit ARM. I did start out from the linuxefi code, but that was quite x86 specific, and was also dependent on the shim, so I ended up changing most of it (for now). I would still like to see a unified (upstream) linuxefi module for loading the kernel as the UEFI stub (with architecture-specific bits extracted out under loader/arch). The UEFI stub loader will then call ExitBootServices(), not GRUB. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 1/2] Documentation: arm: early_ioremap/early_memremap
This patch provides documentation of the early_ioremap() and early_memremap() functionality,including its implementation and usage instructions. Cc: linux-...@vger.kernel.org Cc: Nicolas Pitre n...@linaro.org Cc: Arnd Bergman a...@arndb.de Cc: Catalin Marinas catalin.mari...@arm.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Rob Landley r...@landley.net --- Documentation/arm/00-INDEX |2 ++ Documentation/arm/early_ioremap.txt | 23 +++ 2 files changed, 25 insertions(+) create mode 100644 Documentation/arm/early_ioremap.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 36420e1..4978456 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -24,6 +24,8 @@ SPEAr - ST SPEAr platform Linux Overview VFP/ - Release notes for Linux Kernel Vector Floating Point support code +early_ioremap.txt + - documentation of the early_ioremap() functionality empeg/ - Ltd's Empeg MP3 Car Audio Player mem_alignment diff --git a/Documentation/arm/early_ioremap.txt b/Documentation/arm/early_ioremap.txt new file mode 100644 index 000..6096cfa --- /dev/null +++ b/Documentation/arm/early_ioremap.txt @@ -0,0 +1,23 @@ +early_ioremap()/early_memremap() and early_iounmap() provide a mechanism for +temporarily mapping in small blocks of memory, identified by their physical +address, into the fixmap virtual address block before paging_init() has run +and more flexible mapping functions are available. + +Due to its direct method, it also gets around potential need for special +handling of regions that end up in highmem. + +It supports up to 7 simultaneously mapped regions of up to 128KB each. +All mappings created by early_ioremap() are non-shareable device memory. +All mappings created by early_memremap() are uncached normal memory. + +Any residual mappings will be overridden by subsequent kmap() calls (but do +use early_iounmap()). + +Specify 'early_ioremap_debug' on the kernel commandline for verbose output. + +SYNOPSIS + #include linux/io.h + + void *early_ioremap(resource_size_t phys_addr, unsigned long size); + void *early_memremap(resource_size_t phys_addr, unsigned long size); + void early_iounmap(void *addr, unsigned long size); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 0/2] arm: add early_ioremap support
This patch adds support for early_ioremap and early_memremap, based on the existing mechanism in x86. Up to 7 regions of up to 128KB each can be temporarily mapped in before paging_init, regardless of later highmem status. New for this version: - Addressed feedback on v2 - *cough* corrected early_memremap() to use MT_WRITEALLOC instead of MT_UNCACHED. Cc: Nicolas Pitre n...@linaro.org Cc: Arnd Bergman a...@arndb.de Cc: Catalin Marinas catalin.mari...@arm.com Leif Lindholm (2): Documentation: arm: early_ioremap/early_memremap arm: add early_ioremap support Documentation/arm/00-INDEX |2 + Documentation/arm/early_ioremap.txt | 23 +++ arch/arm/Kconfig|9 ++ arch/arm/include/asm/fixmap.h | 29 +++- arch/arm/include/asm/io.h | 23 +++ arch/arm/kernel/setup.c |3 + arch/arm/mm/Makefile|1 + arch/arm/mm/early_ioremap.c | 271 +++ arch/arm/mm/mmu.c |2 + 9 files changed, 362 insertions(+), 1 deletion(-) create mode 100644 Documentation/arm/early_ioremap.txt create mode 100644 arch/arm/mm/early_ioremap.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 2/2] arm: add early_ioremap support
This patch adds support for early_ioremap, based on the existing mechanism in x86. Up to 7 regions of up to 128KB each can be temporarily mapped in before paging_init, regardless of later highmem status. Cc: Nicolas Pitre n...@linaro.org Cc: Arnd Bergman a...@arndb.de Cc: Catalin Marinas catalin.mari...@arm.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig |9 ++ arch/arm/include/asm/fixmap.h | 29 - arch/arm/include/asm/io.h | 23 arch/arm/kernel/setup.c |3 + arch/arm/mm/Makefile |1 + arch/arm/mm/early_ioremap.c | 271 + arch/arm/mm/mmu.c |2 + 7 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mm/early_ioremap.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1ad6fb6..5916a90 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1846,6 +1846,15 @@ config UACCESS_WITH_MEMCPY However, if the CPU data cache is using a write-allocate mode, this option is unlikely to provide any performance gain. +config EARLY_IOREMAP + bool Provide early_ioremap() support for kernel initialization. + depends on MMU + help + Provides a mechanism for kernel initialisation code to temporarily + map, in a highmem-agnostic way, memory pages in before paging_init(). + It generates its map entries in kmap region (0xfff0) before kmap + is initialized. + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index bbae919..8b2507e 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -1,6 +1,8 @@ #ifndef _ASM_FIXMAP_H #define _ASM_FIXMAP_H +#include linux/bug.h + /* * Nothing too fancy for now. * @@ -20,13 +22,38 @@ #define FIX_KMAP_BEGIN 0 #define FIX_KMAP_END (FIXADDR_SIZE PAGE_SHIFT) +/* + * 224 temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + * + * (P)re-using the FIXADDR region, which is used for highmem + * later on, and statically aligned to 1MB. + */ +#define NR_FIX_BTMAPS 32 +#define FIX_BTMAPS_SLOTS 7 +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) +#define FIX_BTMAP_BEGINFIX_KMAP_BEGIN +#define FIX_BTMAP_END (FIX_KMAP_END - 1) + +#define clear_fixmap(idx) \ + __set_fixmap(idx, 0, __pgprot(0)) + #define __fix_to_virt(x) (FIXADDR_START + ((x) PAGE_SHIFT)) #define __virt_to_fix(x) (((x) - FIXADDR_START) PAGE_SHIFT) extern void __this_fixmap_does_not_exist(void); -static inline unsigned long fix_to_virt(const unsigned int idx) +static __always_inline unsigned long fix_to_virt(const unsigned int idx) { + /* +* this branch gets completely eliminated after inlining, +* except when someone tries to use fixaddr indices in an +* illegal way. (such as mixing up address types or using +* out-of-range indices). +* +* If it doesn't get removed, the linker will complain +* loudly with a reasonably clear error message.. +*/ if (idx = FIX_KMAP_END) __this_fixmap_does_not_exist(); return __fix_to_virt(idx); diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index d070741..826cd88 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -26,6 +26,7 @@ #include linux/types.h #include asm/byteorder.h #include asm/memory.h +#include asm/pgtable.h #include asm-generic/pci_iomap.h /* @@ -397,5 +398,27 @@ extern int devmem_is_allowed(unsigned long pfn); extern void register_isa_ports(unsigned int mmio, unsigned int io, unsigned int io_shift); +/* + * early_ioremap(), early_memremap() and early_iounmap() are for + * temporary early boot-time mappings, before the real ioremap() + * is functional. + * A boot-time mapping is currently limited to at most 16 pages. + * + * This is all squashed by paging_init(). + */ +#ifdef CONFIG_EARLY_IOREMAP +extern void early_ioremap_init(void); +extern void early_ioremap_reset(void); +extern void __iomem *early_remap(resource_size_t phys_addr, +unsigned long size, u32 prot); +#define early_ioremap(x, y) early_remap(x, y, L_PTE_MT_DEV_NONSHARED) +#define early_memremap(x, y) early_remap(x, y, L_PTE_MT_WRITEALLOC) + +extern void early_iounmap(void __iomem *addr, unsigned long size); +#else +#define early_ioremap_init() +#define early_ioremap_reset() +#endif + #endif /* __KERNEL__ */ #endif /* __ASM_ARM_IO_H */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 0e1e2b3..b0b2360 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -36,6 +36,7 @@ #include asm/cpu.h #include asm/cputype.h
[PATCH v2 1/3] Documentation: arm: add UEFI support documentation
This patch provides documentation of the [U]EFI runtime services and configuration features. Cc: linux-...@vger.kernel.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Rob Landley r...@landley.net --- Documentation/arm/00-INDEX |3 +++ Documentation/arm/uefi.txt | 47 2 files changed, 50 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 4978456..87e01d1 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -36,3 +36,6 @@ nwfpe/ - NWFPE floating point emulator documentation swp_emulation - SWP/SWPB emulation handler/logging description + +uefi.txt + - [U]EFI configuration and runtime services documentation diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..e6e4d41 --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,47 @@ +UEFI, the Unified Extensible Firmware Interface is a speifcication +governing the behaviours of compatible firmware interfaces. It is +maintained by the UEFI Forum - http://www.uefi.org/. + +Since UEFI is an evolution of its predecessor 'EFI', the terms EFI and +UEFI are used somewhat interchangeably in this document and associated +source code. + +The implementation depends on receiving the UEFI runtime memory map and a +pointer to the System Table in a Flattened Device Tree - so is only available +with CONFIG_OF. + +It parses the FDT /chosen node for the following parameters: +- 'linux,efi-system-table': + Physical address of the system table. (required) + 64-bit value since an ARMv7 plattform may support LPAE, and to facilitate + code sharing with arm64. Top 32 bits will be ignored, since UEFI specification + mandates a 1:1 mapping of all RAM. +- 'linux,efi-mmap': + The EFI memory map as an embedded property. (required) + An array of type EFI_MEMORY_DESCRIPTOR as described by the UEFI + specification, current version described in Linux by efi_memory_desc_t. + The memory map is represented in little-endian, not DT, byte order. + This map needs to contain at least the regions to be preserved for runtime + services, but would normally just be the map retreieved by calling UEFI + GetMemoryMap() immediately before ExitBootServices(). +- 'linux,efi-mmap-desc-size': + Size of each descriptor in the memory map. (override default) +- 'linux,efi-mmap-desc-ver': + Memory descriptor format version. (override default) + +It also depends on early_memremap() to parse the UEFI configuration tables. + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +After the kernel has mapped the required regions into its address space, +a SetVirtualAddressMap() call is made into UEFI in order to update +relocations. This call must be performed with all the code in a 1:1 +mapping. This implementation achieves this by temporarily disabling the +MMU for the duration of this call. This can only be done safely: +- before secondary CPUs are brought online. +- after early_initcalls have completed, since it uses setup_mm_for_reboot(). + +For verbose debug messages, specify 'uefi_debug' on the kernel command +line. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/3] arm: Add [U]EFI runtime services support
This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It uses the generic configuration table scanning to populate ACPI and SMBIOS pointers. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig | 15 ++ arch/arm/include/asm/efi.h | 22 ++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 485 arch/arm/kernel/efi_phys.S | 59 ++ arch/arm/kernel/setup.c|6 + include/linux/efi.h|2 +- 7 files changed, 590 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5916a90..317c75d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1855,6 +1855,19 @@ config EARLY_IOREMAP It generates its map entries in kmap region (0xfff0) before kmap is initialized. +config EFI + bool UEFI runtime service support + depends on OF !CPU_BIG_ENDIAN + select UCS2_STRING + select EARLY_IOREMAP + ---help--- + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel will + continue to boot on non-UEFI platforms. + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode @@ -2267,6 +2280,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm/Kconfig.debug diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h new file mode 100644 index 000..aead94c --- /dev/null +++ b/arch/arm/include/asm/efi.h @@ -0,0 +1,22 @@ +#ifndef _ASM_ARM_EFI_H +#define _ASM_ARM_EFI_H + +#include asm/mach/map.h + +extern int efi_memblock_arm_reserve_range(void); + +typedef efi_status_t efi_phys_call_t(u32 memory_map_size, +u32 descriptor_size, +u32 descriptor_version, +efi_memory_desc_t *dsc, +efi_set_virtual_address_map_t *f); + +extern efi_status_t efi_phys_call(u32, u32, u32, efi_memory_desc_t *, + efi_set_virtual_address_map_t *); + +#define efi_remap(cookie, size) __arm_ioremap((cookie), (size), MT_MEMORY) +#define efi_ioremap(cookie, size) __arm_ioremap((cookie), (size), MT_DEVICE) +#define efi_unmap(cookie) __arm_iounmap((cookie)) +#define efi_iounmap(cookie) __arm_iounmap((cookie)) + +#endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 5140df5f..81b8865 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -96,4 +96,6 @@ obj-y += psci.o obj-$(CONFIG_SMP) += psci_smp.o endif +obj-$(CONFIG_EFI) += efi.o efi_phys.o + extra-y := $(head-y) vmlinux.lds diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c new file mode 100644 index 000..a7c2c8d --- /dev/null +++ b/arch/arm/kernel/efi.c @@ -0,0 +1,485 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.3.1 + * + * Copyright (C) 2013 Linaro Ltd. + * + */ + +#include linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h +#include asm/efi.h +#include asm/idmap.h +#include asm/tlbflush.h + +struct efi_memory_map memmap; + +static efi_runtime_services_t *runtime; + +static phys_addr_t efi_system_table; +static phys_addr_t efi_boot_mmap; +static u32 efi_boot_mmap_size; +static u32 efi_mmap_desc_size; +static u32 efi_mmap_desc_ver; + +static unsigned long arm_efi_facility; + +/* + * Default memory map descriptor information + */ +#define DESC_SIZE 48 +#define DESC_VER 1 + +/* + * If you're planning to wire up a debugger and debug the UEFI side ... + */ +#undef KEEP_ALL_REGIONS + +/* + * If you need to (temporarily) support buggy firmware. + */ +#define KEEP_BOOT_SERVICES_REGIONS + +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, arm_efi_facility) != 0; +} +EXPORT_SYMBOL(efi_enabled); + +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 fdt_find_efi_params(unsigned long node, const char *uname, + int depth, void *data) +{ + unsigned long len; + void *prop
[PATCH v2 3/3] init: efi: arm: enable (U)EFI runtime services on arm
Since the efi_set_virtual_address_map call has strict init ordering requirements, add an explicit hook in the required place. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- init/main.c |4 1 file changed, 4 insertions(+) diff --git a/init/main.c b/init/main.c index af310af..ec6d76e 100644 --- a/init/main.c +++ b/init/main.c @@ -875,6 +875,10 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + + if (IS_ENABLED(CONFIG_ARM) efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); + lockup_detector_init(); smp_init(); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 0/3] arm: [U]EFI runtime services support
In systems based on [U]EFI-conformant firmware, runtime services provide a standardised way for the kernel to update firmware environment variables. This is used for example by efibootmgr to update which image should be loaded on next boot. This patchset implements basic support for UEFI runtime services on ARM platforms, as well as the basic underlying EFI support. It also defines a mechanism by which the required information is passed from the bootloader to the kernel via FDT entries. This patchset depends on the previously submitted early_ioremap() and generic UEFI config table scanning patchsets. Changes from v1: - Updated FDT bindings, based on feedback. - Use common config table scanning and address lookup code. - Add dependency on !CPU_BIG_ENDIAN (for now). - Add proper efi_enabled() facility. - Documentation updates. Leif Lindholm (3): Documentation: arm: add UEFI support documentation arm: Add [U]EFI runtime services support init: efi: arm: enable (U)EFI runtime services on arm Documentation/arm/00-INDEX |3 + Documentation/arm/uefi.txt | 47 + arch/arm/Kconfig | 15 ++ arch/arm/include/asm/efi.h | 22 ++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 485 arch/arm/kernel/efi_phys.S | 59 ++ arch/arm/kernel/setup.c|6 + include/linux/efi.h|2 +- init/main.c|4 + 10 files changed, 644 insertions(+), 1 deletion(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/3] Documentation: arm: add UEFI support documentation
On Thu, Oct 03, 2013 at 11:11:18AM -0500, Rob Herring wrote: Adding devicetree list since you are defining bindings... +with CONFIG_OF. + +It parses the FDT /chosen node for the following parameters: DT bindings should be documented in Documentation/devicetree/bindings. I also wonder if this would be more appropriately placed in a /firmware node. This is information passed to the kernel by the bootloader - not system descriptiont - so I don't quite see why it needs different treatment from initrd and bootargs. Feedback on v1 was: https://lkml.org/lkml/2013/6/26/378 and https://lkml.org/lkml/2013/6/27/420 I don't really mind either way, but the current layout is now used across 3 sets of kernel patches, so we need to reach some sort of consensus. Interested parties so far: me, you, Grant, Arnd, Mark. +- 'linux,efi-mmap': + The EFI memory map as an embedded property. (required) + An array of type EFI_MEMORY_DESCRIPTOR as described by the UEFI + specification, current version described in Linux by efi_memory_desc_t. Is that too complex to describe here? No, just felt a bit redundant, and also not architecture-specific. + The memory map is represented in little-endian, not DT, byte order. + This map needs to contain at least the regions to be preserved for runtime + services, but would normally just be the map retreieved by calling UEFI + GetMemoryMap() immediately before ExitBootServices(). +- 'linux,efi-mmap-desc-size': + Size of each descriptor in the memory map. (override default) 32-bit value? Value as returned by the above mentioned GetMemoryMap(). Defined in UEFI specification (and linux/efi.h) as 32-bit (native int). But yes, I can be explicit. +- 'linux,efi-mmap-desc-ver': + Memory descriptor format version. (override default) String? Number? Value as returned by the above mentioned GetMemoryMap(). Defined in the UEFI specification as 32-bit (uint32), not architecture specific. And I can add that too. Are these all generated by UEFI at runtime or could they be statically set in a platform's DTB? Generated at runtime. This is not the platform memory map, this is the UEFI memory map, which tells us which regions we need to preserve for runtime services, ACPI and such. How would other OS's get this information? Is this really linux specific? The way it is passed through DT is. Other operating systems might keep boot services running for longer, and make calls into UEFI later, so not needing to cache the data. Since boot services means the timer interrupt is active, the ARM Linux boot protocol effectively prohibits this. Many of these questions are about generic UEFI mechanisms. If they need to be documented outside the UEFI specification, Documentation/arm is not the right place for it. If you want, I could give a basic Documentation/uefi.txt a shot. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 1/3] Documentation: arm: add UEFI support documentation
On Thu, Oct 03, 2013 at 06:10:54PM +0100, Mark Rutland wrote: +The implementation depends on receiving the UEFI runtime memory map and a +pointer to the System Table in a Flattened Device Tree - so is only available +with CONFIG_OF. + +It parses the FDT /chosen node for the following parameters: +- 'linux,efi-system-table': + Physical address of the system table. (required) + 64-bit value since an ARMv7 plattform may support LPAE, and to facilitate s/plattform/platform/ Indeed, thanks. + code sharing with arm64. Top 32 bits will be ignored, since UEFI specification + mandates a 1:1 mapping of all RAM. You could use something like #size-cells to describe how big this is going to be. Is this Linux-specific -- it looks like something provided by EFI rather than the kernel itself. Provided by the bootloader, which may be the kernel's UEFI stub, or something else (like GRUB). Extracted from UEFI by stub (or other loader) which executes as a UEFI application. +- 'linux,efi-mmap': + The EFI memory map as an embedded property. (required) + An array of type EFI_MEMORY_DESCRIPTOR as described by the UEFI + specification, current version described in Linux by efi_memory_desc_t. + The memory map is represented in little-endian, not DT, byte order. + This map needs to contain at least the regions to be preserved for runtime + services, but would normally just be the map retreieved by calling UEFI + GetMemoryMap() immediately before ExitBootServices(). This is a little scary. If the format is so complicated, should it really be embedded? How big is this likely to be? With current format, and it has yet to be extended beyond v1, it is 40 bytes per entry. Number of entries will vary depending on how many regions are allocated in UEFI (1 entry per region). I have heard of some x86 systems with 128 or more regions, but my devboards have more like 16, and my desktop ~60. Having it embedded in the DT means the data passed by the bootloader to the kernel is automatically kept together (for kexec or such). Not vital, but nice. Given that this is in a format defined externally, this isn't really Linux-specific. Maybe we need an efi pseudo-vendor prefix. A discussion for the other thread. +- 'linux,efi-mmap-desc-size': + Size of each descriptor in the memory map. (override default) What units is this in? How many u32 cells does this take up (one presumably)? Value as returned by UEFI GetMemoryMap() boot service call. Yes, one for ARM. +- 'linux,efi-mmap-desc-ver': + Memory descriptor format version. (override default) Type, format, valid values and their meaning? Meaning defined by UEFI specification, currently providing the only valid value as 1. 32-bit uint. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 2/3] arm: Add [U]EFI runtime services support
On Thu, Oct 17, 2013 at 03:07:39PM +0100, Matt Fleming wrote: +/* + * If you need to (temporarily) support buggy firmware. + */ +#define KEEP_BOOT_SERVICES_REGIONS Have you seen firmware that requires this? I'm just curious more than anything else. Not really. I _think_ I saw it on a debug build of a development platform once. That coincided with me seeing a post on linux-efi about some laptop that broke unless boot services regions were preserved, so I decided to put it in there for any future debugging. +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, arm_efi_facility) != 0; +} +EXPORT_SYMBOL(efi_enabled); This should move to drivers/firmware/efi/efi.c. Let me write a patch that moves the x86 stuff out of arch/x86 and means you can get rid of this hunk. Excellent, thanks! +/* + * Called explicitly from init/mm.c + */ That's init/main.c. *cough*, right. +void __init efi_enter_virtual_mode(void) +{ + efi_status_t status; + + if (!efi_enabled(EFI_BOOT)) { + pr_info(EFI services will not be available.\n); + return; This is dead code as PATCH 3 does, diff --git a/init/main.c b/init/main.c index af310af..ec6d76e 100644 --- a/init/main.c +++ b/init/main.c @@ -875,6 +875,10 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + + if (IS_ENABLED(CONFIG_ARM) efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); + True. However, this call site is likely to change in the future (preferably to an early_initcall), if we redesign the memory mapping to be reusable after kexec(). At which point the test in efi_enter_virtual_mode() will make sense again. Could I change the test in init/main.c to do if (IS_ENABLED(CONFIG_ARM) IS_ENABLED(CONFIG_EFI)) instead? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 0/3] (U)EFI runtime services for arm
In systems based on [U]EFI-conformant firmware, runtime services provide a standardised way for the kernel to update firmware environment variables. This is used for example by efibootmgr to update which image should be loaded on next boot. This patchset implements basic support for UEFI runtime services on ARM platforms, as well as the basic underlying EFI support. It also defines a mechanism by which the required information is passed from the bootloader (the EFI stub submitted separately) to the kernel via FDT entries. This patchset depends on the presence of early_ioremap(). It has been validated against Mark Salter's generic implementation. Changes from v2: - Updated FDT bindings. - The EFI stub is now the only loader that will support the kernel enabling runtime services. - Documentation updates. Changes from v1: - Updated FDT bindings, based on feedback. - Use common config table scanning and address lookup code. - Add dependency on !CPU_BIG_ENDIAN (for now). - Add proper efi_enabled() facility. - Documentation updates. Leif Lindholm (3): Documentation: arm: add UEFI support documentation arm: Add [U]EFI runtime services support init: efi: arm: enable (U)EFI runtime services on arm Documentation/arm/00-INDEX |3 + Documentation/arm/uefi.txt | 61 ++ arch/arm/Kconfig| 15 ++ arch/arm/include/asm/uefi.h | 22 ++ arch/arm/kernel/Makefile|2 + arch/arm/kernel/setup.c |6 + arch/arm/kernel/uefi.c | 469 +++ arch/arm/kernel/uefi_phys.S | 59 ++ include/linux/efi.h |2 +- init/main.c |4 + 10 files changed, 642 insertions(+), 1 deletion(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm/include/asm/uefi.h create mode 100644 arch/arm/kernel/uefi.c create mode 100644 arch/arm/kernel/uefi_phys.S -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 1/3] Documentation: arm: add UEFI support documentation
This patch provides documentation of the [U]EFI runtime service and configuration features for the arm architecture. Changes since v1/v2: - Complete rewrite. - New FDT bindings. Cc: Rob Landley r...@landley.net Cc: linux-...@vger.kernel.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- Documentation/arm/00-INDEX |3 +++ Documentation/arm/uefi.txt | 61 2 files changed, 64 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 36420e1..b3af704 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -34,3 +34,6 @@ nwfpe/ - NWFPE floating point emulator documentation swp_emulation - SWP/SWPB emulation handler/logging description + +uefi.txt + - [U]EFI configuration and runtime services documentation diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..9ba59509 --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,61 @@ +UEFI, the Unified Extensible Firmware Interface is, a specification +governing the behaviours of compatible firmware interfaces. It is +maintained by the UEFI Forum - http://www.uefi.org/. + +UEFI is an evolution of its predecessor 'EFI', so the terms EFI and +UEFI are used somewhat interchangeably in this document and associated +source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers +to legacy code or specifications. + +UEFI support in Linux += +Booting on a platform with firmware compliant with the UEFI specification +makes it possible for the kernel to support additional features: +- UEFI Runtime Services +- Retrieving various configuration information through the standardised + interface of UEFI configuration tables. (ACPI, SMBIOS, ...) + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +The implementation depends on receiving information about the UEFI environment +in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF. + +UEFI stub += +The stub is a feature that turns the Image/zImage into a valid UEFI PE/COFF +executable, including a loader application that makes it possible to load the +kernel directly from the UEFI shell, boot menu, or one of the lightweight +bootloaders like Gummiboot or rEFInd. + +The kernel image built with stub support remains a valid kernel image for +booting in non-UEFI environments. + +UEFI kernel support on ARM +== +UEFI kernel support on the ARM architectures (arm and arm64) is only available +when boot is performed through the stub. + +The stub populates the FDT /chosen node with (and the kernel scans for) the +following parameters: + +Name | Size | Description + +linux,uefi-system-table | 64-bit | Physical address of the UEFI System Table. + +linux,uefi-mmap-start | 64-bit | Physical address of the UEFI memory map, + || populated by the UEFI GetMemoryMap() call. + +linux,uefi-mmap-size | 32-bit | Size in bytes of the UEFI memory map + || pointed to in previous entry. + +linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI + || memory map. + +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. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3 2/3] arm: Add [U]EFI runtime services support
This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It uses the generic configuration table scanning to populate ACPI and SMBIOS pointers. Changes since v2: - Updated FDT bindings. - Preserve regions marked RESERVED (but don't map them). - Rename 'efi' - 'uefi' within this new port (leaving core code as is). Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig| 15 ++ arch/arm/include/asm/uefi.h | 22 ++ arch/arm/kernel/Makefile|2 + arch/arm/kernel/setup.c |6 + arch/arm/kernel/uefi.c | 469 +++ arch/arm/kernel/uefi_phys.S | 59 ++ include/linux/efi.h |2 +- 7 files changed, 574 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/uefi.h create mode 100644 arch/arm/kernel/uefi.c create mode 100644 arch/arm/kernel/uefi_phys.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 78a79a6a..db8d212 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1853,6 +1853,19 @@ config EARLY_IOREMAP the same virtual memory range as kmap so all early mappings must be unapped before paging_init() is called. +config EFI + bool UEFI runtime service support + depends on OF !CPU_BIG_ENDIAN + select UCS2_STRING + select EARLY_IOREMAP + ---help--- + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel will + continue to boot on non-UEFI platforms. + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode @@ -2272,6 +2285,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm/Kconfig.debug diff --git a/arch/arm/include/asm/uefi.h b/arch/arm/include/asm/uefi.h new file mode 100644 index 000..519ca18 --- /dev/null +++ b/arch/arm/include/asm/uefi.h @@ -0,0 +1,22 @@ +#ifndef _ASM_ARM_EFI_H +#define _ASM_ARM_EFI_H + +#include asm/mach/map.h + +extern int uefi_memblock_arm_reserve_range(void); + +typedef efi_status_t uefi_phys_call_t(u32 memory_map_size, + u32 descriptor_size, + u32 descriptor_version, + efi_memory_desc_t *dsc, + efi_set_virtual_address_map_t *f); + +extern efi_status_t uefi_phys_call(u32, u32, u32, efi_memory_desc_t *, + efi_set_virtual_address_map_t *); + +#define uefi_remap(cookie, size) __arm_ioremap((cookie), (size), MT_MEMORY) +#define uefi_ioremap(cookie, size) __arm_ioremap((cookie), (size), MT_DEVICE) +#define uefi_unmap(cookie) __arm_iounmap((cookie)) +#define uefi_iounmap(cookie) __arm_iounmap((cookie)) + +#endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index a30fc9b..736cce4 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -98,4 +98,6 @@ obj-y += psci.o obj-$(CONFIG_SMP) += psci_smp.o endif +obj-$(CONFIG_EFI) += uefi.o uefi_phys.o + extra-y := $(head-y) vmlinux.lds diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 04c1757..9d44edd 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -30,6 +30,7 @@ #include linux/bug.h #include linux/compiler.h #include linux/sort.h +#include linux/efi.h #include asm/unified.h #include asm/cp15.h @@ -57,6 +58,7 @@ #include asm/unwind.h #include asm/memblock.h #include asm/virt.h +#include asm/uefi.h #include atags.h @@ -898,6 +900,10 @@ void __init setup_arch(char **cmdline_p) sanity_check_meminfo(); arm_memblock_init(meminfo, mdesc); +#ifdef CONFIG_EFI + uefi_memblock_arm_reserve_range(); +#endif + paging_init(mdesc); request_standard_resources(mdesc); diff --git a/arch/arm/kernel/uefi.c b/arch/arm/kernel/uefi.c new file mode 100644 index 000..f771026 --- /dev/null +++ b/arch/arm/kernel/uefi.c @@ -0,0 +1,469 @@ +/* + * Based on Unified Extensible Firmware Interface Specification version 2.3.1 + * + * Copyright (C) 2013 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h +#include asm/idmap.h +#include asm/tlbflush.h +#include asm/uefi.h + +struct efi_memory_map memmap; + +static
[PATCH v3 3/3] init: efi: arm: enable (U)EFI runtime services on arm
Since the efi_set_virtual_address_map call has strict init ordering requirements, add an explicit hook in the required place. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- init/main.c |4 1 file changed, 4 insertions(+) diff --git a/init/main.c b/init/main.c index febc511..1331829 100644 --- a/init/main.c +++ b/init/main.c @@ -905,6 +905,10 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + + if (IS_ENABLED(CONFIG_ARM) efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); + lockup_detector_init(); smp_init(); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 2/3] arm: Add [U]EFI runtime services support
Hi Will, Thanks for having a look. On Fri, Nov 29, 2013 at 04:10:16PM +, Will Deacon wrote: This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It uses the generic configuration table scanning to populate ACPI and SMBIOS pointers. I've got a bunch of implementation questions, so hopefully you can help me to understand what this is doing! I can try :) diff --git a/arch/arm/kernel/uefi.c b/arch/arm/kernel/uefi.c new file mode 100644 index 000..f771026 --- /dev/null +++ b/arch/arm/kernel/uefi.c +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, arm_uefi_facility) != 0; !test_bit(...) ? Could do. Cloned from the x86 implementation. Matt Fleming has indicated some rework coming in this area. +static int __init uefi_init(void) +{ + efi_char16_t *c16; + char vendor[100] = unknown; + int i, retval; + + efi.systab = early_memremap(uefi_system_table, + sizeof(efi_system_table_t)); + + /* +* Verify the UEFI System Table +*/ + if (efi.systab == NULL) + panic(Whoa! Can't find UEFI system table.\n); + if (efi.systab-hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) + panic(Whoa! UEFI system table signature incorrect\n); + if ((efi.systab-hdr.revision 16) == 0) + pr_warn(Warning: UEFI system table version %d.%02d, expected 1.00 or greater\n, + efi.systab-hdr.revision 16, + efi.systab-hdr.revision 0x); + + /* Show what we know for posterity */ + c16 = (efi_char16_t *)early_memremap(efi.systab-fw_vendor, + sizeof(vendor)); + if (c16) { + for (i = 0; i (int) sizeof(vendor) - 1 *c16; ++i) + vendor[i] = c16[i]; + vendor[i] = '\0'; + } + + pr_info(UEFI v%u.%.02u by %s\n, + efi.systab-hdr.revision 16, + efi.systab-hdr.revision 0x, vendor); + + retval = efi_config_init(NULL); + if (retval == 0) + set_bit(EFI_CONFIG_TABLES, arm_uefi_facility); Does this actually need to be atomic? Not necessarily, but it's neater than masking, and only called once. + + early_iounmap(c16, sizeof(vendor)); + early_iounmap(efi.systab, sizeof(efi_system_table_t)); + + return retval; +} + +static __init int is_discardable_region(efi_memory_desc_t *md) +{ +#ifdef KEEP_ALL_REGIONS + return 0; +#endif Maybe just have a dummy is_discardable_region in this case, like we usually do instead of inlining the #ifdef? OK. + if (md-attribute EFI_MEMORY_RUNTIME) + return 0; + + switch (md-type) { +#ifdef KEEP_BOOT_SERVICES_REGIONS + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: +#endif + /* Keep tables around for any future kexec operations */ + case EFI_ACPI_RECLAIM_MEMORY: + return 0; + /* Preserve */ + case EFI_RESERVED_TYPE: + return 0; + } + + return 1; +} [...] +int __init uefi_memblock_arm_reserve_range(void) +{ + if (!of_scan_flat_dt(fdt_find_uefi_params, NULL)) + return 0; + + set_bit(EFI_BOOT, arm_uefi_facility); Similar comment wrt atomicity here (and in the rest of this patch). Similar response. + uefi_init(); + + remove_regions(); + + return 0; +} + +/* + * Disable instrrupts, enable idmap and disable caches. interrupts Yeah. + */ +static void __init phys_call_prologue(void) +{ + local_irq_disable(); + + /* Take out a flat memory mapping. */ + setup_mm_for_reboot(); + + /* Clean and invalidate caches */ + flush_cache_all(); + + /* Turn off caching */ + cpu_proc_fin(); + + /* Push out any further dirty data, and ensure cache is empty */ + flush_cache_all(); Do we care about outer caches here? I think we do. We jump into UEFI and make it relocate itself to the new virtual addresses, with MMU disabled (so all accesses NC). This all looks suspiciously like copy-paste from __soft_restart; Yeah, 'cause you told me to :) perhaps some refactoring/reuse is in order? Could do. Turn this into a process.c:idcall_prepare(), or something less daftly named? +} + +/* + * Restore original memory map and re-enable interrupts. + */ +static void __init phys_call_epilogue(void) +{ + static struct mm_struct *mm = init_mm; + + /* Restore original memory
Re: [PATCH v3 0/3] (U)EFI runtime services for arm
On Fri, Nov 29, 2013 at 11:53:19AM +, Matt Fleming wrote: On Thu, 28 Nov, at 04:41:20PM, Leif Lindholm wrote: In systems based on [U]EFI-conformant firmware, runtime services provide a standardised way for the kernel to update firmware environment variables. This is used for example by efibootmgr to update which image should be loaded on next boot. This patchset implements basic support for UEFI runtime services on ARM platforms, as well as the basic underlying EFI support. It also defines a mechanism by which the required information is passed from the bootloader (the EFI stub submitted separately) to the kernel via FDT entries. This all looks pretty good to me. Is this series going through the ARM trees? Thanks. That's the plan. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 1/3] Documentation: arm: add UEFI support documentation
On Mon, Dec 02, 2013 at 01:51:22PM -0600, Matt Sealey wrote: Here's where I think this whole thing falls down as being the weirdest possible implementation of this. It defies logic to put this information in the device tree /chosen node while also attempting to boot the kernel using an EFI stub; the stub is going to have this information because it is going to have the pointer to the system System Table (since it was called by StartImage()). Why not stash the System Table pointer somewhere safe in the stub? We do. In the DT. The information in the device tree is all accessible from Boot Services and as long as the System Table isn't being thrown away (my suggestion would be.. stuff it in r2, and set r1 = EFI\0 then work with arch/arm/kernel/head{-common,}.S code to do the right thing) You left out the bit of redefining the kernel boot protocol to permit calling it with caches, MMU and interrupts enabled - also known as before ExitBootServices(). It seems like the advantages of booting from UEFI and having all this information and API around are being thrown away very early, and picked up when it's no longer relevant to gain access to the very minimal runtime services. What's missing is a UUID for a Device Tree Blob in the Configuration Table, so you can very easily go grab that information from the firmware. Which is what we are going to implement anyway in order to permit firmware to supply DT hardware description in the same way as with ACPI. Yes, we could pass the system table pointer directly - but that doesn't get us the memory map. As implemented, these patches employ a very long-winded and complex method of recovering UEFI after throwing the system table pointer away early in boot, and then implements an EFI calling convention which isn't strictly necessary according to the UEFI spec - the question is, is this a workaround for SetVirtualAddressMap() not actually doing the right thing on ARM UEFI implementations? If you can't guarantee that most of the calls from Boot Services or Runtime Services are going to allow this, then having any UEFI support in the kernel at all seems rather weird. No, it is a workaround for it being explicitly against the kernel boot protocol (not to mention slightly hairy) to enter head.S with MMU and caches enabled and interrupts firing. The EFI calling convention (as pointed out in the patch itself) is there in order to not have to duplicate code already there for x86. What I'm worried about is that this is basically a hack to try and shoehorn an existing UEFI implementation to an existing Linux boot method - and implements it in a way nobody is ever going to be able to justify improving. Part of the reason the OpenFirmware CIF got thrown away early in SPARC/PowerPC boot (after flattening the device tree using the CIF calls to parse it out) was because you had to disable the MMU, caches, interrupts etc. which caused all kinds of slow firmware code to be all kinds of extra-slow. I prefer to see it as a way to not reinvent things that do not need reinventing, while not adding more special-case code to the kernel. What that meant is nobody bothered to implement working, re-entrant, re-locatable firmware to a great degree. This ended up being a self-fulfilling prophecy of don't trust the bootloader and get rid of it as soon as we can, which essentially meant Linux never took advantage of the resources available. In OF's case, the CIF sucked by specification. In UEFI's case here, it's been implemented in Linux in such a way that guarantees poor-performing firmware code with huge penalties to call them, which isn't even required by UEFI if the earlier boot code did the right things in the first place. I don't follow. In which way does this implementation result in poor performance or reduced functionality? We deal with a highly quirky set of requirements for calling SetVirtualAddressMap() in a clunky way - after which calls into UEFI are direct and cachable. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 0/3] arm: [U]EFI runtime services support
Hi Olof, Many thanks for having a look. On Fri, Nov 15, 2013 at 10:04:22AM -0800, Olof Johansson wrote: This series is generally looking sane to me without looking at the code in very close detail. In the interest of full disclosure, I would like to point out that I will be posting another version next week, based on the output of the discussions around the DT bindings and documentation. This set needs to be tested in combination with Roy's UEFI stub patches is recommended, as this is the intended boot mechanism on UEFI platforms. https://wiki.linaro.org/LEG/Engineering/Kernel/UEFI/EFIstub Do you have a test setup that you've been using for this that you could give a pointer to? Well, I have been using vexpress ca9 and ca15_a7 (TC2), or the ARM commercial software models (RTSM) of the same. I have also tested on Arndale, but I don't know if that is fully supported by mainline yet. Prebuilt UEFI images are available from http://releases.linaro.org/13.09/components/kernel/uefi-linaro efibootmgr is probably the best utility to test the runtime services, if scanning the /sys entries are not sufficient. It builds for armhf without modification. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 1/3] Documentation: arm: add UEFI support documentation
On Wed, Dec 04, 2013 at 03:06:47PM -0600, Matt Sealey wrote: By the time we get half-way through arm/kernel/head.S the cache and MMU has been turned off and on and off again by the decompressor, and after a large amount of guesswork and arbitrary restriction-based implementation, there's no guarantee that the kernel hasn't been decompressed over some important UEFI feature or some memory hasn't been trashed. You can't make that guarantee because by entering the plain zImage, you forfeited that information. This is at worst case going to be lots of blank screens and blinking serial console prompts and little more than frustration.. So, Grant covered the reason _why_ we coexist with zImage, so I won't go into that. I will however point out that we are explicitly using the UEFI interfaces to allocate the regions the zImage will decompress into. This isn't guesswork, and has in fact already turned up issues with a couple of UEFI board ports that reserved memory near 0 (which were indeed previously being silently overwritten by the kernel decompression). We _are_ planning to do more development for subsequent patches, making more use of the UEFI memory map. And by subsequent, I mean hopefully in time for 3.14. I sneekily included this in the version of uefi.txt sent out for separate review early November: http://permalink.gmane.org/gmane.linux.kernel.efi/2657, but not in the one included with this patch set (since the code isn't there yet). But we considered it more important to get the basic support ready first. At that point, you will see the stub reading the dram_base from the UEFI memory map rather than DT, and memblock_init getting its input from there too. Regards, Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 03/15] efi: create memory map iteration helper
From: Mark Salter msal...@redhat.com There are a lot of places in the kernel which iterate through an EFI memory map. Most of these places use essentially the same for-loop code. This patch adds a for_each_efi_memory_desc() helper to clean up all of the existing duplicate code and avoid more in the future. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- include/linux/efi.h |6 ++ 1 file changed, 6 insertions(+) diff --git a/include/linux/efi.h b/include/linux/efi.h index 64d532c..a3276da 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -622,6 +622,12 @@ extern int efi_set_rtc_mmss(const struct timespec *now); extern void efi_reserve_boot_services(void); extern struct efi_memory_map memmap; +/* Iterate through an efi_memory_map */ +#define for_each_efi_memory_desc(m, md) \ + for ((md) = (m)-map; \ +(md) = (efi_memory_desc_t *)((m)-map_end - (m)-desc_size); \ +(md) = (void *)(md) + (m)-desc_size) + /** * efi_range_is_wc - check the WC bit on an address range * @start: starting kvirt address -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 15/15] efi/arm64: ignore dtb= when UEFI SecureBoot is enabled
From: Ard Biesheuvel ard.biesheu...@linaro.org Loading unauthenticated FDT blobs directly from storage is a security hazard, so this should only be allowed when running with UEFI Secure Boot disabled. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/arm-stub.c| 23 ++- drivers/firmware/efi/efi-stub-helper.c | 24 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/arm-stub.c index b505fde..733723c 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/arm-stub.c @@ -41,7 +41,7 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, /* addr/point and size pairs for memory management*/ unsigned long initrd_addr; u64 initrd_size = 0; - unsigned long fdt_addr; /* Original DTB */ + unsigned long fdt_addr = 0; /* Original DTB */ u64 fdt_size = 0; /* We don't get size from configuration table */ char *cmdline_ptr = NULL; int cmdline_size = 0; @@ -93,15 +93,20 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, goto fail_free_image; } - /* Load a device tree from the configuration table, if present. */ - fdt_addr = (uintptr_t)get_fdt(sys_table); + /* +* Unauthenticated device tree data is a security hazard, so +* ignore 'dtb=' unless UEFI Secure Boot is disabled. +*/ + if (efi_secureboot_enabled(sys_table)) + pr_efi(sys_table, UEFI Secure Boot is enabled.\n); + else + handle_cmdline_files(sys_table, image, cmdline_ptr, dtb=, +~0UL, (unsigned long *)fdt_addr, +(unsigned long *)fdt_size); if (!fdt_addr) { - status = handle_cmdline_files(sys_table, image, cmdline_ptr, - dtb=, - ~0UL, (unsigned long *)fdt_addr, - (unsigned long *)fdt_size); - - if (status != EFI_SUCCESS) { + /* Look for a device tree configuration table entry. */ + fdt_addr = (uintptr_t)get_fdt(sys_table); + if (!fdt_addr) { pr_efi_err(sys_table, Failed to load device tree!\n); goto fail_free_cmdline; } diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 4a9986b..f2014f2 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -704,3 +704,27 @@ static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, *cmd_line_len = options_bytes; return (char *)cmdline_addr; } + +static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) +{ + static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; + static efi_char16_t const var_name[] __initconst = { + 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', 0 }; + + efi_get_variable_t *f_getvar = sys_table_arg-runtime-get_variable; + unsigned long size = sizeof(u8); + efi_status_t status; + u8 val; + + status = efi_call_phys5(f_getvar, (efi_char16_t *)var_name, + (efi_guid_t *)var_guid, NULL, size, val); + + switch (status) { + case EFI_SUCCESS: + return val; + case EFI_NOT_FOUND: + return 0; + default: + return 1; + } +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 12/15] doc: arm64: add description of EFI stub support
From: Mark Salter msal...@redhat.com Add explanation of arm64 EFI stub and kernel image header changes needed to masquerade as a PE/COFF application. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org CC: linux-...@vger.kernel.org CC: Rob Landley r...@landley.net --- Documentation/arm64/booting.txt |4 Documentation/efi-stub.txt | 12 +--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index a9691cc..aa95d38c 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt @@ -85,6 +85,10 @@ The decompressed kernel image contains a 64-byte header as follows: Header notes: - code0/code1 are responsible for branching to stext. +- when booting through EFI, code0/code1 are initially skipped. + res5 is an offset to the PE header and the PE header has the EFI + entry point (efi_stub_entry). When the stub has done its work, it + jumps to code0 to resume the normal boot process. The image must be placed at the specified offset (currently 0x8) from the start of the system RAM and called there. The start of the diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt index 26be7b0..7747024 100644 --- a/Documentation/efi-stub.txt +++ b/Documentation/efi-stub.txt @@ -12,6 +12,11 @@ arch/arm/boot/compressed/efi-header.S and arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared between architectures is in drivers/firmware/efi/efi-stub-helper.c. +For arm64, there is no compressed kernel support, so the Image itself +masquerades as a PE/COFF image and the EFI stub is linked into the +kernel. The arm64 EFI stub lives in arch/arm64/kernel/efi-entry.S +and arch/arm64/kernel/efi-stub.c. + By using the EFI boot stub it's possible to boot a Linux kernel without the use of a conventional EFI boot loader, such as grub or elilo. Since the EFI boot stub performs the jobs of a boot loader, in @@ -28,7 +33,8 @@ the extension the EFI firmware loader will refuse to execute it. It's not possible to execute bzImage.efi from the usual Linux file systems because EFI firmware doesn't have support for them. For ARM the arch/arm/boot/zImage should be copied to the system partition, and it -may not need to be renamed. +may not need to be renamed. Similarly for arm64, arch/arm64/boot/Image +should be copied but not necessarily renamed. Passing kernel parameters from the EFI shell @@ -72,7 +78,7 @@ is passed to bzImage.efi. The dtb= option -For the ARM architecture, we also need to be able to provide a device -tree to the kernel. This is done with the dtb= command line option, +For the ARM and arm64 architectures, we also need to be able to provide a +device tree to the kernel. This is done with the dtb= command line option, and is processed in the same manner as the initrd= option that is described above. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 14/15] doc: arm: add UEFI support documentation
This patch provides documentation of the [U]EFI runtime service and configuration features for the arm architecture. Cc: Rob Landley r...@landley.net Cc: linux-...@vger.kernel.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- Documentation/arm/00-INDEX |2 ++ Documentation/arm/uefi.txt | 64 2 files changed, 66 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index a94090c..3b08bc2 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -46,5 +46,7 @@ swp_emulation - SWP/SWPB emulation handler/logging description tcm.txt - ARM Tightly Coupled Memory +uefi.txt + - [U]EFI configuration and runtime services documentation vlocks.txt - Voting locks, low-level mechanism relying on memory system atomic writes. diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..d60030a --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,64 @@ +UEFI, the Unified Extensible Firmware Interface, is a specification +governing the behaviours of compatible firmware interfaces. It is +maintained by the UEFI Forum - http://www.uefi.org/. + +UEFI is an evolution of its predecessor 'EFI', so the terms EFI and +UEFI are used somewhat interchangeably in this document and associated +source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers +to legacy code or specifications. + +UEFI support in Linux += +Booting on a platform with firmware compliant with the UEFI specification +makes it possible for the kernel to support additional features: +- UEFI Runtime Services +- Retrieving various configuration information through the standardised + interface of UEFI configuration tables. (ACPI, SMBIOS, ...) + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +The implementation depends on receiving information about the UEFI environment +in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF. + +UEFI stub += +The stub is a feature that extends the Image/zImage into a valid UEFI +PE/COFF executable, including a loader application that makes it possible to +load the kernel directly from the UEFI shell, boot menu, or one of the +lightweight bootloaders like Gummiboot or rEFInd. + +The kernel image built with stub support remains a valid kernel image for +booting in non-UEFI environments. + +UEFI kernel support on ARM +== +UEFI kernel support on the ARM architectures (arm and arm64) is only available +when boot is performed through the stub. + +When booting in UEFI mode, the stub deletes any memory nodes from a provided DT. +Instead, the kernel reads the UEFI memory map. + +The stub populates the FDT /chosen node with (and the kernel scans for) the +following parameters: + +Name | Size | Description + +linux,uefi-system-table | 64-bit | Physical address of the UEFI System Table. + +linux,uefi-mmap-start | 64-bit | Physical address of the UEFI memory map, + || populated by the UEFI GetMemoryMap() call. + +linux,uefi-mmap-size | 32-bit | Size in bytes of the UEFI memory map + || pointed to in previous entry. + +linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI + || memory map. + +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. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 11/15] arm64: add EFI stub
From: Mark Salter msal...@redhat.com This patch adds PE/COFF header fields to the start of the Image so that it appears as an EFI application to EFI firmware. An EFI stub is included to allow direct booting of the kernel Image. Support in the COFF header for signed images was provided by Ard Biesheuvel. Signed-off-by: Ard Biesheuvel ard.biesheu...@linaro.org Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/Kconfig | 10 +++ arch/arm64/kernel/Makefile |3 + arch/arm64/kernel/efi-entry.S | 93 + arch/arm64/kernel/efi-stub.c| 83 ++ arch/arm64/kernel/head.S| 112 ++ drivers/firmware/efi/arm-stub.c | 144 +++ 6 files changed, 445 insertions(+) create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 drivers/firmware/efi/arm-stub.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index da4304a..6333d49 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -259,6 +259,16 @@ config CMDLINE_FORCE This is useful if you cannot or don't want to change the command-line options your boot loader passes to the kernel. +config EFI_STUB + bool EFI stub support + depends on OF + select LIBFDT + default y + help + This kernel feature allows an Image to be loaded directly + by EFI firmware without the use of a bootloader. + See Documentation/efi-stub.txt for more information. + endmenu menu Userspace binary formats diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 2d4554b..0f60b45 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -4,6 +4,8 @@ CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) +CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \ + -I$(src)/../../../scripts/dtc/libfdt # Object file lists. arm64-obj-y:= cputable.o debug-monitors.o entry.o irq.o fpsimd.o \ @@ -20,6 +22,7 @@ arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o +arm64-obj-$(CONFIG_EFI_STUB) += efi-stub.o efi-entry.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S new file mode 100644 index 000..bfe8c9b --- /dev/null +++ b/arch/arm64/kernel/efi-entry.S @@ -0,0 +1,93 @@ +/* + * EFI entry point. + * + * Copyright (C) 2013 Red Hat, Inc. + * Author: Mark Salter msal...@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include linux/linkage.h +#include linux/init.h + +#include asm/assembler.h + +#define EFI_LOAD_ERROR 0x8001 + + __INIT + + /* +* We arrive here from the EFI boot manager with: +* +** MMU on with identity-mapped RAM. +** Icache and Dcache on +* +* We will most likely be running from some place other than where +* we want to be. The kernel image wants to be placed at TEXT_OFFSET +* from start of RAM. +*/ +ENTRY(efi_stub_entry) + stp x29, x30, [sp, #-32]! + + /* +* Call efi_entry to do the real work. +* x0 and x1 are already set up by firmware. Current runtime +* address of image is calculated and passed via *image_addr. +* +* unsigned long efi_entry(void *handle, +* efi_system_table_t *sys_table, +* unsigned long *image_addr) ; +*/ + adrpx8, _text + add x8, x8, #:lo12:_text + add x2, sp, 16 + str x8, [x2] + bl efi_entry + cmn x0, #1 + b.eqefi_load_fail + + /* +* efi_entry() will have relocated the kernel image if necessary +* and we return here with device tree address in x0 and the kernel +* entry point stored at *image_addr. Save those values in registers +* which are preserved by __flush_dcache_all. +*/ + ldr x1, [sp, #16] + mov x20, x0 + mov x21, x1 + + /* Turn off Dcache and MMU */ + mrs x0, CurrentEL + cmp x0, #PSR_MODE_EL2t + ccmpx0, #PSR_MODE_EL2h, #0x4, ne + b.ne1f + mrs x0, sctlr_el2 + bic x0, x0, #1 0 // clear SCTLR.M + bic x0, x0, #1 2 // clear SCTLR.C
[PATCH v2 13/15] arm64: add EFI runtime services
From: Mark Salter msal...@redhat.com This patch adds EFI runtime support for arm64. The runtime support allows the kernel to access various EFI runtime services provided by EFI firmware. Things like reboot, real time clock, EFI boot variables, and others. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/Kconfig | 16 ++ arch/arm64/include/asm/efi.h | 14 ++ arch/arm64/kernel/Makefile |1 + arch/arm64/kernel/efi.c | 465 ++ arch/arm64/kernel/setup.c|5 + init/main.c |4 + 6 files changed, 505 insertions(+) create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 6333d49..52d846e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -259,6 +259,20 @@ config CMDLINE_FORCE This is useful if you cannot or don't want to change the command-line options your boot loader passes to the kernel. +config EFI +bool EFI runtime service support + depends on OF + select UCS2_STRING + select LIBFDT + select UEFI_PARAMS_FROM_FDT + help + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + config EFI_STUB bool EFI stub support depends on OF @@ -318,6 +332,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm64/kvm/Kconfig diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h new file mode 100644 index 000..5a46c4e --- /dev/null +++ b/arch/arm64/include/asm/efi.h @@ -0,0 +1,14 @@ +#ifndef _ASM_EFI_H +#define _ASM_EFI_H + +#include asm/io.h + +#ifdef CONFIG_EFI +extern void efi_init(void); +extern void efi_idmap_init(void); +#else +#define efi_init() +#define efi_idmap_init() +#endif + +#endif /* _ASM_EFI_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 0f60b45..4c5a797 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -23,6 +23,7 @@ arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o arm64-obj-$(CONFIG_EFI_STUB) += efi-stub.o efi-entry.o +arm64-obj-$(CONFIG_EFI)+= efi.o obj-y += $(arm64-obj-y) vdso/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c new file mode 100644 index 000..87c4910 --- /dev/null +++ b/arch/arm64/kernel/efi.c @@ -0,0 +1,465 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.4 + * + * Copyright (C) 2013 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/bootmem.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h +#include asm/efi.h +#include asm/tlbflush.h +#include asm/mmu_context.h + +struct efi_memory_map memmap; + +static efi_runtime_services_t *runtime; + +static u64 efi_system_table; + +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) + return 1; + return 0; +} + +static void __init efi_setup_idmap(void) +{ + struct memblock_region *r; + efi_memory_desc_t *md; + u64 paddr, npages, size; + + for_each_memblock(memory, r) + create_id_mapping(r-base, r-size, 0); + + /* map runtime io spaces */ + for_each_efi_memory_desc(memmap, md) { + if (!(md-attribute EFI_MEMORY_RUNTIME) || is_normal_ram(md)) + continue; + paddr = md-phys_addr; + npages = md-num_pages; + memrange_efi_to_native(paddr, npages); + size = npages PAGE_SHIFT; + create_id_mapping(paddr, size, 1); + } +} + +static int __init uefi_init(void) +{ + efi_char16_t *c16; + char vendor[100] = unknown; + int i, retval; + + efi.systab = early_memremap(efi_system_table, + sizeof
[PATCH v2 10/15] arm64: Add function to create identity mappings
From: Mark Salter msal...@redhat.com At boot time, before switching to a virtual UEFI memory map, firmware expects UEFI memory and IO regions to be identity mapped whenever kernel makes runtime services calls. The existing early boot code creates an identity map of kernel text/data but this is not sufficient for UEFI. This patch adds a create_id_mapping() function which reuses the core code of the existing create_mapping(). Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm64/include/asm/mmu.h |2 ++ arch/arm64/mm/mmu.c | 65 ++ 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h index f600d40..29ed1d8 100644 --- a/arch/arm64/include/asm/mmu.h +++ b/arch/arm64/include/asm/mmu.h @@ -28,5 +28,7 @@ extern void paging_init(void); extern void setup_mm_for_reboot(void); extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt); extern void init_mem_pgprot(void); +/* create an identity mapping for memory (or io if map_io is true) */ +extern void create_id_mapping(phys_addr_t addr, phys_addr_t size, int map_io); #endif diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 6b7e895..357956a 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -168,7 +168,8 @@ static void __init *early_alloc(unsigned long sz) } static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, - unsigned long end, unsigned long pfn) + unsigned long end, unsigned long pfn, + pgprot_t prot) { pte_t *pte; @@ -180,16 +181,28 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, pte = pte_offset_kernel(pmd, addr); do { - set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); + set_pte(pte, pfn_pte(pfn, prot)); pfn++; } while (pte++, addr += PAGE_SIZE, addr != end); } static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, - unsigned long end, phys_addr_t phys) + unsigned long end, phys_addr_t phys, + int map_io) { pmd_t *pmd; unsigned long next; + pmdval_t prot_sect; + pgprot_t prot_pte; + + if (map_io) { + prot_sect = PMD_TYPE_SECT | PMD_SECT_AF | + PMD_ATTRINDX(MT_DEVICE_nGnRE); + prot_pte = __pgprot(PROT_DEVICE_nGnRE); + } else { + prot_sect = prot_sect_kernel; + prot_pte = PAGE_KERNEL_EXEC; + } /* * Check for initial section mappings in the pgd/pud and remove them. @@ -205,7 +218,7 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, /* try section mapping first */ if (((addr | next | phys) ~SECTION_MASK) == 0) { pmd_t old_pmd =*pmd; - set_pmd(pmd, __pmd(phys | prot_sect_kernel)); + set_pmd(pmd, __pmd(phys | prot_sect)); /* * Check for previous table entries created during * boot (__create_page_tables) and flush them. @@ -213,21 +226,23 @@ static void __init alloc_init_pmd(pud_t *pud, unsigned long addr, if (!pmd_none(old_pmd)) flush_tlb_all(); } else { - alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys)); + alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys), + prot_pte); } phys += next - addr; } while (pmd++, addr = next, addr != end); } static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, - unsigned long end, unsigned long phys) + unsigned long end, unsigned long phys, + int map_io) { pud_t *pud = pud_offset(pgd, addr); unsigned long next; do { next = pud_addr_end(addr, end); - alloc_init_pmd(pud, addr, next, phys); + alloc_init_pmd(pud, addr, next, phys, map_io); phys += next - addr; } while (pud++, addr = next, addr != end); } @@ -236,30 +251,44 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr, * Create the page directory entries and any necessary page tables for the * mapping specified by 'md'. */ -static void __init create_mapping(phys_addr_t phys, unsigned long virt, - phys_addr_t size) +static void __init __create_mapping(pgd_t *pgd, phys_addr_t phys, + unsigned long virt, phys_addr_t
[PATCH v2 09/15] efi: Add shared FDT related functions for ARM/ARM64
From: Roy Franz roy.fr...@linaro.org Both ARM and ARM64 stubs will update the device tree that they pass to the kernel. In both cases they primarily need to add the same UEFI related information, so the function can be shared. Create a new FDT related file for this to avoid use of architecture #ifdefs in efi-stub-helper.c. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- drivers/firmware/efi/fdt.c | 268 include/linux/efi.h|3 + 2 files changed, 271 insertions(+) create mode 100644 drivers/firmware/efi/fdt.c diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/fdt.c new file mode 100644 index 000..4510f97 --- /dev/null +++ b/drivers/firmware/efi/fdt.c @@ -0,0 +1,268 @@ +/* + * FDT related Helper functions used by the EFI stub on multiple + * architectures. This should be #included by the EFI stub + * implementation files. + * + * Copyright 2013 Linaro Limited; author Roy Franz + * + * This file is part of the Linux kernel, and is made available + * under the terms of the GNU General Public License version 2. + * + */ + +static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, + unsigned long orig_fdt_size, + void *fdt, int new_fdt_size, char *cmdline_ptr, + u64 initrd_addr, u64 initrd_size, + efi_memory_desc_t *memory_map, + unsigned long map_size, unsigned long desc_size, + u32 desc_ver) +{ + int node; + int status; + u32 fdt_val32; + u64 fdt_val64; + + /* +* Copy definition of linux_banner here. Since this code is +* built as part of the decompressor for ARM v7, pulling +* in version.c where linux_banner is defined for the +* kernel brings other kernel dependencies with it. +*/ + const char linux_banner[] = + Linux version UTS_RELEASE ( LINUX_COMPILE_BY @ + LINUX_COMPILE_HOST ) ( LINUX_COMPILER ) UTS_VERSION \n; + + /* Do some checks on provided FDT, if it exists*/ + if (orig_fdt) { + if (fdt_check_header(orig_fdt)) { + pr_efi_err(sys_table, Device Tree header not valid!\n); + return EFI_LOAD_ERROR; + } + /* +* We don't get the size of the FDT if we get if from a +* configuration table. +*/ + if (orig_fdt_size fdt_totalsize(orig_fdt) orig_fdt_size) { + pr_efi_err(sys_table, Truncated device tree! foo!\n); + return EFI_LOAD_ERROR; + } + } + + if (orig_fdt) + status = fdt_open_into(orig_fdt, fdt, new_fdt_size); + else + status = fdt_create_empty_tree(fdt, new_fdt_size); + + if (status != 0) + goto fdt_set_fail; + + /* Delete any memory nodes present */ + while ((node = fdt_subnode_offset(fdt, 0, memory)) = 0) + fdt_del_node(fdt, node); + + node = fdt_subnode_offset(fdt, 0, chosen); + if (node 0) { + node = fdt_add_subnode(fdt, 0, chosen); + if (node 0) { + status = node; /* node is error code when negative */ + goto fdt_set_fail; + } + } + + if ((cmdline_ptr != NULL) (strlen(cmdline_ptr) 0)) { + status = fdt_setprop(fdt, node, bootargs, cmdline_ptr, +strlen(cmdline_ptr) + 1); + if (status) + goto fdt_set_fail; + } + + /* Set initrd address/end in device tree, if present */ + if (initrd_size != 0) { + u64 initrd_image_end; + u64 initrd_image_start = cpu_to_fdt64(initrd_addr); + status = fdt_setprop(fdt, node, linux,initrd-start, +initrd_image_start, sizeof(u64)); + if (status) + goto fdt_set_fail; + initrd_image_end = cpu_to_fdt64(initrd_addr + initrd_size); + status = fdt_setprop(fdt, node, linux,initrd-end, +initrd_image_end, sizeof(u64)); + if (status) + goto fdt_set_fail; + } + + /* Add FDT entries for EFI runtime services in chosen node. */ + node = fdt_subnode_offset(fdt, 0, chosen); + fdt_val64 = cpu_to_fdt64((u64)(unsigned long)sys_table); + status = fdt_setprop(fdt, node, linux,uefi-system-table, +fdt_val64, sizeof(fdt_val64)); + if (status) + goto fdt_set_fail; + + fdt_val64 = cpu_to_fdt64((u64)(unsigned long
[PATCH v2 07/15] efi: Add shared printk wrapper for consistent prefixing
From: Roy Franz roy.fr...@linaro.org Add a wrapper for printk to standardize the prefix for informational and error messages from the EFI stub. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi-stub-helper.c | 25 ++--- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 661f425..4c8ab86 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -45,6 +45,9 @@ static void efi_printk(efi_system_table_t *sys_table_arg, char *str) } } +#define pr_efi(sys_table, msg) efi_printk(sys_table, EFI stub: msg) +#define pr_efi_err(sys_table, msg) efi_printk(sys_table, EFI stub: ERROR: msg) + static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, efi_memory_desc_t **map, @@ -324,7 +327,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, nr_files * sizeof(*files), (void **)files); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to alloc mem for file handle list\n); + pr_efi_err(sys_table_arg, Failed to alloc mem for file handle list\n); goto fail; } @@ -376,13 +379,13 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, image-device_handle, fs_proto, (void **)io); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to handle fs_proto\n); + pr_efi_err(sys_table_arg, Failed to handle fs_proto\n); goto free_files; } status = efi_call_phys2(io-open_volume, io, fh); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to open volume\n); + pr_efi_err(sys_table_arg, Failed to open volume\n); goto free_files; } } @@ -390,7 +393,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, status = efi_call_phys5(fh-open, fh, h, filename_16, EFI_FILE_MODE_READ, (u64)0); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to open file: ); + pr_efi_err(sys_table_arg, Failed to open file: ); efi_char16_printk(sys_table_arg, filename_16); efi_printk(sys_table_arg, \n); goto close_handles; @@ -402,7 +405,7 @@ static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, status = efi_call_phys4(h-get_info, h, info_guid, info_sz, NULL); if (status != EFI_BUFFER_TOO_SMALL) { - efi_printk(sys_table_arg, Failed to get file info size\n); + pr_efi_err(sys_table_arg, Failed to get file info size\n); goto close_handles; } @@ -411,7 +414,7 @@ grow: EFI_LOADER_DATA, info_sz, (void **)info); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to alloc mem for file info\n); + pr_efi_err(sys_table_arg, Failed to alloc mem for file info\n); goto close_handles; } @@ -427,7 +430,7 @@ grow: efi_call_phys1(sys_table_arg-boottime-free_pool, info); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to get file info\n); + pr_efi_err(sys_table_arg, Failed to get file info\n); goto close_handles; } @@ -446,13 +449,13 @@ grow: status = efi_high_alloc(sys_table_arg, file_size_total, 0x1000, file_addr, max_addr); if (status != EFI_SUCCESS) { - efi_printk(sys_table_arg, Failed to alloc highmem for files\n); + pr_efi_err(sys_table_arg, Failed to alloc highmem for files\n); goto close_handles; } /* We've run out of free low memory. */ if (file_addr max_addr) { - efi_printk(sys_table_arg, We've run out of free low memory\n); + pr_efi_err(sys_table_arg, We've run out of free low
[PATCH v2 08/15] efi: Add get_dram_base() helper function
From: Roy Franz roy.fr...@linaro.org Add the get_dram_base() function, shared by arm/arm64. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi-stub-helper.c | 30 ++ 1 file changed, 30 insertions(+) diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 4c8ab86..4a9986b 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -11,6 +11,10 @@ */ #define EFI_READ_CHUNK_SIZE(1024 * 1024) +/* error code which can't be mistaken for valid address */ +#define EFI_ERROR (~0UL) + + struct file_info { efi_file_handle_t *handle; u64 size; @@ -92,6 +96,32 @@ fail: return status; } + +static unsigned long __init get_dram_base(efi_system_table_t *sys_table) +{ + efi_status_t status; + unsigned long map_size; + unsigned long membase = EFI_ERROR; + struct efi_memory_map map; + efi_memory_desc_t *md; + + status = efi_get_memory_map(sys_table, (efi_memory_desc_t **)map.map, + map_size, map.desc_size, NULL, NULL); + if (status != EFI_SUCCESS) + return membase; + + map.map_end = map.map + map_size; + + for_each_efi_memory_desc(map, md) + if (md-attribute EFI_MEMORY_WB) + if (membase md-phys_addr) + membase = md-phys_addr; + + efi_call_phys1(sys_table-boottime-free_pool, map.map); + + return membase; +} + /* * Allocate at the highest possible address that is not above 'max'. */ -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 06/15] doc: efi-stub.txt updates for ARM
From: Roy Franz roy.fr...@linaro.org Update efi-stub.txt documentation to be more general and not x86 specific. Add ARM only dtb= command line option description. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- Documentation/efi-stub.txt | 27 --- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Documentation/efi-stub.txt b/Documentation/efi-stub.txt index c628788..26be7b0 100644 --- a/Documentation/efi-stub.txt +++ b/Documentation/efi-stub.txt @@ -1,13 +1,16 @@ The EFI Boot Stub --- -On the x86 platform, a bzImage can masquerade as a PE/COFF image, -thereby convincing EFI firmware loaders to load it as an EFI -executable. The code that modifies the bzImage header, along with the -EFI-specific entry point that the firmware loader jumps to are -collectively known as the EFI boot stub, and live in +On the x86 and ARM platforms, a kernel zImage/bzImage can masquerade +as a PE/COFF image, thereby convincing EFI firmware loaders to load +it as an EFI executable. The code that modifies the bzImage header, +along with the EFI-specific entry point that the firmware loader +jumps to are collectively known as the EFI boot stub, and live in arch/x86/boot/header.S and arch/x86/boot/compressed/eboot.c, -respectively. +respectively. For ARM the EFI stub is implemented in +arch/arm/boot/compressed/efi-header.S and +arch/arm/boot/compressed/efi-stub.c. EFI stub code that is shared +between architectures is in drivers/firmware/efi/efi-stub-helper.c. By using the EFI boot stub it's possible to boot a Linux kernel without the use of a conventional EFI boot loader, such as grub or @@ -23,7 +26,9 @@ The bzImage located in arch/x86/boot/bzImage must be copied to the EFI System Partition (ESP) and renamed with the extension .efi. Without the extension the EFI firmware loader will refuse to execute it. It's not possible to execute bzImage.efi from the usual Linux file systems -because EFI firmware doesn't have support for them. +because EFI firmware doesn't have support for them. For ARM the +arch/arm/boot/zImage should be copied to the system partition, and it +may not need to be renamed. Passing kernel parameters from the EFI shell @@ -63,3 +68,11 @@ Notice how bzImage.efi can be specified with a relative path. That's because the image we're executing is interpreted by the EFI shell, which understands relative paths, whereas the rest of the command line is passed to bzImage.efi. + + + The dtb= option + +For the ARM architecture, we also need to be able to provide a device +tree to the kernel. This is done with the dtb= command line option, +and is processed in the same manner as the initrd= option that is +described above. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 04/15] lib: add fdt_empty_tree.c
From: Mark Salter msal...@redhat.com CONFIG_LIBFDT support does not include fdt_empty_tree.c which is needed by arm64 EFI stub. Add it to libfdt_files. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- lib/Makefile |3 ++- lib/fdt_empty_tree.c |2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 lib/fdt_empty_tree.c diff --git a/lib/Makefile b/lib/Makefile index 48140e3..befe555 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -147,7 +147,8 @@ obj-$(CONFIG_GENERIC_NET_UTILS) += net_utils.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o -libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o +libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ + fdt_empty_tree.o $(foreach file, $(libfdt_files), \ $(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt)) lib-$(CONFIG_LIBFDT) += $(libfdt_files) diff --git a/lib/fdt_empty_tree.c b/lib/fdt_empty_tree.c new file mode 100644 index 000..5d30c58 --- /dev/null +++ b/lib/fdt_empty_tree.c @@ -0,0 +1,2 @@ +#include linux/libfdt_env.h +#include ../scripts/dtc/libfdt/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 00/14] UEFI support for arm(64)
Since all prerequisites are not ready for the (32-bit) arm patches to go in, I have broken these out of this set and will be resubmitting them separately. This set now provides arm64 support only - but includes the code that is common between the ARM ports. Prerequisites for this set are: - Mark Salter's generic early_ioremap() - Matt Fleming's efi_enabled() rework Changes from the last upstream posting: - Some cleanup based on feedback - Fixed range test in create_id_mapping() - Fixed name of guard ifdef in arch/arm64/include/asm/efi.h - Fixed memory corruption bug caused by late use of create_id_mapping(). That function uses memblock_alloc() to allocate new pmd/pte pages and it was being called after slab allocator was initialized. This led to possibility that the allocated memory for pmd/pte was already in use by something else. Now, create_id_mapping() gets called just after paging_init() when it is still okay to use memblock_alloc(). - Fixed whitespace error in efi-entry.S - Now support 64K pagesize in EFI runtime - Undid the breakage I caused to Ard's dtb= SecureBoot patch --- Ard Biesheuvel (1): efi/arm64: ignore dtb= when UEFI SecureBoot is enabled H. Peter Anvin (1): efi: x86: Improve cmdline conversion Leif Lindholm (2): efi: delete stray ARM ifdef doc: arm: add UEFI support documentation Mark Salter (7): efi: create memory map iteration helper lib: add fdt_empty_tree.c efi: add helper function to get UEFI params from FDT arm64: Add function to create identity mappings arm64: add EFI stub doc: arm64: add description of EFI stub support arm64: add EFI runtime services Roy Franz (4): doc: efi-stub.txt updates for ARM efi: Add shared printk wrapper for consistent prefixing efi: Add get_dram_base() helper function efi: Add shared FDT related functions for ARM/ARM64 Documentation/arm/00-INDEX |2 + Documentation/arm/uefi.txt | 64 + Documentation/arm64/booting.txt|4 + Documentation/efi-stub.txt | 33 ++- arch/arm64/Kconfig | 26 ++ arch/arm64/include/asm/efi.h | 14 + arch/arm64/include/asm/mmu.h |2 + arch/arm64/kernel/Makefile |4 + arch/arm64/kernel/efi-entry.S | 93 +++ arch/arm64/kernel/efi-stub.c | 83 ++ arch/arm64/kernel/efi.c| 465 arch/arm64/kernel/head.S | 112 arch/arm64/kernel/setup.c |5 + arch/arm64/mm/mmu.c| 65 +++-- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/Kconfig |7 + drivers/firmware/efi/arm-stub.c| 149 ++ drivers/firmware/efi/efi-stub-helper.c | 182 ++--- drivers/firmware/efi/efi.c | 79 ++ drivers/firmware/efi/fdt.c | 268 ++ include/linux/efi.h| 18 ++ init/main.c|4 + lib/Makefile |3 +- lib/fdt_empty_tree.c |2 + 24 files changed, 1615 insertions(+), 72 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm64/include/asm/efi.h create mode 100644 arch/arm64/kernel/efi-entry.S create mode 100644 arch/arm64/kernel/efi-stub.c create mode 100644 arch/arm64/kernel/efi.c create mode 100644 drivers/firmware/efi/arm-stub.c create mode 100644 drivers/firmware/efi/fdt.c create mode 100644 lib/fdt_empty_tree.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 05/15] efi: add helper function to get UEFI params from FDT
From: Mark Salter msal...@redhat.com ARM and ARM64 architectures use the device tree to pass UEFI parameters from stub to kernel. These parameters are things known to the stub but not discoverable by the kernel after the stub calls ExitBootSerives(). There is a helper function in: drivers/firmware/efi/fdt.c which the stub uses to add the UEFI parameters to the device tree. This patch adds a complimentary helper function which UEFI runtime support may use to retrieve the parameters from the device tree. If an architecture wants to use this helper, it should select CONFIG_UEFI_PARAMS_FROM_FDT. Signed-off-by: Mark Salter msal...@redhat.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/Kconfig |7 drivers/firmware/efi/efi.c | 79 ++ include/linux/efi.h |9 + 3 files changed, 95 insertions(+) diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index 1e75f48..d3fe28d 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig @@ -47,6 +47,13 @@ config EFI_RUNTIME_MAP See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. +config UEFI_PARAMS_FROM_FDT + bool + help + Select this config option from the architecture Kconfig if + the EFI runtime support gets system table address, memory + map address, and other parameters from the device tree. + endmenu config UEFI_CPER diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index b25b36b..7f6e977 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -20,6 +20,8 @@ #include linux/init.h #include linux/device.h #include linux/efi.h +#include linux/of.h +#include linux/of_fdt.h #include linux/io.h struct efi __read_mostly efi = { @@ -318,3 +320,80 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) return 0; } + +#ifdef CONFIG_UEFI_PARAMS_FROM_FDT + +#define UEFI_PARAM(name, prop, field) \ + { \ + { name }, \ + { prop }, \ + offsetof(struct efi_fdt_params, field),\ + FIELD_SIZEOF(struct efi_fdt_params, field) \ + } + +static __initdata struct { + const char name[32]; + const char propname[32]; + int offset; + int size; +} dt_params[] = { + UEFI_PARAM(System Table, linux,uefi-system-table, system_table), + UEFI_PARAM(MemMap Address, linux,uefi-mmap-start, mmap), + UEFI_PARAM(MemMap Size, linux,uefi-mmap-size, mmap_size), + UEFI_PARAM(MemMap Desc. Size, linux,uefi-mmap-desc-size, desc_size), + UEFI_PARAM(MemMap Desc. Version, linux,uefi-mmap-desc-ver, desc_ver) +}; + +struct param_info { + int verbose; + void *params; +}; + +static int __init fdt_find_uefi_params(unsigned long node, const char *uname, + int depth, void *data) +{ + struct param_info *info = data; + void *prop, *dest; + unsigned long len; + u64 val; + int i; + + if (depth != 1 || + (strcmp(uname, chosen) != 0 strcmp(uname, chosen@0) != 0)) + return 0; + + pr_info(Getting parameters from FDT:\n); + + for (i = 0; i ARRAY_SIZE(dt_params); i++) { + prop = of_get_flat_dt_prop(node, dt_params[i].propname, len); + if (!prop) { + pr_err(Can't find %s in device tree!\n, + dt_params[i].name); + return 0; + } + dest = info-params + dt_params[i].offset; + + val = of_read_number(prop, len / sizeof(u32)); + + if (dt_params[i].size == sizeof(u32)) + *(u32 *)dest = val; + else + *(u64 *)dest = val; + + if (info-verbose) + 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) +{ + struct param_info info; + + info.verbose = verbose; + info.params = params; + + return of_scan_flat_dt(fdt_find_uefi_params, info); +} +#endif /* CONFIG_UEFI_PARAMS_FROM_FDT */ diff --git a/include/linux/efi.h b/include/linux/efi.h index a3276da..d450673 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -483,6 +483,14 @@ struct efi_memory_map { unsigned long desc_size; }; +struct efi_fdt_params { + u64 system_table; + u64 mmap; + u32 mmap_size; + u32 desc_size; + u32 desc_ver; +}; + typedef struct { u32 revision; void *parent_handle; @@ -620,6 +628,7 @@ extern void
[PATCH v2 02/15] efi: x86: Improve cmdline conversion
From: H. Peter Anvin h...@zytor.com Improve the conversion of the UTF-16 EFI command line to UTF-8 for passing to the kernel. Signed-off-by: Roy Franz roy.fr...@linaro.org Signed-off-by: H. Peter Anvin h...@zytor.com Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/boot/compressed/eboot.c |3 +- drivers/firmware/efi/efi-stub-helper.c | 91 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index a7677ba..feca05f 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -488,8 +488,7 @@ struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) hdr-type_of_loader = 0x21; /* Convert unicode cmdline to ascii */ - cmdline_ptr = efi_convert_cmdline_to_ascii(sys_table, image, - options_size); + cmdline_ptr = efi_convert_cmdline(sys_table, image, options_size); if (!cmdline_ptr) goto fail; hdr-cmd_line_ptr = (unsigned long)cmdline_ptr; diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index 6811af7..661f425 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -575,52 +575,99 @@ static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, } /* - * Convert the unicode UEFI command line to ASCII to pass to kernel. + * Get the number of UTF-8 bytes corresponding to an UTF-16 character. + * This overestimates for surrogates, but that is okay. + */ +static int efi_utf8_bytes(u16 c) +{ + return 1 + (c = 0x80) + (c = 0x800); +} + +/* + * Convert an UTF-16 string, not necessarily null terminated, to UTF-8. + */ +static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n) +{ + unsigned int c; + + while (n--) { + c = *src++; + if (n c = 0xd800 c = 0xdbff + *src = 0xdc00 *src = 0xdfff) { + c = 0x1 + ((c 0x3ff) 10) + (*src 0x3ff); + src++; + n--; + } + if (c = 0xd800 c = 0xdfff) + c = 0xfffd; /* Unmatched surrogate */ + if (c 0x80) { + *dst++ = c; + continue; + } + if (c 0x800) { + *dst++ = 0xc0 + (c 6); + goto t1; + } + if (c 0x1) { + *dst++ = 0xe0 + (c 12); + goto t2; + } + *dst++ = 0xf0 + (c 18); + *dst++ = 0x80 + ((c 12) 0x3f); +t2: + *dst++ = 0x80 + ((c 6) 0x3f); +t1: + *dst++ = 0x80 + (c 0x3f); + } + + return dst; +} + +/* + * Do proper conversion from UTF-16 to UTF-8 * Size of memory allocated return in *cmd_line_len. * Returns NULL on error. */ -static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg, - efi_loaded_image_t *image, - int *cmd_line_len) +static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, +efi_loaded_image_t *image, +int *cmd_line_len) { - u16 *s2; + const u16 *s2; u8 *s1 = NULL; unsigned long cmdline_addr = 0; - int load_options_size = image-load_options_size / 2; /* ASCII */ - void *options = image-load_options; - int options_size = 0; + int load_options_chars = image-load_options_size / 2; /* UTF-16 */ + const u16 *options = image-load_options; + int options_bytes = 0; /* UTF-8 bytes */ + int options_chars = 0; /* UTF-16 chars */ efi_status_t status; - int i; u16 zero = 0; if (options) { s2 = options; - while (*s2 *s2 != '\n' options_size load_options_size) { - s2++; - options_size++; + while (options_chars load_options_chars + *s2 *s2 != '\n') { + options_bytes += efi_utf8_bytes(*s2++); + options_chars++; } } - if (options_size == 0) { - /* No command line options, so return empty string*/ - options_size = 1; + if (!options_chars) { + /* No command line options, so return empty string */ options = zero; } - options_size++; /* NUL termination */ + options_bytes++; /* NUL termination */ - status = efi_low_alloc(sys_table_arg, options_size, 0, cmdline_addr); + status = efi_low_alloc(sys_table_arg, options_bytes, 0, cmdline_addr
[PATCH v2 01/15] efi: delete stray ARM ifdef
An #ifdef CONFIG_ARM clause in efi-stub-helper.c got included with some of the generic stub rework by Roy Franz. Drop it here to make subsequent patches less confusing. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- drivers/firmware/efi/efi-stub-helper.c | 14 ++ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/efi-stub-helper.c index b6bffbf..6811af7 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/efi-stub-helper.c @@ -608,18 +608,8 @@ static char *efi_convert_cmdline_to_ascii(efi_system_table_t *sys_table_arg, } options_size++; /* NUL termination */ -#ifdef CONFIG_ARM - /* -* For ARM, allocate at a high address to avoid reserved -* regions at low addresses that we don't know the specfics of -* at the time we are processing the command line. -*/ - status = efi_high_alloc(sys_table_arg, options_size, 0, - cmdline_addr, 0xf000); -#else - status = efi_low_alloc(sys_table_arg, options_size, 0, - cmdline_addr); -#endif + + status = efi_low_alloc(sys_table_arg, options_size, 0, cmdline_addr); if (status != EFI_SUCCESS) return NULL; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4 4/6] arm: add early_ioremap support
Hi Rob, Thanks for having a look. Since I'm at least partially responsible for the below, I'll respond before Mark wakes up. On Tue, Feb 25, 2014 at 11:48:19PM -0600, Rob Herring wrote: On Wed, Feb 12, 2014 at 2:56 PM, Mark Salter msal...@redhat.com wrote: This patch uses the generic early_ioremap code to implement early_ioremap for ARM. The ARM-specific bits come mostly from an earlier patch from Leif Lindholm leif.lindh...@linaro.org here: This doesn't actually work for me. The PTE flags are not correct and accesses to a device fault. See below. Do they fault before paging_init()? If not, see below. https://lkml.org/lkml/2013/10/3/279 Signed-off-by: Mark Salter msal...@redhat.com Tested-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Catalin Marinas catalin.mari...@arm.com --- arch/arm/Kconfig | 10 + arch/arm/include/asm/Kbuild | 1 + arch/arm/include/asm/fixmap.h | 20 ++ arch/arm/include/asm/io.h | 1 + arch/arm/kernel/setup.c | 2 + arch/arm/mm/Makefile | 4 ++ arch/arm/mm/early_ioremap.c | 93 +++ arch/arm/mm/mmu.c | 2 + 8 files changed, 133 insertions(+) create mode 100644 arch/arm/mm/early_ioremap.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e254198..7a35ef6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1874,6 +1874,16 @@ config UACCESS_WITH_MEMCPY However, if the CPU data cache is using a write-allocate mode, this option is unlikely to provide any performance gain. +config EARLY_IOREMAP + bool Provide early_ioremap() support for kernel initialization + select GENERIC_EARLY_IOREMAP + help + Provide a mechanism for kernel initialisation code to temporarily + map, in a highmem-agnostic way, memory pages in before ioremap() + and friends are available (before paging_init() has run). It uses + the same virtual memory range as kmap so all early mappings must + be unmapped before paging_init() is called. + ^^ config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 3278afe..6fcfd7d 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -4,6 +4,7 @@ generic-y += auxvec.h generic-y += bitsperlong.h generic-y += cputime.h generic-y += current.h +generic-y += early_ioremap.h generic-y += emergency-restart.h generic-y += errno.h generic-y += exec.h diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index 68ea615..ff8fa3e 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -21,8 +21,28 @@ enum fixed_addresses { FIX_KMAP_BEGIN, FIX_KMAP_END = (FIXADDR_TOP - FIXADDR_START) PAGE_SHIFT, __end_of_fixed_addresses +/* + * 224 temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + * + * (P)re-using the FIXADDR region, which is used for highmem + * later on, and statically aligned to 1MB. + */ +#define NR_FIX_BTMAPS 32 +#define FIX_BTMAPS_SLOTS 7 +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) +#define FIX_BTMAP_END FIX_KMAP_BEGIN +#define FIX_BTMAP_BEGIN(FIX_BTMAP_END + TOTAL_FIX_BTMAPS - 1) Why the different logic from arm64? Specifically, it doesn't make adding a permanent mapping simple. Making a permanent mapping using this would require either: - Not using the fixmap region. - Rewriting arm kmap. }; +#define FIXMAP_PAGE_COMMON (L_PTE_YOUNG | L_PTE_PRESENT | L_PTE_XN) + +#define FIXMAP_PAGE_NORMAL (FIXMAP_PAGE_COMMON | L_PTE_MT_WRITEBACK) +#define FIXMAP_PAGE_IO(FIXMAP_PAGE_COMMON | L_PTE_MT_DEV_NONSHARED) This should be L_PTE_MT_DEV_SHARED and also needs L_PTE_DIRTY and L_PTE_SHARED as we want this to match MT_DEVICE. These should also be wrapped with __pgprot(). Ok. + +extern void __early_set_fixmap(enum fixed_addresses idx, + phys_addr_t phys, pgprot_t flags); + #include asm-generic/fixmap.h #endif diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 8aa4cca..637e0cd 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -28,6 +28,7 @@ #include asm/byteorder.h #include asm/memory.h #include asm-generic/pci_iomap.h +#include asm/early_ioremap.h #include xen/xen.h /* diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index b0df976..9c8b751 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -30,6 +30,7 @@ #include linux/bug.h #include linux/compiler.h #include linux/sort.h +#include linux/io.h #include asm/unified.h
[PATCH v4 0/5] arm: add UEFI runtime services support
In systems based on [U]EFI-conformant firmware, runtime services provide a standardised way for the kernel to update firmware environment variables. This is used for example by efibootmgr to update which image should be loaded on next boot. This patchset implements basic support for UEFI runtime services on ARM platforms, as well as the basic underlying EFI support. It also defines a mechanism by which the required information is passed from the bootloader (the EFI stub submitted separately) to the kernel via FDT entries. This patchset depends on the presence of early_ioremap(). It has been validated against Mark Salter's generic implementation. It also depends on Mark's efi: add helper function to get UEFI params from FDT patch. Changes since v3: - Use new common function (from arm64 set) for extracting UEFI params from FDT. - Use new generic early_ioremap implementation (with early_memunmap). - Reworked/simplified phys_call code, using new shared functions/macros. - Slightly refactored to reduce number of explicit casts. - Also preserve and map EFI_ACPI_MEMORY_NVS regions. - Added some ACKs. Change since v2: - Updated FDT bindings. - Preserve regions marked RESERVED (but don't map them). - Rename 'efi' - 'uefi' within this new port (leaving core code as is). Leif Lindholm (5): arm: break part of __soft_restart out into separate function arm: add new asm macro update_sctlr Documentation: arm: add UEFI support documentation arm: Add [U]EFI runtime services support init: efi: arm: enable (U)EFI runtime services on arm Documentation/arm/00-INDEX |3 + Documentation/arm/uefi.txt | 61 ++ arch/arm/Kconfig | 16 ++ arch/arm/include/asm/assembler.h | 13 ++ arch/arm/include/asm/idmap.h |1 + arch/arm/include/asm/uefi.h | 28 +++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/process.c| 12 +- arch/arm/kernel/setup.c |4 + arch/arm/kernel/uefi.c | 418 ++ arch/arm/kernel/uefi_phys.S | 67 ++ arch/arm/mm/idmap.c | 15 ++ include/linux/efi.h |2 +- init/main.c |4 + 14 files changed, 634 insertions(+), 12 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm/include/asm/uefi.h create mode 100644 arch/arm/kernel/uefi.c create mode 100644 arch/arm/kernel/uefi_phys.S -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 3/5] Documentation: arm: add UEFI support documentation
This patch provides documentation of the [U]EFI runtime service and configuration features for the arm architecture. Cc: Rob Landley r...@landley.net Cc: linux-...@vger.kernel.org Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- Documentation/arm/00-INDEX |3 +++ Documentation/arm/uefi.txt | 61 2 files changed, 64 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 36420e1..b3af704 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -34,3 +34,6 @@ nwfpe/ - NWFPE floating point emulator documentation swp_emulation - SWP/SWPB emulation handler/logging description + +uefi.txt + - [U]EFI configuration and runtime services documentation diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..04da9ce --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,61 @@ +UEFI, the Unified Extensible Firmware Interface, is a specification +governing the behaviours of compatible firmware interfaces. It is +maintained by the UEFI Forum - http://www.uefi.org/. + +UEFI is an evolution of its predecessor 'EFI', so the terms EFI and +UEFI are used somewhat interchangeably in this document and associated +source code. As a rule, anything new uses 'UEFI', whereas 'EFI' refers +to legacy code or specifications. + +UEFI support in Linux += +Booting on a platform with firmware compliant with the UEFI specification +makes it possible for the kernel to support additional features: +- UEFI Runtime Services +- Retrieving various configuration information through the standardised + interface of UEFI configuration tables. (ACPI, SMBIOS, ...) + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +The implementation depends on receiving information about the UEFI environment +in a Flattened Device Tree (FDT) - so is only available with CONFIG_OF. + +UEFI stub += +The stub is a feature that extends the Image/zImage into a valid UEFI +PE/COFF executable, including a loader application that makes it possible to +load the kernel directly from the UEFI shell, boot menu, or one of the +lightweight bootloaders like Gummiboot or rEFInd. + +The kernel image built with stub support remains a valid kernel image for +booting in non-UEFI environments. + +UEFI kernel support on ARM +== +UEFI kernel support on the ARM architectures (arm and arm64) is only available +when boot is performed through the stub. + +The stub populates the FDT /chosen node with (and the kernel scans for) the +following parameters: + +Name | Size | Description + +linux,uefi-system-table | 64-bit | Physical address of the UEFI System Table. + +linux,uefi-mmap-start | 64-bit | Physical address of the UEFI memory map, + || populated by the UEFI GetMemoryMap() call. + +linux,uefi-mmap-size | 32-bit | Size in bytes of the UEFI memory map + || pointed to in previous entry. + +linux,uefi-mmap-desc-size | 32-bit | Size in bytes of each entry in the UEFI + || memory map. + +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. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 4/5] arm: Add [U]EFI runtime services support
This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It uses the generic configuration table scanning to populate ACPI and SMBIOS pointers. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Reviewed-by: Grant Likely grant.lik...@linaro.org Cc: Arnd Bergmann a...@arndb.de Cc: Will Deacon will.dea...@arm.com --- arch/arm/Kconfig| 16 ++ arch/arm/include/asm/uefi.h | 28 +++ arch/arm/kernel/Makefile|2 + arch/arm/kernel/setup.c |4 + arch/arm/kernel/uefi.c | 418 +++ arch/arm/kernel/uefi_phys.S | 67 +++ include/linux/efi.h |2 +- 7 files changed, 536 insertions(+), 1 deletion(-) create mode 100644 arch/arm/include/asm/uefi.h create mode 100644 arch/arm/kernel/uefi.c create mode 100644 arch/arm/kernel/uefi_phys.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 78a79a6a..1ab24cc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1853,6 +1853,20 @@ config EARLY_IOREMAP the same virtual memory range as kmap so all early mappings must be unapped before paging_init() is called. +config EFI + bool UEFI runtime service support + depends on OF !CPU_BIG_ENDIAN + select UCS2_STRING + select EARLY_IOREMAP + select UEFI_PARAMS_FROM_FDT + ---help--- + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel will + continue to boot on non-UEFI platforms. + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode @@ -2272,6 +2286,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm/Kconfig.debug diff --git a/arch/arm/include/asm/uefi.h b/arch/arm/include/asm/uefi.h new file mode 100644 index 000..eff27da --- /dev/null +++ b/arch/arm/include/asm/uefi.h @@ -0,0 +1,28 @@ +#ifndef _ASM_ARM_EFI_H +#define _ASM_ARM_EFI_H + +#ifdef CONFIG_EFI +#include asm/mach/map.h + +extern void uefi_memblock_arm_reserve_range(void); + +typedef efi_status_t uefi_phys_call_t(efi_set_virtual_address_map_t *f, + u32 virt_phys_offset, + u32 memory_map_size, + u32 descriptor_size, + u32 descriptor_version, + efi_memory_desc_t *dsc); + +extern efi_status_t uefi_phys_call(u32, u32, u32, efi_memory_desc_t *, + efi_set_virtual_address_map_t *); + +#define uefi_remap(cookie, size) __arm_ioremap((cookie), (size), MT_MEMORY) +#define uefi_ioremap(cookie, size) __arm_ioremap((cookie), (size), MT_DEVICE) +#define uefi_unmap(cookie) __arm_iounmap((cookie)) +#define uefi_iounmap(cookie) __arm_iounmap((cookie)) + +#else +#define uefi_memblock_arm_reserve_range() +#endif /* CONFIG_EFI */ + +#endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index a30fc9b..736cce4 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -98,4 +98,6 @@ obj-y += psci.o obj-$(CONFIG_SMP) += psci_smp.o endif +obj-$(CONFIG_EFI) += uefi.o uefi_phys.o + extra-y := $(head-y) vmlinux.lds diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 038fb75..57c33dd 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -30,6 +30,7 @@ #include linux/bug.h #include linux/compiler.h #include linux/sort.h +#include linux/efi.h #include asm/unified.h #include asm/cp15.h @@ -57,6 +58,7 @@ #include asm/unwind.h #include asm/memblock.h #include asm/virt.h +#include asm/uefi.h #include atags.h @@ -897,6 +899,8 @@ void __init setup_arch(char **cmdline_p) sanity_check_meminfo(); arm_memblock_init(meminfo, mdesc); + uefi_memblock_arm_reserve_range(); + paging_init(mdesc); request_standard_resources(mdesc); diff --git a/arch/arm/kernel/uefi.c b/arch/arm/kernel/uefi.c new file mode 100644 index 000..65e7b05 --- /dev/null +++ b/arch/arm/kernel/uefi.c @@ -0,0 +1,418 @@ +/* + * Based on Unified Extensible Firmware Interface Specification version 2.3.1 + * + * Copyright (C) 2013-2014 Linaro Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h
[PATCH v4 5/5] init: efi: arm: enable (U)EFI runtime services on arm
Since the efi_set_virtual_address_map call has strict init ordering requirements, add an explicit hook in the required place. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Grant Likely grant.lik...@linaro.org --- init/main.c |4 1 file changed, 4 insertions(+) diff --git a/init/main.c b/init/main.c index febc511..1331829 100644 --- a/init/main.c +++ b/init/main.c @@ -905,6 +905,10 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + + if (IS_ENABLED(CONFIG_ARM) efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); + lockup_detector_init(); smp_init(); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 2/5] arm: add new asm macro update_sctlr
A new macro for setting/clearing bits in the SCTLR. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Suggested-by: Will Deacon will.dea...@arm.com --- arch/arm/include/asm/assembler.h | 13 + 1 file changed, 13 insertions(+) diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 5c22851..aba6458 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -383,4 +383,17 @@ THUMB( orr \reg , \reg , #PSR_T_BIT) #endif .endm +#ifdef CONFIG_CPU_CP15 +/* Macro for setting/clearing bits in sctlr */ + .macro update_sctlr, set:req, clear:req, tmp:req, tmp2:req + mrc p15, 0, \tmp, c1, c0, 0 + ldr \tmp2, =\set + orr \tmp, \tmp, \tmp2 + ldr \tmp2, =\clear + mvn \tmp2, \tmp2 + and \tmp, \tmp, \tmp2 + mcr p15, 0, \tmp, c1, c0, 0 + .endm +#endif + #endif /* __ASM_ASSEMBLER_H__ */ -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 1/5] arm: break part of __soft_restart out into separate function
Certain operations can be considered mandatory for any piece of code preparing to switch off the MMU. Break this out into separate function dmap_prepare(). Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Suggested-by: Will Deacon will.dea...@arm.com --- arch/arm/include/asm/idmap.h |1 + arch/arm/kernel/process.c| 12 +--- arch/arm/mm/idmap.c | 15 +++ 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/arch/arm/include/asm/idmap.h b/arch/arm/include/asm/idmap.h index bf863ed..2e914a8 100644 --- a/arch/arm/include/asm/idmap.h +++ b/arch/arm/include/asm/idmap.h @@ -10,5 +10,6 @@ extern pgd_t *idmap_pgd; void setup_mm_for_reboot(void); +void idmap_prepare(void); #endif /* __ASM_IDMAP_H */ diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 92f7b15..91b4cec 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -75,17 +75,7 @@ static void __soft_restart(void *addr) { phys_reset_t phys_reset; - /* Take out a flat memory mapping. */ - setup_mm_for_reboot(); - - /* Clean and invalidate caches */ - flush_cache_all(); - - /* Turn off caching */ - cpu_proc_fin(); - - /* Push out any further dirty data, and ensure cache is empty */ - flush_cache_all(); + idmap_prepare(); /* Switch to the identity mapping. */ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 8e0e52e..5c85779 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -122,3 +122,18 @@ void setup_mm_for_reboot(void) local_flush_tlb_all(); #endif } + +void idmap_prepare(void) +{ + /* Take out a flat memory mapping. */ + setup_mm_for_reboot(); + + /* Clean and invalidate caches */ + flush_cache_all(); + + /* Turn off caching */ + cpu_proc_fin(); + + /* Push out any further dirty data, and ensure cache is empty */ + flush_cache_all(); +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4 5/5] init: efi: arm: enable (U)EFI runtime services on arm
On Mon, Jan 13, 2014 at 07:29:06PM +0100, Arnd Bergmann wrote: On Saturday 11 January 2014, Leif Lindholm wrote: diff --git a/init/main.c b/init/main.c index febc511..1331829 100644 --- a/init/main.c +++ b/init/main.c @@ -905,6 +905,10 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + + if (IS_ENABLED(CONFIG_ARM) efi_enabled(EFI_BOOT)) + efi_enter_virtual_mode(); What is the dependency on CONFIG_ARM here? Wouldn't most other architectures need the same? Most 64-bit architectures could get away from it. x86 does it where its particular init environment forces it to. For arm, the strict ordering requirement is for efi_enter_virtual_mode to be called after init_static_idmap. If ordering between early_initcalls was possible in a sane way, I could do that instead, but I don't think a patch that swapped order of kernel/ and mm/ in arch/arm/Makefile would be accepted :) I'd rather not see this turn into a long list of CONFIG_$(ARCH) checks if other architectures enable it in the same place. I also wonder why the three architectures implementing it all call this from wildly different places during init/main.c, namely (very early) setup_arch() on ia64, Likewise arm64. (relatively early) start_kernel on x86 and (relatively late) kernel_init_freeable on arm. As I said - the pure 64-bit archs have less of an issue, since they can have their kernel somewhere that won't clash with the 1:1 mapping of RAM required by UEFI SetVirtualAddressMap. In general, I'd be happy with adding this as late in the startup code as possible, but it may be better to use the same place as x86 in order to avoid surprises with unexpected dependencies. I _really_ don't want to call SetVirtualAddressMap after smp_init. One such dependency that may cause problems is the fact that we (try to) call efi_late_init() before efi_enter_virtual_mode() now. Well, efi_late_init() is an inline {} on everything !x86. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4 4/5] arm: Add [U]EFI runtime services support
On Mon, Jan 13, 2014 at 07:43:09PM +0100, Arnd Bergmann wrote: This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It uses the generic configuration table scanning to populate ACPI and SMBIOS pointers. As far as I'm concerned there are no plans to have ACPI support on ARM32, so I wonder what the code to populate the ACPI tables is about. Can you clarify this? Are you suggesting that I should #ifndef ARM in common code, or that I should neglect to document what the common code will do with data it is given by UEFI? diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 78a79a6a..1ab24cc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1853,6 +1853,20 @@ config EARLY_IOREMAP the same virtual memory range as kmap so all early mappings must be unapped before paging_init() is called. +config EFI + bool UEFI runtime service support + depends on OF !CPU_BIG_ENDIAN What is the dependency on !CPU_BIG_ENDIAN? Mainly on code not being implemented to byte-reverse UCS strings. We try hard to have all kernel code support both big-endian and little-endian, and I'm guessing there is a significant overlap between the people that want UEFI support and those that want big-endian kernels. Not really. There might be some. Also, it is not necessarily the case that those people want to run the big-endian kernel at EL2. If a need is seen, this support can be added at a later date. +struct efi_memory_map memmap; memmap is not a good name for a global identifier, particularly because it's easily confused with the well-known mem_map array. This wants namespace prefix like you other variable, or a static tag, preferably both. It is defined by include/linux/efi.h. +/* + * This function switches the UEFI runtime services to virtual mode. + * This operation must be performed only once in the system's lifetime, + * including any kecec calls. kexec Ok. diff --git a/include/linux/efi.h b/include/linux/efi.h index fa7d950..afaeb85 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -664,7 +664,7 @@ extern int __init efi_setup_pcdp_console(char *); #define EFI_64BIT 5 /* Is the firmware 64-bit? */ #ifdef CONFIG_EFI -# ifdef CONFIG_X86 +# if defined(CONFIG_X86) || defined(CONFIG_ARM) extern int efi_enabled(int facility); # else static inline int efi_enabled(int facility) Maybe better #ifndef CONFIG_IA64? It seems that is the odd one out and all possible future architectures would be like x86 and ARM. This was pointed out by Matt Fleming earlier, so it will change. Mark Salter suggested introducing something like ARCH_USES_EFI_FACILITY would be a bit cleaner. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4 4/5] arm: Add [U]EFI runtime services support
On Tue, Jan 14, 2014 at 07:52:32AM +0100, Arnd Bergmann wrote: It uses the generic configuration table scanning to populate ACPI and SMBIOS pointers. As far as I'm concerned there are no plans to have ACPI support on ARM32, so I wonder what the code to populate the ACPI tables is about. Can you clarify this? Are you suggesting that I should #ifndef ARM in common code, or that I should neglect to document what the common code will do with data it is given by UEFI? It would probably be good to document the fact that it won't work, possibly even having a BUG_ON statement in the code for this case. Why? You'll only touch that pointer if you enable CONFIG_ACPI, and if you do you probably want that address. Sounds a bit hostile to throw a BUG in the face of someone who's (for example) just succeeded to get Linux running on a Windows RT device. diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 78a79a6a..1ab24cc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1853,6 +1853,20 @@ config EARLY_IOREMAP the same virtual memory range as kmap so all early mappings must be unapped before paging_init() is called. +config EFI + bool UEFI runtime service support + depends on OF !CPU_BIG_ENDIAN What is the dependency on !CPU_BIG_ENDIAN? Mainly on code not being implemented to byte-reverse UCS strings. Why would you byte-reverse /strings/? They normally just come in order of the characters, and UTF-16 strings are already defined as being big-endian or marked by the BOM character. Well, then that bit might just work[tm]. Although no other architectures supported by UEFI support big-endian, so to be honest, I don't want to have to be the first one to validate that in order to get the basic support into the kernel. Some of the data structures might need swizzling though... Again - if there is demand, this can be dealt with at a later date. +struct efi_memory_map memmap; memmap is not a good name for a global identifier, particularly because it's easily confused with the well-known mem_map array. This wants namespace prefix like you other variable, or a static tag, preferably both. It is defined by include/linux/efi.h. This seems to be a mistake: there is no user of this variable outside of arch/x86/platform/efi/efi.c and arch/x86/platform/efi/efi_64.c. I think it should just be moved into an x86 specific header file, or preferably be renamed in the process. There is also efi-memmap, which seems to be the same pointer. Humm, seems I unknowingly removed the only remaining x86-external reference to this variable when I made efi_lookup_mapped_address a common function. Yeah, changing this makes sense. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v4 4/5] arm: Add [U]EFI runtime services support
On 14 January 2014 13:26, Arnd Bergmann a...@arndb.de wrote: Are you suggesting that I should #ifndef ARM in common code, or that I should neglect to document what the common code will do with data it is given by UEFI? It would probably be good to document the fact that it won't work, possibly even having a BUG_ON statement in the code for this case. Why? You'll only touch that pointer if you enable CONFIG_ACPI, and if you do you probably want that address. Sounds a bit hostile to throw a BUG in the face of someone who's (for example) just succeeded to get Linux running on a Windows RT device. But we know that it can't work unless a lot of other things get changed in the kernel. We know using ACPI cannot work without updates to the kernel. That doesn't mean we need to throw a BUG just because the firmware tells us a table exists. Although no other architectures supported by UEFI support big-endian, so to be honest, I don't want to have to be the first one to validate that in order to get the basic support into the kernel. I think there was a project to run UEFI on PowerPC on some stage, though I can't find any code now. That does sound familiar, but there is nothing in the specification. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] arm: add early_ioremap support
This patch adds support for early_ioremap, based on the existing mechanism in x86. Up to 7 regions of up to 128KB each can be temporarily mapped in before paging_init, regardless of later highmem status. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig |7 ++ arch/arm/include/asm/fixmap.h | 31 - arch/arm/include/asm/io.h | 13 ++ arch/arm/kernel/setup.c |3 + arch/arm/mm/Makefile |1 + arch/arm/mm/early_ioremap.c | 273 + arch/arm/mm/mmu.c |2 + 7 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mm/early_ioremap.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 49d993c..bf8e55d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1756,6 +1756,13 @@ config UACCESS_WITH_MEMCPY However, if the CPU data cache is using a write-allocate mode, this option is unlikely to provide any performance gain. +config EARLY_IOREMAP + depends on MMU + bool Provide early_ioremap() support for kernel initialization. + help + Provides a mechanism for kernel initialisation code to temporarily + map, in a highmem-agnostic way, memory pages in before paging_init(). + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index bbae919..a2a5f50 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -1,6 +1,8 @@ #ifndef _ASM_FIXMAP_H #define _ASM_FIXMAP_H +#include linux/bug.h + /* * Nothing too fancy for now. * @@ -20,13 +22,38 @@ #define FIX_KMAP_BEGIN 0 #define FIX_KMAP_END (FIXADDR_SIZE PAGE_SHIFT) +/* + * 224 temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + * + * (P)re-using the FIXADDR region, which is used for highmem + * later on, and statically aligned to 1MB. + */ +#define NR_FIX_BTMAPS 32 +#define FIX_BTMAPS_SLOTS 7 +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) +#define FIX_BTMAP_BEGINFIX_KMAP_BEGIN +#define FIX_BTMAP_END (FIX_KMAP_END - 1) + +#define clear_fixmap(idx) \ + __set_fixmap(idx, 0, __pgprot(0)) + #define __fix_to_virt(x) (FIXADDR_START + ((x) PAGE_SHIFT)) #define __virt_to_fix(x) (((x) - FIXADDR_START) PAGE_SHIFT) extern void __this_fixmap_does_not_exist(void); -static inline unsigned long fix_to_virt(const unsigned int idx) +static __always_inline unsigned long fix_to_virt(const unsigned int idx) { + /* +* this branch gets completely eliminated after inlining, +* except when someone tries to use fixaddr indices in an +* illegal way. (such as mixing up address types or using +* out-of-range indices). +* +* If it doesn't get removed, the linker will complain +* loudly with a reasonably clear error message.. +*/ if (idx = FIX_KMAP_END) __this_fixmap_does_not_exist(); return __fix_to_virt(idx); @@ -38,4 +65,4 @@ static inline unsigned int virt_to_fix(const unsigned long vaddr) return __virt_to_fix(vaddr); } -#endif +#endif /* _ASM_FIXMAP_H */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 652b560..c8866e3 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -397,5 +397,18 @@ extern int devmem_is_allowed(unsigned long pfn); extern void register_isa_ports(unsigned int mmio, unsigned int io, unsigned int io_shift); +/* + * early_ioremap() and early_iounmap() are for temporary early boot-time + * mappings, before the real ioremap() is functional. + * A boot-time mapping is currently limited to at most 16 pages. + * + * This is all squashed by paging_init(). + */ +extern void early_ioremap_init(void); +extern void early_ioremap_reset(void); +extern void __iomem *early_ioremap(resource_size_t phys_addr, + unsigned long size); +extern void early_iounmap(void __iomem *addr, unsigned long size); + #endif /* __KERNEL__ */ #endif /* __ASM_ARM_IO_H */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 1522c7a..290c561 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -36,6 +36,7 @@ #include asm/cpu.h #include asm/cputype.h #include asm/elf.h +#include asm/io.h #include asm/procinfo.h #include asm/sections.h #include asm/setup.h @@ -783,6 +784,8 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); + early_ioremap_init(); + sort(meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); sanity_check_meminfo(); arm_memblock_init(meminfo, mdesc); diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 9e51be9..ae2c477 100644
[PATCH 0/2] arm: add early_ioremap() support
x86 and ia64 have the early_ioremap()/early_iounmap() functions, which are useful for supporting things like UEFI, ACPI and SMBIOS, where configuration tables need to be parsed before proper memory management is available, regardless of highmem status. This patchset implements a restricted form of early_ioremap(), available before paging_init() only. Like the x86 code on which it is based, it (p)re-uses the fixmap regions for its virtual mapping range. Up to 7 simultaneous mappings of up to 128KB can be accommodated in the available fixmap space. Leif Lindholm (2): Documentation: arm: early_ioremap arm: add early_ioremap support Documentation/arm/00-INDEX |2 + Documentation/arm/early_ioremap.txt | 12 ++ arch/arm/Kconfig|7 + arch/arm/include/asm/fixmap.h | 31 +++- arch/arm/include/asm/io.h | 13 ++ arch/arm/kernel/setup.c |3 + arch/arm/mm/Makefile|1 + arch/arm/mm/early_ioremap.c | 273 +++ arch/arm/mm/mmu.c |2 + 9 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 Documentation/arm/early_ioremap.txt create mode 100644 arch/arm/mm/early_ioremap.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] Documentation: arm: early_ioremap
This patch provides documentation of the early_ioremap() functionality, including its implementation and usage instructions. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- Documentation/arm/00-INDEX |2 ++ Documentation/arm/early_ioremap.txt | 12 2 files changed, 14 insertions(+) create mode 100644 Documentation/arm/early_ioremap.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 36420e1..4978456 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -24,6 +24,8 @@ SPEAr - ST SPEAr platform Linux Overview VFP/ - Release notes for Linux Kernel Vector Floating Point support code +early_ioremap.txt + - documentation of the early_ioremap() functionality empeg/ - Ltd's Empeg MP3 Car Audio Player mem_alignment diff --git a/Documentation/arm/early_ioremap.txt b/Documentation/arm/early_ioremap.txt new file mode 100644 index 000..178f791 --- /dev/null +++ b/Documentation/arm/early_ioremap.txt @@ -0,0 +1,12 @@ +early_ioremap() and early_iounmap() rovide a mechanism for temporarily mapping +in small blocks of memory, identified by their physical address, into the +fixmap virtual address block before paging_init() has been called and more +flexible mapping functions are available. + +Due to its direct method, it also gets around potential need for special +handling of regions that end up in highmem. + +It supports up to 7 simultaneously mapped regions of up to 128KB each. +All regions are mapped as non-shareable device memory. + +Specify 'early_ioremap_debug' on the kernel commandline for verbose output. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/4] Documentation: arm: [U]EFI runtime services
This patch provides documentation of the [U]EFI runtime services and configuration features. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- Documentation/arm/00-INDEX |3 +++ Documentation/arm/uefi.txt | 39 +++ 2 files changed, 42 insertions(+) create mode 100644 Documentation/arm/uefi.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 4978456..87e01d1 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -36,3 +36,6 @@ nwfpe/ - NWFPE floating point emulator documentation swp_emulation - SWP/SWPB emulation handler/logging description + +uefi.txt + - [U]EFI configuration and runtime services documentation diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt new file mode 100644 index 000..5c48271 --- /dev/null +++ b/Documentation/arm/uefi.txt @@ -0,0 +1,39 @@ +The nomenclature EFI and UEFI are used interchangeably in this document. + +The implementation depends on receiving pointers to the UEFI memory map +and System Table in a Flattened Device Tree - so is only available with +CONFIG_OF. + +It (early) parses the FDT for the following parameters: +- 'efi-system-table': + Physical address of the system table. (required) +- 'efi-runtime-mmap': + Physical address of an EFI memory map, containing at least + the regions to be preserved. (required) +- 'efi-runtime-mmap-size': + Size in bytes of the provided memory map. (required) +- 'efi-mmap-desc-size': + Size of each descriptor in the memory map. (override default) +- 'efi-mmap-desc-ver': + Memory descriptor format version. (override default) + +Since UEFI firmware on ARM systems are required to use a 1:1 memory map +even on LPAE-capable systems, the above fields are 32-bit regardless. + +It also depends on early_ioremap to parse the memory map and preserve +the regions required for runtime services. + +For actually enabling [U]EFI support, enable: +- CONFIG_EFI=y +- CONFIG_EFI_VARS=y or m + +After the kernel has mapped the required regions into its address space, +a SetVirtualAddressMap() call is made into UEFI in order to update +relocations. This call must be performed with all the code in a 1:1 +mapping. This implementation achieves this by temporarily disabling the +MMU for the duration of this call. This can only be done safely: +- before secondary CPUs are brought online. +- after early_initcalls have completed, sinze it uses setup_mm_for_reboot(). + +For verbose debug messages, specify 'uefi_debug' on the kernel command +line. -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/4] arm: Add [U]EFI runtime services support
This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It also locates any presented SMBIOS configuration table and stores it for potential later use by DMI. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig | 15 ++ arch/arm/include/asm/efi.h | 22 +++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 456 arch/arm/kernel/efi_phys.S | 59 ++ arch/arm/kernel/setup.c|5 + 6 files changed, 559 insertions(+) create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bf8e55d..022d2eb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1763,6 +1763,19 @@ config EARLY_IOREMAP Provides a mechanism for kernel initialisation code to temporarily map, in a highmem-agnostic way, memory pages in before paging_init(). +config EFI +bool UEFI runtime service support + depends on OF + select UCS2_STRING + select EARLY_IOREMAP + ---help--- + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should + continue to boot on existing non-UEFI platforms. + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode @@ -2217,6 +2230,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm/Kconfig.debug diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h new file mode 100644 index 000..aead94c --- /dev/null +++ b/arch/arm/include/asm/efi.h @@ -0,0 +1,22 @@ +#ifndef _ASM_ARM_EFI_H +#define _ASM_ARM_EFI_H + +#include asm/mach/map.h + +extern int efi_memblock_arm_reserve_range(void); + +typedef efi_status_t efi_phys_call_t(u32 memory_map_size, +u32 descriptor_size, +u32 descriptor_version, +efi_memory_desc_t *dsc, +efi_set_virtual_address_map_t *f); + +extern efi_status_t efi_phys_call(u32, u32, u32, efi_memory_desc_t *, + efi_set_virtual_address_map_t *); + +#define efi_remap(cookie, size) __arm_ioremap((cookie), (size), MT_MEMORY) +#define efi_ioremap(cookie, size) __arm_ioremap((cookie), (size), MT_DEVICE) +#define efi_unmap(cookie) __arm_iounmap((cookie)) +#define efi_iounmap(cookie) __arm_iounmap((cookie)) + +#endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 5f3338e..12b9c30 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -84,4 +84,6 @@ obj-$(CONFIG_EARLY_PRINTK)+= early_printk.o obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o obj-$(CONFIG_ARM_PSCI) += psci.o +obj-$(CONFIG_EFI) += efi.o efi_phys.o + extra-y := $(head-y) vmlinux.lds diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c new file mode 100644 index 000..43ecf0b --- /dev/null +++ b/arch/arm/kernel/efi.c @@ -0,0 +1,456 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.3.1 + * + * Copyright (C) 2013 Linaro Ltd. + * + */ + +#include linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h +#include asm/efi.h +#include asm/idmap.h +#include asm/tlbflush.h + +struct efi efi; +EXPORT_SYMBOL(efi); +struct efi_memory_map memmap; + +static efi_runtime_services_t *runtime; + +static phys_addr_t efi_system_table; +static phys_addr_t efi_boot_mmap; +static u32 efi_boot_mmap_size; +static u32 efi_mmap_desc_size; +static u32 efi_mmap_desc_ver; + +/* Default memory map descriptor information */ +#define DESC_SIZE 48 +#define DESC_VER 1 + +/* If you're planning to wire up a debugger and debug the UEFI side ... */ +#undef KEEP_ALL_REGIONS +#define KEEP_BOOT_SERVICES_REGIONS + +static int __initdata uefi_debug; +static int __init uefi_debug_setup(char *str) +{ + uefi_debug = 1; + + return 0; +} +early_param(uefi_debug, uefi_debug_setup); + +static int __init fdt_find_efi_params(unsigned long node, const char *uname, + int depth, void *data) +{ + unsigned long len; + __be32 *prop; + + if (depth != 1 || + (strcmp(uname, chosen) != 0 strcmp(uname, chosen@0) != 0)) + return 0; + + pr_info(Getting EFI parameters from FDT.\n); + + prop = of_get_flat_dt_prop(node, efi
[PATCH 4/4] init: efi: arm: enable (U)EFI runtime services on arm
Since the efi_set_virtual_address_map call has strict init ordering requirements, add an explicit hook in the required place. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- init/main.c |6 ++ 1 file changed, 6 insertions(+) diff --git a/init/main.c b/init/main.c index 9484f4b..c61706e 100644 --- a/init/main.c +++ b/init/main.c @@ -872,6 +872,12 @@ static noinline void __init kernel_init_freeable(void) smp_prepare_cpus(setup_max_cpus); do_pre_smp_initcalls(); + +#ifdef CONFIG_ARM + if (efi_enabled(EFI_RUNTIME_SERVICES)) + efi_enter_virtual_mode(); +#endif + lockup_detector_init(); smp_init(); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/4] arm: [U]EFI runtime services support
In systems based on [U]EFI-conformant firmware, runtime services provide a standardised way for the kernel to update firmware environment variables. This is used for example by efibootmgr to update which image should be loaded on next boot. This patchset implements basic support for UEFI runtime services on ARM platforms, as well as the basic underlying EFI support. It also defines a mechanism by which the required information is passed from the bootloader to the kernel via FDT entries. This patchset depends on the previously submitted early_ioremap() patchset. Leif Lindholm (4): Documentation: arm: [U]EFI runtime services x86: efi: break efi_lookup_mapped_addr out to generic code arm: Add [U]EFI runtime services support init: efi: arm: enable (U)EFI runtime services on arm Documentation/arm/00-INDEX|3 + Documentation/arm/uefi.txt| 39 arch/arm/Kconfig | 15 ++ arch/arm/include/asm/efi.h| 22 ++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 456 + arch/arm/kernel/efi_phys.S| 59 + arch/arm/kernel/setup.c |5 + arch/x86/platform/efi/efi.c | 28 --- drivers/firmware/efi/Makefile |2 +- drivers/firmware/efi/efi-helper.c | 33 +++ init/main.c |6 + 12 files changed, 641 insertions(+), 29 deletions(-) create mode 100644 Documentation/arm/uefi.txt create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S create mode 100644 drivers/firmware/efi/efi-helper.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/4] x86: efi: break efi_lookup_mapped_addr out to generic code
efi_lookup_mapped_addr is a handy helper function for translating a physical address to the corresponding virtual one by scanning through memmap.map. This patch breaks it out into a new file for use elsewhere. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 28 drivers/firmware/efi/Makefile |2 +- drivers/firmware/efi/efi-helper.c | 33 + 3 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 drivers/firmware/efi/efi-helper.c diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 5ae2eb0..d1a1b6b 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -814,34 +814,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md-num_pages EFI_PAGE_SHIFT; - u64 end = md-phys_addr + size; - if (!(md-attribute EFI_MEMORY_RUNTIME) - md-type != EFI_BOOT_SERVICES_CODE - md-type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md-virt_addr) - continue; - if (phys_addr = md-phys_addr phys_addr end) { - phys_addr += md-virt_addr - md-phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - void efi_memory_uc(u64 addr, unsigned long size) { unsigned long page_shift = 1UL EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 99245ab..629a513 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile @@ -1,6 +1,6 @@ # # Makefile for linux kernel # -obj-y += efi.o vars.o +obj-y += efi.o vars.o efi-helper.o obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o diff --git a/drivers/firmware/efi/efi-helper.c b/drivers/firmware/efi/efi-helper.c new file mode 100644 index 000..c5c2c72 --- /dev/null +++ b/drivers/firmware/efi/efi-helper.c @@ -0,0 +1,33 @@ +/* + * Common [U]EFI support helper functions across architectures. + */ + +#include linux/efi.h + +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + void *p; + if (WARN_ON(!memmap.map)) + return NULL; + for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { + efi_memory_desc_t *md = p; + u64 size = md-num_pages EFI_PAGE_SHIFT; + u64 end = md-phys_addr + size; + if (!(md-attribute EFI_MEMORY_RUNTIME) + md-type != EFI_BOOT_SERVICES_CODE + md-type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md-virt_addr) + continue; + if (phys_addr = md-phys_addr phys_addr end) { + phys_addr += md-virt_addr - md-phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/4] Documentation: arm: [U]EFI runtime services
On Wed, Jun 26, 2013 at 02:20:23PM +0100, Grant Likely wrote: On Wed, Jun 26, 2013 at 12:42 AM, Stephen Warren swar...@wwwdotorg.org wrote: the properties) should be part of a file in Documentation/devicetree/bindings/ (arm/uefi.txt?). What node are these properties expected to be contained within? Shouldn't that node be required to contain a compatible value, which would define the schema for the other properties? Typically, a compatible property isn't only used for nodes that represent a device or a so-called 'virtual' device (ie. such as to describe how all the sound complex is wired together) since that should be the clue to an OS that a device driver will bind against the node. I think these properties can be dropped into /chosen without defining a new compatible value. That would be my preference. But yes, that should be documented, and will be in the next version. +Since UEFI firmware on ARM systems are required to use a 1:1 memory map +even on LPAE-capable systems, the above fields are 32-bit regardless. What about ARMv8? Is the intention to have a separate definition for the UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a future version of UEFI allows LPAE usage? It is unlikely that will happen on v7 since newer versions of UEFI are expected to remain backwards compatible with the current spec. I'm going to go out on a limb here and claim that it wouldn't be possible to do that compatibly. The current spec doesn't ban LPAE (or use of long descriptors). But it does specify that all RAM known to UEFI must use a 1:1 mapping. +After the kernel has mapped the required regions into its address space, +a SetVirtualAddressMap() call is made into UEFI in order to update +relocations. This call must be performed with all the code in a 1:1 Presumably all the code also includes all .data and .bss, or whatever the UEFI-equivalent may be? I'm not familiar with UEFI at all; does the EFI memory map mentioned above describe all the memory regions that must be mapped to use UEFI? yes.Actually, there is an API for retrieving the memory map from UEFI at runtime, but it is difficult to call from within the kernel. Actually, my preference would be to not require GRUB or the Linux Loader to add the above properties at all and instead have the kernel proper retrieve the memory map directly. That would reduce the dependency on GRUB/LinuxLoader doing things correctly, but Leif knows better how feasible that would be. It's completely feasible, but we'd need to use a different method to do the boot services call with a 1:1 mapping (idmap support is not available until much later in the boot process). The System Table pointer still needs to be passed across though. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/4] Documentation: arm: [U]EFI runtime services
On Wed, Jun 26, 2013 at 02:13:39PM +0100, Grant Likely wrote: diff --git a/Documentation/arm/uefi.txt b/Documentation/arm/uefi.txt +It (early) parses the FDT for the following parameters: Need to state which node these properties can be found in. I recommend /chosen Will do. I would also prefix all of the following properties with linux, since they are very much about what the Linux kernel needs for booting. EFI stub will be creating these properties specifically for Linux, and the LinuxLoader should do the same (until we eventually kill it). And that. +- 'efi-system-table': + Physical address of the system table. (required) Need to mention the size of this address. Is it 64 bit or 32 bit? I would follow the lead of 'linux,initrd-start' here and make the size of property the size of the address. ie. If it is 8 bytes long, then it is a 64 bit address. Currently, it's a 4-byte address. Although technically possible to be 32-bit in an LPAE system, the 1:1 mappign requirement of the UEFI spec forces it to reside in the lower 4GB on a 32-bit system. +- 'efi-runtime-mmap': + Physical address of an EFI memory map, containing at least + the regions to be preserved. (required) +- 'efi-runtime-mmap-size': + Size in bytes of the provided memory map. (required) I would collapse the above two properties into a single property that actually contains the memory map instead of pointing to it. You will also need to specify the exact format of the data in this property. Ok, that makes sense. Hmm. The data is an array of struct EFI_MEMORY_DESCRIPTOR entries, known in Linux as efi_memory_desc_t. Is that a good enough description? +- 'efi-mmap-desc-size': + Size of each descriptor in the memory map. (override default) +- 'efi-mmap-desc-ver': + Memory descriptor format version. (override default) I don't understand how these properties will actually work. What changes in the parsing if these properties are set? I guess the intended use is that these options would permit you to append new fields to the struct and have old code correctly parse the array anyway. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/4] x86: efi: break efi_lookup_mapped_addr out to generic code
On Wed, Jun 26, 2013 at 02:32:17PM +0100, Matt Fleming wrote: On Tue, 25 Jun, at 07:11:01PM, Leif Lindholm wrote: efi_lookup_mapped_addr is a handy helper function for translating a physical address to the corresponding virtual one by scanning through memmap.map. This patch breaks it out into a new file for use elsewhere. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 28 drivers/firmware/efi/Makefile |2 +- drivers/firmware/efi/efi-helper.c | 33 + 3 files changed, 34 insertions(+), 29 deletions(-) create mode 100644 drivers/firmware/efi/efi-helper.c I'm not sure this function needs its own file. drivers/firmware/efi/efi.c is a suitable place for this. Sure. Would you be happy for me to start moving the other things mentioned (config table parsing, common debug printout, global structs) in there too? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 3/4] arm: Add [U]EFI runtime services support
On Wed, Jun 26, 2013 at 02:46:09PM +0100, Grant Likely wrote: This patch implements basic support for UEFI runtime services in the ARM architecture - a requirement for using efibootmgr to read and update the system boot configuration. It also locates any presented SMBIOS configuration table and stores it for potential later use by DMI. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig | 15 ++ arch/arm/include/asm/efi.h | 22 +++ arch/arm/kernel/Makefile |2 + arch/arm/kernel/efi.c | 456 arch/arm/kernel/efi_phys.S | 59 ++ arch/arm/kernel/setup.c|5 + 6 files changed, 559 insertions(+) create mode 100644 arch/arm/include/asm/efi.h create mode 100644 arch/arm/kernel/efi.c create mode 100644 arch/arm/kernel/efi_phys.S diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bf8e55d..022d2eb 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1763,6 +1763,19 @@ config EARLY_IOREMAP Provides a mechanism for kernel initialisation code to temporarily map, in a highmem-agnostic way, memory pages in before paging_init(). +config EFI +bool UEFI runtime service support + depends on OF + select UCS2_STRING + select EARLY_IOREMAP + ---help--- + This enables the kernel to use UEFI runtime services that are + available (such as the UEFI variable services). + + This option is only useful on systems that have UEFI firmware. + However, even with this option, the resultant kernel should Be confident! s/should/will/ :-) Ok. + continue to boot on existing non-UEFI platforms. s/existing// Ok. + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode @@ -2217,6 +2230,8 @@ source net/Kconfig source drivers/Kconfig +source drivers/firmware/Kconfig + source fs/Kconfig source arch/arm/Kconfig.debug diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h new file mode 100644 index 000..aead94c --- /dev/null +++ b/arch/arm/include/asm/efi.h @@ -0,0 +1,22 @@ +#ifndef _ASM_ARM_EFI_H +#define _ASM_ARM_EFI_H + +#include asm/mach/map.h + +extern int efi_memblock_arm_reserve_range(void); + +typedef efi_status_t efi_phys_call_t(u32 memory_map_size, +u32 descriptor_size, +u32 descriptor_version, +efi_memory_desc_t *dsc, +efi_set_virtual_address_map_t *f); + +extern efi_status_t efi_phys_call(u32, u32, u32, efi_memory_desc_t *, + efi_set_virtual_address_map_t *); + +#define efi_remap(cookie, size) __arm_ioremap((cookie), (size), MT_MEMORY) +#define efi_ioremap(cookie, size) __arm_ioremap((cookie), (size), MT_DEVICE) +#define efi_unmap(cookie) __arm_iounmap((cookie)) +#define efi_iounmap(cookie) __arm_iounmap((cookie)) + +#endif /* _ASM_ARM_EFI_H */ diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 5f3338e..12b9c30 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -84,4 +84,6 @@ obj-$(CONFIG_EARLY_PRINTK)+= early_printk.o obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o obj-$(CONFIG_ARM_PSCI) += psci.o +obj-$(CONFIG_EFI) += efi.o efi_phys.o + extra-y := $(head-y) vmlinux.lds diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c new file mode 100644 index 000..43ecf0b --- /dev/null +++ b/arch/arm/kernel/efi.c @@ -0,0 +1,456 @@ +/* + * Extensible Firmware Interface + * + * Based on Extensible Firmware Interface Specification version 2.3.1 + * + * Copyright (C) 2013 Linaro Ltd. Was any of the above code extracted from the x86/ia64 efi code base? If so then make sure the copyright header and license text gets retained. Well, some of efi_config_init() was, but it looks like I will be movng it out now. + * + */ + +#include linux/efi.h +#include linux/export.h +#include linux/memblock.h +#include linux/of.h +#include linux/of_fdt.h +#include linux/sched.h +#include linux/slab.h + +#include asm/cacheflush.h +#include asm/efi.h +#include asm/idmap.h +#include asm/tlbflush.h + +struct efi efi; +EXPORT_SYMBOL(efi); +struct efi_memory_map memmap; The above symbols should be pulled out of x86 and ia64 and made part of drivers/efi/efi.c. Although in my quick look I don't see memmap defined for ia64. You'll need to make sure that it actually exists before moving it. Happy to do that. Can be ifdef'd if need be. That will also affect your earlier patch which moves the memmap lookup function. I suspect that function won't build on ia64. Argh, indeed. I had that ifdef'd ARM
Re: [PATCH 0/2] arm: add early_ioremap() support
On Wed, Jun 26, 2013 at 08:52:09PM +0200, Arnd Bergmann wrote: I made a similar suggestion to extending the use of fixmap recently, see Re: SCU registers mapping for CA9/CA5 cores. Russell pointed out that fixmap is intentionally limited to just kmap_atomic uses at the moment and changing that would potentially have a significant impact when we run out of pages in the fixmap area. Is this an issue here, since (unlike x86) this early_ioremap only works before paging_init()? The method we use on ARM normally is the iotable_init() function, which requires hardcoding a virtual address at the moment. It might be nicer to change that code than to put early_ioremap into fixmap. Note that early_ioremap in fixmap is a bit of a kludge on x86 as well because it is very much /not/ a fixed mapping like the rest of fixmap, they just use it because it's convenient. Yes, but they also only use it (at least the bits where I looked) for temporary mappings very early in the boot process. That is certainly how I use it. So at least my intention was to use it before kmap is even available. Extending the iotable mechanism on ARM would be the convenient solution for us I think. Could that easily be extended to give similar semantics sufficiently that we can progress with merging more of the UEFI and ACPI support together as common code with x86/ia64? / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/4] Documentation: arm: [U]EFI runtime services
On Wed, Jun 26, 2013 at 12:32:30PM -0600, Stephen Warren wrote: What about ARMv8? Is the intention to have a separate definition for the UEFI bindings on ARMv8, so that compatibility isn't an issue? What if a future version of UEFI allows LPAE usage? It is unlikely that will happen on v7 since newer versions of UEFI are expected to remain backwards compatible with the current spec. The expectation of backwards-compatibility sounds nice, but it seems a little dangerous to outright rely on it. Even if not a regular compatible property, can we define a property that indicates the UEFI revision or revision of this DT binding, so that if we ever have to change it, there is some way of explicitly indicating which exact schema the DT corresponds to, rather than having to reverse-engineer it from the set of properties that just happen to be present in DT? This is rather like the firmware node discussion that happened recently, where we were expecting to represent a firmware (secure mode) interface by a DT node, which would have a compatible value, which in turn would convey information about which OS the secure firmware was running, and well as any potential SoC-/OEM-/board-specific interface provided by it. And who knows, what if UEFI gets replaced someday; presumably we'd want some way of explicitly stating running under UEFI vs. running under something else? To me, these concerns are all covered by the existence of the efi-system-table node, and the version number that you can extract from the table (mandatory in any UEFI implementation) located at that address. There is no reverse-engineering involved. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/2] arm: add early_ioremap() support
On Wed, Jun 26, 2013 at 11:23:50PM +0200, Arnd Bergmann wrote: Is this an issue here, since (unlike x86) this early_ioremap only works before paging_init()? The main problem is that the total fixmap size is only around 900kb, and we want to reserve at least 64kb per cpu for kmap_atomic. If you want to fit multiple 128kb mappings in there, you run out of space really fast. Sorry, I still don't get it. Are you saying that kmap_atomic is available before kmap_init() (in paging_init())? If not, all of my mappings are discarded (well, abandoned to be more correct), so I don't see how it affects kmap. Extending the iotable mechanism on ARM would be the convenient solution for us I think. Could that easily be extended to give similar semantics sufficiently that we can progress with merging more of the UEFI and ACPI support together as common code with x86/ia64? I don't know what the requirements are, but the idea with iotable is that the mappings stay around at run time, while it seems you want to discard them at some point. Indeed - almost immediately. x86 early_ioremap can coexist with kmap; the intent of my implementation is to use the kmap region only before kmap is available. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/2] arm: add early_ioremap() support
On Thu, Jun 27, 2013 at 12:13:55AM +0200, Arnd Bergmann wrote: Sorry, I still don't get it. Are you saying that kmap_atomic is available before kmap_init() (in paging_init())? If not, all of my mappings are discarded (well, abandoned to be more correct), so I don't see how it affects kmap. Sorry, I was under the assumption that the mappings are meant to stay around. Ok, just so I'm not completely lost :) No, the purpose is just like for x86 - do early parsing of things like the UEFI system and configuration tables, DMI and ACPI, in order to populate global structs and stuff. Indeed - almost immediately. x86 early_ioremap can coexist with kmap; the intent of my implementation is to use the kmap region only before kmap is available. So if you never plan to use fixmap and early_ioremap at the same time, why even bother using the fixmap code? Wouldn't it be easier to just use the same memory area and ensure we never use fixmap before we're done with early_ioremap? Well, I did have a crazy idea that much/most of the early_ioremap code could be made generic and shared between x86 and arm (and any other 32-bit architecture). Using the fixmap macros would make that possible with a minimum of ifdefs. If we ever wanted early_ioremap() to work like on x86, beyond kmap_init() (but not beyond the booting system state), using the same macros would help there too. I had no need for that for my EFI patches. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 2/5] efi: provide a generic efi_config_init()
On Mon, Sep 02, 2013 at 10:29:02AM +0100, Matt Fleming wrote: This patch actually breaks git bisection, Urgh, sorry about that. /home/build/git/efi/arch/x86/platform/efi/efi.c:581:19: error: conflicting types for ‘efi_config_init’ In file included from /home/build/git/efi/arch/x86/platform/efi/efi.c:33:0: /home/build/git/efi/include/linux/efi.h:596:12: note: previous declaration of ‘efi_config_init’ was here I've merged patches 2,3 and 4 into the following single patch so that the ability to bisect isn't lost. Does it look OK? It boots fine on my test machines. Looks fine to me, and works on the ARM port. I'm about to send out an updated patch set, including this squash. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 3/3] efi: x86: make efi_lookup_mapped_addr() a common function
efi_lookup_mapped_addr() is a handy utility for other platforms than x86. Move it from arch/x86 to drivers/firmware. Add memmap pointer to global efi structure, and initialise it on x86. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/x86/platform/efi/efi.c | 30 ++ drivers/firmware/efi/efi.c | 32 include/linux/efi.h |1 + 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index ed2be58..fbc1d70 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -393,6 +393,8 @@ int __init efi_memblock_x86_reserve_range(void) memblock_reserve(pmap, memmap.nr_map * memmap.desc_size); + efi.memmap = memmap; + return 0; } @@ -736,34 +738,6 @@ static void __init runtime_code_page_mkexec(void) } } -/* - * We can't ioremap data in EFI boot services RAM, because we've already mapped - * it as RAM. So, look it up in the existing EFI memory map instead. Only - * callable after efi_enter_virtual_mode and before efi_free_boot_services. - */ -void __iomem *efi_lookup_mapped_addr(u64 phys_addr) -{ - void *p; - if (WARN_ON(!memmap.map)) - return NULL; - for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { - efi_memory_desc_t *md = p; - u64 size = md-num_pages EFI_PAGE_SHIFT; - u64 end = md-phys_addr + size; - if (!(md-attribute EFI_MEMORY_RUNTIME) - md-type != EFI_BOOT_SERVICES_CODE - md-type != EFI_BOOT_SERVICES_DATA) - continue; - if (!md-virt_addr) - continue; - if (phys_addr = md-phys_addr phys_addr end) { - phys_addr += md-virt_addr - md-phys_addr; - return (__force void __iomem *)(unsigned long)phys_addr; - } - } - return NULL; -} - void efi_memory_uc(u64 addr, unsigned long size) { unsigned long page_shift = 1UL EFI_PAGE_SHIFT; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index e1010d4..2e2fbde 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -150,6 +150,38 @@ err_put: subsys_initcall(efisubsys_init); +/* + * We can't ioremap data in EFI boot services RAM, because we've already mapped + * it as RAM. So, look it up in the existing EFI memory map instead. Only + * callable after efi_enter_virtual_mode and before efi_free_boot_services. + */ +void __iomem *efi_lookup_mapped_addr(u64 phys_addr) +{ + struct efi_memory_map *map; + void *p; + map = efi.memmap; + if (!map) + return NULL; + if (WARN_ON(!map-map)) + return NULL; + for (p = map-map; p map-map_end; p += map-desc_size) { + efi_memory_desc_t *md = p; + u64 size = md-num_pages EFI_PAGE_SHIFT; + u64 end = md-phys_addr + size; + if (!(md-attribute EFI_MEMORY_RUNTIME) + md-type != EFI_BOOT_SERVICES_CODE + md-type != EFI_BOOT_SERVICES_DATA) + continue; + if (!md-virt_addr) + continue; + if (phys_addr = md-phys_addr phys_addr end) { + phys_addr += md-virt_addr - md-phys_addr; + return (__force void __iomem *)(unsigned long)phys_addr; + } + } + return NULL; +} + static __initdata efi_config_table_type_t common_tables[] = { {ACPI_20_TABLE_GUID, ACPI 2.0, efi.acpi20}, {ACPI_TABLE_GUID, ACPI, efi.acpi}, diff --git a/include/linux/efi.h b/include/linux/efi.h index 09d9e42..c084b6d 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -558,6 +558,7 @@ extern struct efi { efi_get_next_high_mono_count_t *get_next_high_mono_count; efi_reset_system_t *reset_system; efi_set_virtual_address_map_t *set_virtual_address_map; + struct efi_memory_map *memmap; } efi; static inline int -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 0/3] Make commonly useful UEFI functions common
This set breaks out some common code from x86/ia64 EFI support code and puts it into drivers/firmware/efi. First it takes the definition of the global efi data structure and moves it into global efi.c. Then it implements a common version of efi_config_init(). Secondly it breaks the efi_lookup_mapped_addr() function out of x86 and places it in global efi.c, for shared use with future ARM patches. IA64 code compile tested only. Leif Lindholm (3): ia64: add early_memremap() alias for early_ioremap() efi: x86: ia64: provide a generic efi_config_init() efi: x86: make efi_lookup_mapped_addr() a common function arch/ia64/include/asm/io.h |1 + arch/ia64/kernel/efi.c | 54 - arch/x86/platform/efi/efi.c | 126 -- drivers/firmware/efi/efi.c | 140 +++ include/linux/efi.h |8 +++ 5 files changed, 170 insertions(+), 159 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v4 2/3] efi: x86: ia64: provide a generic efi_config_init()
Common to (U)EFI support on all platforms is the global efi data structure, and the code that parses the System Table to locate addresses to populate that structure with. This patch adds both of these to the global EFI driver code and removes the local definition of the global efi data structure from the x86 and ia64 code. Squashed into one big patch to avoid breaking bisection. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Tony Luck tony.l...@intel.com Signed-off-by: Matt Fleming matt.flem...@intel.com --- arch/ia64/kernel/efi.c | 54 +- arch/x86/platform/efi/efi.c | 96 -- drivers/firmware/efi/efi.c | 108 +++ include/linux/efi.h |7 +++ 4 files changed, 134 insertions(+), 131 deletions(-) diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 51bce59..da5b462 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -44,10 +44,15 @@ #define EFI_DEBUG 0 +static __initdata unsigned long palo_phys; + +static __initdata efi_config_table_type_t arch_tables[] = { + {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, PALO, palo_phys}, + {NULL_GUID, NULL, 0}, +}; + extern efi_status_t efi_call_phys (void *, ...); -struct efi efi; -EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; static u64 mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; @@ -423,9 +428,9 @@ static u8 __init palo_checksum(u8 *buffer, u32 length) * Parse and handle PALO table which is published at: * http://www.dig64.org/home/DIG64_PALO_R1_0.pdf */ -static void __init handle_palo(unsigned long palo_phys) +static void __init handle_palo(unsigned long phys_addr) { - struct palo_table *palo = __va(palo_phys); + struct palo_table *palo = __va(phys_addr); u8 checksum; if (strncmp(palo-signature, PALO_SIG, sizeof(PALO_SIG) - 1)) { @@ -467,12 +472,10 @@ void __init efi_init (void) { void *efi_map_start, *efi_map_end; - efi_config_table_t *config_tables; efi_char16_t *c16; u64 efi_desc_size; char *cp, vendor[100] = unknown; int i; - unsigned long palo_phys; /* * It's too early to be able to use the standard kernel command line @@ -514,8 +517,6 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x); - config_tables = __va(efi.systab-tables); - /* Show what we know for posterity */ c16 = __va(efi.systab-fw_vendor); if (c16) { @@ -528,43 +529,10 @@ efi_init (void) efi.systab-hdr.revision 16, efi.systab-hdr.revision 0x, vendor); - efi.mps= EFI_INVALID_TABLE_ADDR; - efi.acpi = EFI_INVALID_TABLE_ADDR; - efi.acpi20 = EFI_INVALID_TABLE_ADDR; - efi.smbios = EFI_INVALID_TABLE_ADDR; - efi.sal_systab = EFI_INVALID_TABLE_ADDR; - efi.boot_info = EFI_INVALID_TABLE_ADDR; - efi.hcdp = EFI_INVALID_TABLE_ADDR; - efi.uga= EFI_INVALID_TABLE_ADDR; - palo_phys = EFI_INVALID_TABLE_ADDR; - for (i = 0; i (int) efi.systab-nr_tables; i++) { - if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { - efi.mps = config_tables[i].table; - printk( MPS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { - efi.acpi20 = config_tables[i].table; - printk( ACPI 2.0=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { - efi.acpi = config_tables[i].table; - printk( ACPI=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { - efi.smbios = config_tables[i].table; - printk( SMBIOS=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { - efi.sal_systab = config_tables[i].table; - printk( SALsystab=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { - efi.hcdp = config_tables[i].table; - printk( HCDP=0x%lx, config_tables[i].table); - } else if (efi_guidcmp(config_tables[i].guid, -PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID) == 0) { - palo_phys = config_tables[i].table; - printk( PALO=0x%lx, config_tables[i].table); - } - } - printk(\n); + if (efi_config_init(arch_tables) != 0) + return
[PATCH v4 1/3] ia64: add early_memremap() alias for early_ioremap()
early_ioremap() on IA64 chooses its mapping type based on the EFI memory map. This patch adds an alias early_memremap() to be used where the targeted location is memory rather than an i/o device. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Tony Luck tony.l...@intel.com --- arch/ia64/include/asm/io.h |1 + 1 file changed, 1 insertion(+) diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h index 74a7cc3..0d2bcb3 100644 --- a/arch/ia64/include/asm/io.h +++ b/arch/ia64/include/asm/io.h @@ -424,6 +424,7 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size); extern void __iomem * ioremap_nocache (unsigned long offset, unsigned long size); extern void iounmap (volatile void __iomem *addr); extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size); +#define early_memremap(phys_addr, size)early_ioremap(phys_addr, size) extern void early_iounmap (volatile void __iomem *addr, unsigned long size); static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size) { -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 1/2] Documentation: arm: early_ioremap/early_memremap
This patch provides documentation of the early_ioremap() and early_memremap() functionality,including its implementation and usage instructions. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Acked-by: Rob Landley r...@landley.net --- Documentation/arm/00-INDEX |2 ++ Documentation/arm/early_ioremap.txt | 23 +++ 2 files changed, 25 insertions(+) create mode 100644 Documentation/arm/early_ioremap.txt diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 36420e1..4978456 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -24,6 +24,8 @@ SPEAr - ST SPEAr platform Linux Overview VFP/ - Release notes for Linux Kernel Vector Floating Point support code +early_ioremap.txt + - documentation of the early_ioremap() functionality empeg/ - Ltd's Empeg MP3 Car Audio Player mem_alignment diff --git a/Documentation/arm/early_ioremap.txt b/Documentation/arm/early_ioremap.txt new file mode 100644 index 000..e1c0b16 --- /dev/null +++ b/Documentation/arm/early_ioremap.txt @@ -0,0 +1,23 @@ +early_ioremap()/early_memremap() and early_iounmap() provide a mechanism for +temporarily mapping in small blocks of memory, identified by their physical +address, into the fixmap virtual address block before paging_init() has run +and more flexible mapping functions are available. + +Due to its direct method, it also gets around potential need for special +handling of regions that end up in highmem. + +It supports up to 7 simultaneously mapped regions of up to 128KB each. +All mappings created by early_ioremap() are non-shareable device memory. +All mappings created by early_memremap() are uncached normal memory. + +Any residual mappings will be overridden by subsequent kmap() calls (but do +use early_iounmap()). + +Specify 'early_ioremap_debug' on the kernel commandline for verbose output. + +SYNOPSIS + #include asm/io.h + + void *early_ioremap(resource_size_t phys_addr, unsigned long size); + void *early_memremap(resource_size_t phys_addr, unsigned long size); + void early_iounmap(void *addr, unsigned long size); -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 0/2] Add early_ioremap()/early_memremap() support to arm
x86 and ia64 have the early_ioremap()/early_memremap() functions, which are useful for supporting things like UEFI, ACPI and SMBIOS, where configuration tables need to be parsed before proper memory management is available, regardless of highmem status. This patchset implements a restricted form of early_ioremap() and early_memremap(), available before paging_init() only. Like the x86 code on which it is based, it (p)re-uses the fixmap regions for its virtual mapping range. Up to 7 simultaneous mappings of up to 128KB can be accommodated in the available fixmap space. New for this version is the addition of the early_memremap() call, which maps a region in with uncached normal memory type. Leif Lindholm (2): Documentation: arm: early_ioremap/early_memremap arm: add early_ioremap support Documentation/arm/00-INDEX |2 + Documentation/arm/early_ioremap.txt | 23 +++ arch/arm/Kconfig|7 + arch/arm/include/asm/fixmap.h | 31 +++- arch/arm/include/asm/io.h | 17 +++ arch/arm/kernel/setup.c |5 + arch/arm/mm/Makefile|1 + arch/arm/mm/early_ioremap.c | 271 +++ arch/arm/mm/mmu.c |4 + 9 files changed, 359 insertions(+), 2 deletions(-) create mode 100644 Documentation/arm/early_ioremap.txt create mode 100644 arch/arm/mm/early_ioremap.c -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/2] arm: add early_ioremap support
This patch adds support for early_ioremap and early_memremap, based on the existing mechanism in x86. Up to 7 regions of up to 128KB each can be temporarily mapped in before paging_init, regardless of later highmem status. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org --- arch/arm/Kconfig |7 ++ arch/arm/include/asm/fixmap.h | 31 - arch/arm/include/asm/io.h | 17 +++ arch/arm/kernel/setup.c |5 + arch/arm/mm/Makefile |1 + arch/arm/mm/early_ioremap.c | 271 + arch/arm/mm/mmu.c |4 + 7 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mm/early_ioremap.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 43594d5..53a82da 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1805,6 +1805,13 @@ config UACCESS_WITH_MEMCPY However, if the CPU data cache is using a write-allocate mode, this option is unlikely to provide any performance gain. +config EARLY_IOREMAP + depends on MMU + bool Provide early_ioremap() support for kernel initialization. + help + Provides a mechanism for kernel initialisation code to temporarily + map, in a highmem-agnostic way, memory pages in before paging_init(). + config SECCOMP bool prompt Enable seccomp to safely compute untrusted bytecode diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h index bbae919..a2a5f50 100644 --- a/arch/arm/include/asm/fixmap.h +++ b/arch/arm/include/asm/fixmap.h @@ -1,6 +1,8 @@ #ifndef _ASM_FIXMAP_H #define _ASM_FIXMAP_H +#include linux/bug.h + /* * Nothing too fancy for now. * @@ -20,13 +22,38 @@ #define FIX_KMAP_BEGIN 0 #define FIX_KMAP_END (FIXADDR_SIZE PAGE_SHIFT) +/* + * 224 temporary boot-time mappings, used by early_ioremap(), + * before ioremap() is functional. + * + * (P)re-using the FIXADDR region, which is used for highmem + * later on, and statically aligned to 1MB. + */ +#define NR_FIX_BTMAPS 32 +#define FIX_BTMAPS_SLOTS 7 +#define TOTAL_FIX_BTMAPS (NR_FIX_BTMAPS * FIX_BTMAPS_SLOTS) +#define FIX_BTMAP_BEGINFIX_KMAP_BEGIN +#define FIX_BTMAP_END (FIX_KMAP_END - 1) + +#define clear_fixmap(idx) \ + __set_fixmap(idx, 0, __pgprot(0)) + #define __fix_to_virt(x) (FIXADDR_START + ((x) PAGE_SHIFT)) #define __virt_to_fix(x) (((x) - FIXADDR_START) PAGE_SHIFT) extern void __this_fixmap_does_not_exist(void); -static inline unsigned long fix_to_virt(const unsigned int idx) +static __always_inline unsigned long fix_to_virt(const unsigned int idx) { + /* +* this branch gets completely eliminated after inlining, +* except when someone tries to use fixaddr indices in an +* illegal way. (such as mixing up address types or using +* out-of-range indices). +* +* If it doesn't get removed, the linker will complain +* loudly with a reasonably clear error message.. +*/ if (idx = FIX_KMAP_END) __this_fixmap_does_not_exist(); return __fix_to_virt(idx); @@ -38,4 +65,4 @@ static inline unsigned int virt_to_fix(const unsigned long vaddr) return __virt_to_fix(vaddr); } -#endif +#endif /* _ASM_FIXMAP_H */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index d070741..35499d9 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -26,6 +26,7 @@ #include linux/types.h #include asm/byteorder.h #include asm/memory.h +#include asm/pgtable.h #include asm-generic/pci_iomap.h /* @@ -397,5 +398,21 @@ extern int devmem_is_allowed(unsigned long pfn); extern void register_isa_ports(unsigned int mmio, unsigned int io, unsigned int io_shift); +/* + * early_ioremap() and early_iounmap() are for temporary early boot-time + * mappings, before the real ioremap() is functional. + * A boot-time mapping is currently limited to at most 16 pages. + * + * This is all squashed by paging_init(). + */ +extern void early_ioremap_init(void); +extern void early_ioremap_reset(void); +extern void __iomem *early_remap(resource_size_t phys_addr, +unsigned long size, u32 prot); +#define early_ioremap(x, y) early_remap(x, y, L_PTE_MT_DEV_NONSHARED) +#define early_memremap(x, y) early_remap(x, y, L_PTE_MT_UNCACHED) + +extern void early_iounmap(void __iomem *addr, unsigned long size); + #endif /* __KERNEL__ */ #endif /* __ASM_ARM_IO_H */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index afc2489..ce913ea 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -36,6 +36,7 @@ #include asm/cpu.h #include asm/cputype.h #include asm/elf.h +#include asm/io.h #include asm/procinfo.h #include asm/psci.h #include asm/sections.h @@ -877,6 +878,10 @@ void __init setup_arch(char
Re: [PATCH 02/11] efi: Remove EFI_PAGE_SHIFT and EFI_PAGE_SIZE
On Fri, Sep 20, 2013 at 11:42:49AM +0100, Matt Fleming wrote: On Thu, 19 Sep, at 04:54:45PM, Borislav Petkov wrote: From: Borislav Petkov b...@suse.de ... and use the good old standard defines which we all know. Also, simplify math to shift by PAGE_SHIFT instead of multiplying by PAGE_SIZE. Signed-off-by: Borislav Petkov b...@suse.de --- arch/x86/boot/compressed/eboot.c | 12 ++-- arch/x86/boot/compressed/eboot.h | 1 - arch/x86/platform/efi/efi.c | 22 +++--- include/linux/efi.h | 6 ++ 4 files changed, 19 insertions(+), 22 deletions(-) I'm pulling in Leif and Roy just so they're aware of this change, because while PAGE_SHIFT is always 12 on x86, that's not true for arm64. Thank you. Also adding Mark. However, I imagine that much work would be needed to allow for page sizes other than 4K, so I am definitely going to take this patch. This could actually be a problem for us pretty much from day 1. UEFI mandates the use of 4K pages on arm64, but Fedora will be using 64K - so this aspect of this patch will actually break the default usage model of Linux on arm64. It will probably not be a problem on the stub side, and it's not used in many places but it would break efi_lookup_mapped_address(), efi_range_is_wc() and memrange_efi_to_native() for use by arm64. At least the first of these would be a problem. / Leif diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b7388a425f09..5c440bf769a8 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -96,7 +96,7 @@ static efi_status_t high_alloc(unsigned long size, unsigned long align, if (status != EFI_SUCCESS) goto fail; - nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; + nr_pages = round_up(size, PAGE_SIZE) / PAGE_SIZE; again: for (i = 0; i map_size / desc_size; i++) { efi_memory_desc_t *desc; @@ -111,7 +111,7 @@ again: continue; start = desc-phys_addr; - end = start + desc-num_pages * (1UL EFI_PAGE_SHIFT); + end = start + (desc-num_pages PAGE_SHIFT); if ((start + size) end || (start + size) max) continue; @@ -173,7 +173,7 @@ static efi_status_t low_alloc(unsigned long size, unsigned long align, if (status != EFI_SUCCESS) goto fail; - nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; + nr_pages = round_up(size, PAGE_SIZE) / PAGE_SIZE; for (i = 0; i map_size / desc_size; i++) { efi_memory_desc_t *desc; unsigned long m = (unsigned long)map; @@ -188,7 +188,7 @@ static efi_status_t low_alloc(unsigned long size, unsigned long align, continue; start = desc-phys_addr; - end = start + desc-num_pages * (1UL EFI_PAGE_SHIFT); + end = start + (desc-num_pages PAGE_SHIFT); /* * Don't allocate at 0x0. It will confuse code that @@ -224,7 +224,7 @@ static void low_free(unsigned long size, unsigned long addr) { unsigned long nr_pages; - nr_pages = round_up(size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; + nr_pages = round_up(size, PAGE_SIZE) / PAGE_SIZE; efi_call_phys2(sys_table-boottime-free_pages, addr, nr_pages); } @@ -1128,7 +1128,7 @@ static efi_status_t relocate_kernel(struct setup_header *hdr) * possible. */ start = hdr-pref_address; - nr_pages = round_up(hdr-init_size, EFI_PAGE_SIZE) / EFI_PAGE_SIZE; + nr_pages = round_up(hdr-init_size, PAGE_SIZE) / PAGE_SIZE; status = efi_call_phys4(sys_table-boottime-allocate_pages, EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA, diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index e5b0a8f91c5f..786398c1bb9a 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h @@ -11,7 +11,6 @@ #define DESC_TYPE_CODE_DATA(1 0) -#define EFI_PAGE_SIZE (1UL EFI_PAGE_SHIFT) #define EFI_READ_CHUNK_SIZE(1024 * 1024) #define EFI_CONSOLE_OUT_DEVICE_GUID\ diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 7cec1e9e5494..538c1e6b7b2c 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -339,7 +339,7 @@ static void __init do_add_efi_memmap(void) for (p = memmap.map; p memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md-phys_addr; - unsigned long long size = md-num_pages EFI_PAGE_SHIFT; + unsigned long long size = md-num_pages PAGE_SHIFT; int e820_type; switch (md-type) { @@ -416,8 +416,8 @@ static void __init
Re: [PATCH 02/11] efi: Remove EFI_PAGE_SHIFT and EFI_PAGE_SIZE
On Sat, Sep 21, 2013 at 05:41:43PM +0200, Borislav Petkov wrote: On Sat, Sep 21, 2013 at 05:21:39PM +0200, Leif Lindholm wrote: It will probably not be a problem on the stub side, and it's not used in many places but it would break efi_lookup_mapped_address(), efi_range_is_wc() and memrange_efi_to_native() for use by arm64. At least the first of these would be a problem. Ok, maybe the generic header include/linux/efi.h might be a problem but the rest are changes to arch/x86/ which should have no effect whatsoever on any other arch. Indeed - my concerns are restricted to include/linux/efi.h and drivers/firmware/efi.c. Or are you planning to move some of it into generic code? I think some of the stub code is moved to generic in Roy's/Mark's patches - but then the stub shouldn't be an issue as in UEFI we have 4K pages. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 02/11] efi: Remove EFI_PAGE_SHIFT and EFI_PAGE_SIZE
On Sat, Sep 21, 2013 at 05:50:39PM +0200, Borislav Petkov wrote: Ok, maybe the generic header include/linux/efi.h might be a problem but the rest are changes to arch/x86/ which should have no effect whatsoever on any other arch. Or are you planning to move some of it into generic code? Oh, and arm64 defines a respective PAGE_SIZE too, so what's the problem? Or is possibly EFI_PAGE_SIZE != PAGE_SIZE on arm64? Correct. On arm64, EFI_PAGE_SIZE will be 4K, and PAGE_SIZE can be 4K or 64K, with at least Fedora opting for 64K. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] arm64: Add flush_cache_vmap call in __early_set_fixmap
__early_set_fixmap does not do any synchronization when called to set a fixmap entry. Add call to flush_vmap_cache(). Tested on hardware. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Tested-by: Graeme Gregory graeme.greg...@linaro.org Cc: Steve Capper steve.cap...@linaro.org --- arch/arm64/mm/ioremap.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c index 7ec3283..5b8766c 100644 --- a/arch/arm64/mm/ioremap.c +++ b/arch/arm64/mm/ioremap.c @@ -176,9 +176,10 @@ void __init __early_set_fixmap(enum fixed_addresses idx, pte = early_ioremap_pte(addr); - if (pgprot_val(flags)) + if (pgprot_val(flags)) { set_pte(pte, pfn_pte(phys PAGE_SHIFT, flags)); - else { + flush_cache_vmap(addr, addr + PAGE_SIZE); + } else { pte_clear(init_mm, addr, pte); flush_tlb_kernel_range(addr, addr+PAGE_SIZE); } -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] arm64: Add flush_cache_vmap call in __early_set_fixmap
On Fri, Jun 06, 2014 at 10:37:29AM -0400, Mark Salter wrote: On Fri, 2014-06-06 at 11:29 +0100, Leif Lindholm wrote: __early_set_fixmap does not do any synchronization when called to set a fixmap entry. Add call to flush_vmap_cache(). Tested on hardware. Signed-off-by: Leif Lindholm leif.lindh...@linaro.org Tested-by: Graeme Gregory graeme.greg...@linaro.org Cc: Steve Capper steve.cap...@linaro.org --- arch/arm64/mm/ioremap.c |5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c index 7ec3283..5b8766c 100644 --- a/arch/arm64/mm/ioremap.c +++ b/arch/arm64/mm/ioremap.c @@ -176,9 +176,10 @@ void __init __early_set_fixmap(enum fixed_addresses idx, pte = early_ioremap_pte(addr); - if (pgprot_val(flags)) + if (pgprot_val(flags)) { set_pte(pte, pfn_pte(phys PAGE_SHIFT, flags)); - else { + flush_cache_vmap(addr, addr + PAGE_SIZE); + } else { pte_clear(init_mm, addr, pte); flush_tlb_kernel_range(addr, addr+PAGE_SIZE); } I'm confused by the commit message mentioning synchronization but the code doing a cache flush. I see that arm64 implementation of flush_cache_vmap() is just a dsb(). If it is synchronization that we need here (and it certainly looks like we do), why not just add the dsb() directly to make that clear? It needs this Linux-semantically for the same reason remap_page_range needs it. From the ARM architectural point of view, the reason is that the translation table walk is considered a separate observer from the core data interface. But since there is a common Linux semantic for this, I preferred reusing that over just throwing in a dsb(). My interpretation of flush_cache_vmap() was flush mappings from cache, so they can be picked up by table walk. While we don't technically need to flush the cache here, the underlying requirement is the same. / Leif -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] arm64: Add flush_cache_vmap call in __early_set_fixmap
On Mon, Jun 09, 2014 at 12:03:56PM +0100, Catalin Marinas wrote: __early_set_fixmap does not do any synchronization when called to set a fixmap entry. Add call to flush_vmap_cache(). Did you hit a problem or it was just for safety? This fixes an abort when accessing early UEFI configuration tables on a hardware platform. (The issue can not be triggered with the FVM Base Model, even with cache modelling enabled.) I'm confused by the commit message mentioning synchronization but the code doing a cache flush. I see that arm64 implementation of flush_cache_vmap() is just a dsb(). If it is synchronization that we need here (and it certainly looks like we do), why not just add the dsb() directly to make that clear? It needs this Linux-semantically for the same reason remap_page_range needs it. From the ARM architectural point of view, the reason is that the translation table walk is considered a separate observer from the core data interface. But since there is a common Linux semantic for this, I preferred reusing that over just throwing in a dsb(). My interpretation of flush_cache_vmap() was flush mappings from cache, so they can be picked up by table walk. While we don't technically need to flush the cache here, the underlying requirement is the same. But the range you are flushing is not a range seen by the table walk observer. I just think it is clearer to explicitly show that it is the pte write which we want the table walk to see rather than to rely on the implicit behavior of a cache flush routine. I think that's a valid point. flush_cache_vmap() is used to remove any cached entries for the ioremap/vmap'ed range. That's not the aim here. As an optimisation, set_pte() doesn't have a dsb(). We do this on the clearing/invalidating path via the TLB flushing routines but not on the re-enabling path. Here we just added dsb() in the relevant functions that were called from the generic code (flush_cache_vmap, update_mmu_cache). A quick grep through the kernel shows that we have other set_pte() calls without additional dsb() like create_mapping(), I think kvm_set_pte() as well. So I'm proposing an alternative patch (which needs some benchmarking as well to see if anything is affected, maybe application startup time). I'm happy for any fix which can be included in 3.16. But is the dsb(ishst) sufficient? We need to also prevent reads from overtaking the set_pte(). i.e.: ptr = early_ioremap(phys_addr, size); if (ptr strcmp(ptr, magic) == 0) ... Does it not require a dsb(ish)? --8--- From b5cd0fff5cb044fa32cbaa4eebd2f00690922567 Mon Sep 17 00:00:00 2001 From: Catalin Marinas catalin.mari...@arm.com Date: Mon, 9 Jun 2014 11:55:03 +0100 Subject: [PATCH] arm64: Use DSB after page table update As an optimisation, set_pte() does not contain a DSB instruction to ensure the observability of the page table update before subsequent memory accesses or TLB maintenance. Such barrier is placed in the flush_tlb_*() functions and flush_cache_vmap()/update_mmu_cache(). However, there are still places where this barrier is missed like create_mapping(). This patch adds a dsb(ishst) call in set_pte() but only when the entry being written is valid. For invalid entries, there is always a subsequent TLB maintenance containing the DSB. Signed-off-by: Catalin Marinas catalin.mari...@arm.com Cc: Will Deacon will.dea...@arm.com --- arch/arm64/include/asm/cacheflush.h | 11 +-- arch/arm64/include/asm/pgtable.h| 8 arch/arm64/include/asm/tlbflush.h | 5 - 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h index a5176cf32dad..8fdf37d83014 100644 --- a/arch/arm64/include/asm/cacheflush.h +++ b/arch/arm64/include/asm/cacheflush.h @@ -138,19 +138,10 @@ static inline void __flush_icache_all(void) #define flush_icache_page(vma,page) do { } while (0) /* - * flush_cache_vmap() is used when creating mappings (eg, via vmap, - * vmalloc, ioremap etc) in kernel space for pages. On non-VIPT - * caches, since the direct-mappings of these pages may contain cached - * data, we need to do a full cache flush to ensure that writebacks - * don't corrupt data placed into these pages via the new mappings. + * Not required on AArch64 with VIPT caches. */ static inline void flush_cache_vmap(unsigned long start, unsigned long end) { - /* - * set_pte_at() called from vmap_pte_range() does not - * have a DSB after cleaning the cache line. - */ - dsb(ish); } static inline void flush_cache_vunmap(unsigned long start, unsigned long end) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index aa150ed99f22..2d03af6a2225 100644 --- a/arch/arm64/include/asm/pgtable.h +++