UEFI updates for arm64
This series consists of: - fixes for compliance with PE/COFF and UEFI specs - added support for SMBIOS, including upcoming version 3.0 - cleanups and diagnostic output improvements -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQF8BAABCgBmBQJUWf+KXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25zLm9w ZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQ5Q0QyQTBEQTZBRDhGNzMzMDE3NUUyQkJD MjM3MjA3RTk1NzRGQTdEAAoJEMI3IH6VdPp9T+MH/227Uei0tw1aTghisTqQ3cY5 4EowpMAJggFW5flBv5f+6vP0LMb8WTRsj2phlHZLlIatTD+TPcatSI6VnIxT2RWg UUD9mSxPYfIu5FVYGryySIpr5lU66nQmbafRAbQ16n20cZSsbAxaBkpIR1/R1sL3 ZQQdBcjiV6wIFuM9o7jd4pDzBfYzlM5rQh3nGb+6385CqazFaiWq7JR+uvICMu14 0nBtP9u9yxALlGC60HqbRxU7fBa9K5uPVVnedR6BJQLDJrZPEaQCGLsxL9XX/O7z jqO6F3drjKcRZ3dy+2OR8MtIl2uleUoA7XDT6cPDgm24FAlWOP9VfYzHVcK6vUU= =Gpfl -----END PGP SIGNATURE----- Merge tag 'for-3.19' of git://git.linaro.org/people/ard.biesheuvel/linux-arm into ard/efi-for-3.19 Pull UEFI updates from Ard Biesheuvel: - fixes for compliance with PE/COFF and UEFI specs - added support for SMBIOS, including upcoming version 3.0 - cleanups and diagnostic output improvements Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
Коммит
f2001bd5b8
|
@ -401,6 +401,17 @@ config EFI
|
|||
allow the kernel to be booted as an EFI application. This
|
||||
is only useful on systems that have UEFI firmware.
|
||||
|
||||
config DMI
|
||||
bool "Enable support for SMBIOS (DMI) tables"
|
||||
depends on EFI
|
||||
default y
|
||||
help
|
||||
This enables SMBIOS/DMI feature for systems.
|
||||
|
||||
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.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Userspace binary formats"
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* arch/arm64/include/asm/dmi.h
|
||||
*
|
||||
* Copyright (C) 2013 Linaro Limited.
|
||||
* Written by: Yi Li (yi.li@linaro.org)
|
||||
*
|
||||
* based on arch/ia64/include/asm/dmi.h
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_DMI_H
|
||||
#define __ASM_DMI_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/*
|
||||
* According to section 2.3.6 of the UEFI spec, the firmware should not
|
||||
* request a virtual mapping for configuration tables such as SMBIOS.
|
||||
* This means we have to map them before use.
|
||||
*/
|
||||
#define dmi_early_remap(x, l) ioremap_cache(x, l)
|
||||
#define dmi_early_unmap(x, l) iounmap(x)
|
||||
#define dmi_remap(x, l) ioremap_cache(x, l)
|
||||
#define dmi_unmap(x) iounmap(x)
|
||||
#define dmi_alloc(l) kzalloc(l, GFP_KERNEL)
|
||||
|
||||
#endif
|
|
@ -61,7 +61,8 @@ ENTRY(efi_stub_entry)
|
|||
*/
|
||||
mov x20, x0 // DTB address
|
||||
ldr x0, [sp, #16] // relocated _text address
|
||||
mov x21, x0
|
||||
ldr x21, =stext_offset
|
||||
add x21, x0, x21
|
||||
|
||||
/*
|
||||
* Flush dcache covering current runtime addresses
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/efi.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/memblock.h>
|
||||
|
@ -112,8 +113,6 @@ static int __init uefi_init(void)
|
|||
efi.systab->hdr.revision & 0xffff, vendor);
|
||||
|
||||
retval = efi_config_init(NULL);
|
||||
if (retval == 0)
|
||||
set_bit(EFI_CONFIG_TABLES, &efi.flags);
|
||||
|
||||
out:
|
||||
early_memunmap(efi.systab, sizeof(efi_system_table_t));
|
||||
|
@ -125,17 +124,17 @@ out:
|
|||
*/
|
||||
static __init int is_reserve_region(efi_memory_desc_t *md)
|
||||
{
|
||||
if (!is_normal_ram(md))
|
||||
switch (md->type) {
|
||||
case EFI_LOADER_CODE:
|
||||
case EFI_LOADER_DATA:
|
||||
case EFI_BOOT_SERVICES_CODE:
|
||||
case EFI_BOOT_SERVICES_DATA:
|
||||
case EFI_CONVENTIONAL_MEMORY:
|
||||
return 0;
|
||||
|
||||
if (md->attribute & EFI_MEMORY_RUNTIME)
|
||||
return 1;
|
||||
|
||||
if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
|
||||
md->type == EFI_RESERVED_TYPE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return is_normal_ram(md);
|
||||
}
|
||||
|
||||
static __init void reserve_regions(void)
|
||||
|
@ -471,3 +470,17 @@ err_unmap:
|
|||
return -1;
|
||||
}
|
||||
early_initcall(arm64_enter_virtual_mode);
|
||||
|
||||
static int __init arm64_dmi_init(void)
|
||||
{
|
||||
/*
|
||||
* On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to
|
||||
* be called early because dmi_id_init(), which is an arch_initcall
|
||||
* itself, depends on dmi_scan_machine() having been called already.
|
||||
*/
|
||||
dmi_scan_machine();
|
||||
if (dmi_available)
|
||||
dmi_set_dump_stack_arch_desc();
|
||||
return 0;
|
||||
}
|
||||
core_initcall(arm64_dmi_init);
|
||||
|
|
|
@ -132,6 +132,8 @@ efi_head:
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
.globl stext_offset
|
||||
.set stext_offset, stext - efi_head
|
||||
.align 3
|
||||
pe_header:
|
||||
.ascii "PE"
|
||||
|
@ -155,12 +157,12 @@ optional_header:
|
|||
.long 0 // SizeOfInitializedData
|
||||
.long 0 // SizeOfUninitializedData
|
||||
.long efi_stub_entry - efi_head // AddressOfEntryPoint
|
||||
.long stext - efi_head // BaseOfCode
|
||||
.long stext_offset // BaseOfCode
|
||||
|
||||
extra_header_fields:
|
||||
.quad 0 // ImageBase
|
||||
.long 0x20 // SectionAlignment
|
||||
.long 0x8 // FileAlignment
|
||||
.long 0x1000 // SectionAlignment
|
||||
.long PECOFF_FILE_ALIGNMENT // FileAlignment
|
||||
.short 0 // MajorOperatingSystemVersion
|
||||
.short 0 // MinorOperatingSystemVersion
|
||||
.short 0 // MajorImageVersion
|
||||
|
@ -172,7 +174,7 @@ extra_header_fields:
|
|||
.long _end - efi_head // SizeOfImage
|
||||
|
||||
// Everything before the kernel image is considered part of the header
|
||||
.long stext - efi_head // SizeOfHeaders
|
||||
.long stext_offset // SizeOfHeaders
|
||||
.long 0 // CheckSum
|
||||
.short 0xa // Subsystem (EFI application)
|
||||
.short 0 // DllCharacteristics
|
||||
|
@ -217,16 +219,24 @@ section_table:
|
|||
.byte 0
|
||||
.byte 0 // end of 0 padding of section name
|
||||
.long _end - stext // VirtualSize
|
||||
.long stext - efi_head // VirtualAddress
|
||||
.long stext_offset // VirtualAddress
|
||||
.long _edata - stext // SizeOfRawData
|
||||
.long stext - efi_head // PointerToRawData
|
||||
.long stext_offset // PointerToRawData
|
||||
|
||||
.long 0 // PointerToRelocations (0 for executables)
|
||||
.long 0 // PointerToLineNumbers (0 for executables)
|
||||
.short 0 // NumberOfRelocations (0 for executables)
|
||||
.short 0 // NumberOfLineNumbers (0 for executables)
|
||||
.long 0xe0500020 // Characteristics (section flags)
|
||||
.align 5
|
||||
|
||||
/*
|
||||
* EFI will load stext onwards at the 4k section alignment
|
||||
* described in the PE/COFF header. To ensure that instruction
|
||||
* sequences using an adrp and a :lo12: immediate will function
|
||||
* correctly at this alignment, we must ensure that stext is
|
||||
* placed at a 4k boundary in the Image to begin with.
|
||||
*/
|
||||
.align 12
|
||||
#endif
|
||||
|
||||
ENTRY(stext)
|
||||
|
|
|
@ -32,6 +32,22 @@ jiffies = jiffies_64;
|
|||
*(.hyp.text) \
|
||||
VMLINUX_SYMBOL(__hyp_text_end) = .;
|
||||
|
||||
/*
|
||||
* The size of the PE/COFF section that covers the kernel image, which
|
||||
* runs from stext to _edata, must be a round multiple of the PE/COFF
|
||||
* FileAlignment, which we set to its minimum value of 0x200. 'stext'
|
||||
* itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
|
||||
* boundary should be sufficient.
|
||||
*/
|
||||
PECOFF_FILE_ALIGNMENT = 0x200;
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
#define PECOFF_EDATA_PADDING \
|
||||
.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
|
||||
#else
|
||||
#define PECOFF_EDATA_PADDING
|
||||
#endif
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
|
@ -103,6 +119,7 @@ SECTIONS
|
|||
_data = .;
|
||||
_sdata = .;
|
||||
RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
|
||||
PECOFF_EDATA_PADDING
|
||||
_edata = .;
|
||||
|
||||
BSS_SECTION(0, 0, 0)
|
||||
|
|
|
@ -92,6 +92,12 @@ static void dmi_table(u8 *buf, int len, int num,
|
|||
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
|
||||
const struct dmi_header *dm = (const struct dmi_header *)data;
|
||||
|
||||
/*
|
||||
* 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
|
||||
*/
|
||||
if (dm->type == DMI_ENTRY_END_OF_TABLE)
|
||||
break;
|
||||
|
||||
/*
|
||||
* We want to know the total length (formatted area and
|
||||
* strings) before decoding to make sure we won't run off the
|
||||
|
@ -107,7 +113,7 @@ static void dmi_table(u8 *buf, int len, int num,
|
|||
}
|
||||
}
|
||||
|
||||
static u32 dmi_base;
|
||||
static phys_addr_t dmi_base;
|
||||
static u16 dmi_len;
|
||||
static u16 dmi_num;
|
||||
|
||||
|
@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf)
|
|||
|
||||
if (memcmp(buf, "_SM_", 4) == 0 &&
|
||||
buf[5] < 32 && dmi_checksum(buf, buf[5])) {
|
||||
smbios_ver = (buf[6] << 8) + buf[7];
|
||||
smbios_ver = get_unaligned_be16(buf + 6);
|
||||
|
||||
/* Some BIOS report weird SMBIOS version, fix that up */
|
||||
switch (smbios_ver) {
|
||||
|
@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf)
|
|||
buf += 16;
|
||||
|
||||
if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
|
||||
dmi_num = (buf[13] << 8) | buf[12];
|
||||
dmi_len = (buf[7] << 8) | buf[6];
|
||||
dmi_base = (buf[11] << 24) | (buf[10] << 16) |
|
||||
(buf[9] << 8) | buf[8];
|
||||
dmi_num = get_unaligned_le16(buf + 12);
|
||||
dmi_len = get_unaligned_le16(buf + 6);
|
||||
dmi_base = get_unaligned_le32(buf + 8);
|
||||
|
||||
if (dmi_walk_early(dmi_decode) == 0) {
|
||||
if (smbios_ver) {
|
||||
|
@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy
|
||||
* 32-bit entry point, there is no embedded DMI header (_DMI_) in here.
|
||||
*/
|
||||
static int __init dmi_smbios3_present(const u8 *buf)
|
||||
{
|
||||
if (memcmp(buf, "_SM3_", 5) == 0 &&
|
||||
buf[6] < 32 && dmi_checksum(buf, buf[6])) {
|
||||
dmi_ver = get_unaligned_be16(buf + 7);
|
||||
dmi_len = get_unaligned_le32(buf + 12);
|
||||
dmi_base = get_unaligned_le64(buf + 16);
|
||||
|
||||
/*
|
||||
* The 64-bit SMBIOS 3.0 entry point no longer has a field
|
||||
* containing the number of structures present in the table.
|
||||
* Instead, it defines the table size as a maximum size, and
|
||||
* relies on the end-of-table structure type (#127) to be used
|
||||
* to signal the end of the table.
|
||||
* So let's define dmi_num as an upper bound as well: each
|
||||
* structure has a 4 byte header, so dmi_len / 4 is an upper
|
||||
* bound for the number of structures in the table.
|
||||
*/
|
||||
dmi_num = dmi_len / 4;
|
||||
|
||||
if (dmi_walk_early(dmi_decode) == 0) {
|
||||
pr_info("SMBIOS %d.%d present.\n",
|
||||
dmi_ver >> 8, dmi_ver & 0xFF);
|
||||
dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
|
||||
pr_debug("DMI: %s\n", dmi_ids_string);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void __init dmi_scan_machine(void)
|
||||
{
|
||||
char __iomem *p, *q;
|
||||
char buf[32];
|
||||
|
||||
if (efi_enabled(EFI_CONFIG_TABLES)) {
|
||||
/*
|
||||
* According to the DMTF SMBIOS reference spec v3.0.0, it is
|
||||
* allowed to define both the 64-bit entry point (smbios3) and
|
||||
* the 32-bit entry point (smbios), in which case they should
|
||||
* either both point to the same SMBIOS structure table, or the
|
||||
* table pointed to by the 64-bit entry point should contain a
|
||||
* superset of the table contents pointed to by the 32-bit entry
|
||||
* point (section 5.2)
|
||||
* This implies that the 64-bit entry point should have
|
||||
* precedence if it is defined and supported by the OS. If we
|
||||
* have the 64-bit entry point, but fail to decode it, fall
|
||||
* back to the legacy one (if available)
|
||||
*/
|
||||
if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) {
|
||||
p = dmi_early_remap(efi.smbios3, 32);
|
||||
if (p == NULL)
|
||||
goto error;
|
||||
memcpy_fromio(buf, p, 32);
|
||||
dmi_early_unmap(p, 32);
|
||||
|
||||
if (!dmi_smbios3_present(buf)) {
|
||||
dmi_available = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
|
||||
goto error;
|
||||
|
||||
|
@ -552,7 +617,7 @@ void __init dmi_scan_machine(void)
|
|||
memset(buf, 0, 16);
|
||||
for (q = p; q < p + 0x10000; q += 16) {
|
||||
memcpy_fromio(buf + 16, q, 16);
|
||||
if (!dmi_present(buf)) {
|
||||
if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
|
||||
dmi_available = 1;
|
||||
dmi_early_unmap(p, 0x10000);
|
||||
goto out;
|
||||
|
|
|
@ -30,6 +30,7 @@ struct efi __read_mostly efi = {
|
|||
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi20 = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios3 = EFI_INVALID_TABLE_ADDR,
|
||||
.sal_systab = EFI_INVALID_TABLE_ADDR,
|
||||
.boot_info = EFI_INVALID_TABLE_ADDR,
|
||||
.hcdp = EFI_INVALID_TABLE_ADDR,
|
||||
|
@ -86,6 +87,8 @@ static ssize_t systab_show(struct kobject *kobj,
|
|||
str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
|
||||
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
|
||||
if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
|
||||
if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
|
||||
str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
|
||||
if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
|
||||
|
@ -260,6 +263,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
|
|||
{MPS_TABLE_GUID, "MPS", &efi.mps},
|
||||
{SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
|
||||
{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
|
||||
{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
|
||||
{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
|
||||
{NULL_GUID, NULL, NULL},
|
||||
};
|
||||
|
|
|
@ -247,9 +247,18 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
|
|||
goto fail_free_cmdline;
|
||||
}
|
||||
}
|
||||
if (!fdt_addr)
|
||||
|
||||
if (fdt_addr) {
|
||||
pr_efi(sys_table, "Using DTB from command line\n");
|
||||
} else {
|
||||
/* Look for a device tree configuration table entry. */
|
||||
fdt_addr = (uintptr_t)get_fdt(sys_table);
|
||||
if (fdt_addr)
|
||||
pr_efi(sys_table, "Using DTB from configuration table\n");
|
||||
}
|
||||
|
||||
if (!fdt_addr)
|
||||
pr_efi(sys_table, "Generating empty DTB\n");
|
||||
|
||||
status = handle_cmdline_files(sys_table, image, cmdline_ptr,
|
||||
"initrd=", dram_base + SZ_512M,
|
||||
|
|
|
@ -294,6 +294,7 @@ static const struct efi efi_xen __initconst = {
|
|||
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||
.acpi20 = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios = EFI_INVALID_TABLE_ADDR,
|
||||
.smbios3 = EFI_INVALID_TABLE_ADDR,
|
||||
.sal_systab = EFI_INVALID_TABLE_ADDR,
|
||||
.boot_info = EFI_INVALID_TABLE_ADDR,
|
||||
.hcdp = EFI_INVALID_TABLE_ADDR,
|
||||
|
|
|
@ -547,6 +547,9 @@ void efi_native_runtime_setup(void);
|
|||
#define SMBIOS_TABLE_GUID \
|
||||
EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
|
||||
|
||||
#define SMBIOS3_TABLE_GUID \
|
||||
EFI_GUID( 0xf2fd1544, 0x9794, 0x4a2c, 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 )
|
||||
|
||||
#define SAL_SYSTEM_TABLE_GUID \
|
||||
EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
|
||||
|
||||
|
@ -810,7 +813,8 @@ extern struct efi {
|
|||
unsigned long mps; /* MPS table */
|
||||
unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
|
||||
unsigned long acpi20; /* ACPI table (ACPI 2.0) */
|
||||
unsigned long smbios; /* SM BIOS table */
|
||||
unsigned long smbios; /* SMBIOS table (32 bit entry point) */
|
||||
unsigned long smbios3; /* SMBIOS table (64 bit entry point) */
|
||||
unsigned long sal_systab; /* SAL system table */
|
||||
unsigned long boot_info; /* boot info table */
|
||||
unsigned long hcdp; /* HCDP table */
|
||||
|
|
Загрузка…
Ссылка в новой задаче