Skip to content

Commit f2001bd

Browse files
committed
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 <[email protected]>
2 parents cac7f24 + 0bcaa90 commit f2001bd

File tree

11 files changed

+195
-29
lines changed

11 files changed

+195
-29
lines changed

arch/arm64/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,17 @@ config EFI
401401
allow the kernel to be booted as an EFI application. This
402402
is only useful on systems that have UEFI firmware.
403403

404+
config DMI
405+
bool "Enable support for SMBIOS (DMI) tables"
406+
depends on EFI
407+
default y
408+
help
409+
This enables SMBIOS/DMI feature for systems.
410+
411+
This option is only useful on systems that have UEFI firmware.
412+
However, even with this option, the resultant kernel should
413+
continue to boot on existing non-UEFI platforms.
414+
404415
endmenu
405416

406417
menu "Userspace binary formats"

arch/arm64/include/asm/dmi.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* arch/arm64/include/asm/dmi.h
3+
*
4+
* Copyright (C) 2013 Linaro Limited.
5+
* Written by: Yi Li ([email protected])
6+
*
7+
* based on arch/ia64/include/asm/dmi.h
8+
*
9+
* This file is subject to the terms and conditions of the GNU General Public
10+
* License. See the file "COPYING" in the main directory of this archive
11+
* for more details.
12+
*/
13+
14+
#ifndef __ASM_DMI_H
15+
#define __ASM_DMI_H
16+
17+
#include <linux/io.h>
18+
#include <linux/slab.h>
19+
20+
/*
21+
* According to section 2.3.6 of the UEFI spec, the firmware should not
22+
* request a virtual mapping for configuration tables such as SMBIOS.
23+
* This means we have to map them before use.
24+
*/
25+
#define dmi_early_remap(x, l) ioremap_cache(x, l)
26+
#define dmi_early_unmap(x, l) iounmap(x)
27+
#define dmi_remap(x, l) ioremap_cache(x, l)
28+
#define dmi_unmap(x) iounmap(x)
29+
#define dmi_alloc(l) kzalloc(l, GFP_KERNEL)
30+
31+
#endif

arch/arm64/kernel/efi-entry.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ ENTRY(efi_stub_entry)
6161
*/
6262
mov x20, x0 // DTB address
6363
ldr x0, [sp, #16] // relocated _text address
64-
mov x21, x0
64+
ldr x21, =stext_offset
65+
add x21, x0, x21
6566

6667
/*
6768
* Flush dcache covering current runtime addresses

arch/arm64/kernel/efi.c

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
*
1212
*/
1313

14+
#include <linux/dmi.h>
1415
#include <linux/efi.h>
1516
#include <linux/export.h>
1617
#include <linux/memblock.h>
@@ -112,8 +113,6 @@ static int __init uefi_init(void)
112113
efi.systab->hdr.revision & 0xffff, vendor);
113114

114115
retval = efi_config_init(NULL);
115-
if (retval == 0)
116-
set_bit(EFI_CONFIG_TABLES, &efi.flags);
117116

118117
out:
119118
early_memunmap(efi.systab, sizeof(efi_system_table_t));
@@ -125,17 +124,17 @@ static int __init uefi_init(void)
125124
*/
126125
static __init int is_reserve_region(efi_memory_desc_t *md)
127126
{
128-
if (!is_normal_ram(md))
127+
switch (md->type) {
128+
case EFI_LOADER_CODE:
129+
case EFI_LOADER_DATA:
130+
case EFI_BOOT_SERVICES_CODE:
131+
case EFI_BOOT_SERVICES_DATA:
132+
case EFI_CONVENTIONAL_MEMORY:
129133
return 0;
130-
131-
if (md->attribute & EFI_MEMORY_RUNTIME)
132-
return 1;
133-
134-
if (md->type == EFI_ACPI_RECLAIM_MEMORY ||
135-
md->type == EFI_RESERVED_TYPE)
136-
return 1;
137-
138-
return 0;
134+
default:
135+
break;
136+
}
137+
return is_normal_ram(md);
139138
}
140139

141140
static __init void reserve_regions(void)
@@ -471,3 +470,17 @@ static int __init arm64_enter_virtual_mode(void)
471470
return -1;
472471
}
473472
early_initcall(arm64_enter_virtual_mode);
473+
474+
static int __init arm64_dmi_init(void)
475+
{
476+
/*
477+
* On arm64, DMI depends on UEFI, and dmi_scan_machine() needs to
478+
* be called early because dmi_id_init(), which is an arch_initcall
479+
* itself, depends on dmi_scan_machine() having been called already.
480+
*/
481+
dmi_scan_machine();
482+
if (dmi_available)
483+
dmi_set_dump_stack_arch_desc();
484+
return 0;
485+
}
486+
core_initcall(arm64_dmi_init);

arch/arm64/kernel/head.S

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ efi_head:
132132
#endif
133133

134134
#ifdef CONFIG_EFI
135+
.globl stext_offset
136+
.set stext_offset, stext - efi_head
135137
.align 3
136138
pe_header:
137139
.ascii "PE"
@@ -155,12 +157,12 @@ optional_header:
155157
.long 0 // SizeOfInitializedData
156158
.long 0 // SizeOfUninitializedData
157159
.long efi_stub_entry - efi_head // AddressOfEntryPoint
158-
.long stext - efi_head // BaseOfCode
160+
.long stext_offset // BaseOfCode
159161

160162
extra_header_fields:
161163
.quad 0 // ImageBase
162-
.long 0x20 // SectionAlignment
163-
.long 0x8 // FileAlignment
164+
.long 0x1000 // SectionAlignment
165+
.long PECOFF_FILE_ALIGNMENT // FileAlignment
164166
.short 0 // MajorOperatingSystemVersion
165167
.short 0 // MinorOperatingSystemVersion
166168
.short 0 // MajorImageVersion
@@ -172,7 +174,7 @@ extra_header_fields:
172174
.long _end - efi_head // SizeOfImage
173175

174176
// Everything before the kernel image is considered part of the header
175-
.long stext - efi_head // SizeOfHeaders
177+
.long stext_offset // SizeOfHeaders
176178
.long 0 // CheckSum
177179
.short 0xa // Subsystem (EFI application)
178180
.short 0 // DllCharacteristics
@@ -217,16 +219,24 @@ section_table:
217219
.byte 0
218220
.byte 0 // end of 0 padding of section name
219221
.long _end - stext // VirtualSize
220-
.long stext - efi_head // VirtualAddress
222+
.long stext_offset // VirtualAddress
221223
.long _edata - stext // SizeOfRawData
222-
.long stext - efi_head // PointerToRawData
224+
.long stext_offset // PointerToRawData
223225

224226
.long 0 // PointerToRelocations (0 for executables)
225227
.long 0 // PointerToLineNumbers (0 for executables)
226228
.short 0 // NumberOfRelocations (0 for executables)
227229
.short 0 // NumberOfLineNumbers (0 for executables)
228230
.long 0xe0500020 // Characteristics (section flags)
229-
.align 5
231+
232+
/*
233+
* EFI will load stext onwards at the 4k section alignment
234+
* described in the PE/COFF header. To ensure that instruction
235+
* sequences using an adrp and a :lo12: immediate will function
236+
* correctly at this alignment, we must ensure that stext is
237+
* placed at a 4k boundary in the Image to begin with.
238+
*/
239+
.align 12
230240
#endif
231241

232242
ENTRY(stext)

arch/arm64/kernel/vmlinux.lds.S

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ jiffies = jiffies_64;
3232
*(.hyp.text) \
3333
VMLINUX_SYMBOL(__hyp_text_end) = .;
3434

35+
/*
36+
* The size of the PE/COFF section that covers the kernel image, which
37+
* runs from stext to _edata, must be a round multiple of the PE/COFF
38+
* FileAlignment, which we set to its minimum value of 0x200. 'stext'
39+
* itself is 4 KB aligned, so padding out _edata to a 0x200 aligned
40+
* boundary should be sufficient.
41+
*/
42+
PECOFF_FILE_ALIGNMENT = 0x200;
43+
44+
#ifdef CONFIG_EFI
45+
#define PECOFF_EDATA_PADDING \
46+
.pecoff_edata_padding : { BYTE(0); . = ALIGN(PECOFF_FILE_ALIGNMENT); }
47+
#else
48+
#define PECOFF_EDATA_PADDING
49+
#endif
50+
3551
SECTIONS
3652
{
3753
/*
@@ -103,6 +119,7 @@ SECTIONS
103119
_data = .;
104120
_sdata = .;
105121
RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
122+
PECOFF_EDATA_PADDING
106123
_edata = .;
107124

108125
BSS_SECTION(0, 0, 0)

drivers/firmware/dmi_scan.c

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ static void dmi_table(u8 *buf, int len, int num,
9292
while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
9393
const struct dmi_header *dm = (const struct dmi_header *)data;
9494

95+
/*
96+
* 7.45 End-of-Table (Type 127) [SMBIOS reference spec v3.0.0]
97+
*/
98+
if (dm->type == DMI_ENTRY_END_OF_TABLE)
99+
break;
100+
95101
/*
96102
* We want to know the total length (formatted area and
97103
* 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,
107113
}
108114
}
109115

110-
static u32 dmi_base;
116+
static phys_addr_t dmi_base;
111117
static u16 dmi_len;
112118
static u16 dmi_num;
113119

@@ -467,7 +473,7 @@ static int __init dmi_present(const u8 *buf)
467473

468474
if (memcmp(buf, "_SM_", 4) == 0 &&
469475
buf[5] < 32 && dmi_checksum(buf, buf[5])) {
470-
smbios_ver = (buf[6] << 8) + buf[7];
476+
smbios_ver = get_unaligned_be16(buf + 6);
471477

472478
/* Some BIOS report weird SMBIOS version, fix that up */
473479
switch (smbios_ver) {
@@ -489,10 +495,9 @@ static int __init dmi_present(const u8 *buf)
489495
buf += 16;
490496

491497
if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
492-
dmi_num = (buf[13] << 8) | buf[12];
493-
dmi_len = (buf[7] << 8) | buf[6];
494-
dmi_base = (buf[11] << 24) | (buf[10] << 16) |
495-
(buf[9] << 8) | buf[8];
498+
dmi_num = get_unaligned_le16(buf + 12);
499+
dmi_len = get_unaligned_le16(buf + 6);
500+
dmi_base = get_unaligned_le32(buf + 8);
496501

497502
if (dmi_walk_early(dmi_decode) == 0) {
498503
if (smbios_ver) {
@@ -514,12 +519,72 @@ static int __init dmi_present(const u8 *buf)
514519
return 1;
515520
}
516521

522+
/*
523+
* Check for the SMBIOS 3.0 64-bit entry point signature. Unlike the legacy
524+
* 32-bit entry point, there is no embedded DMI header (_DMI_) in here.
525+
*/
526+
static int __init dmi_smbios3_present(const u8 *buf)
527+
{
528+
if (memcmp(buf, "_SM3_", 5) == 0 &&
529+
buf[6] < 32 && dmi_checksum(buf, buf[6])) {
530+
dmi_ver = get_unaligned_be16(buf + 7);
531+
dmi_len = get_unaligned_le32(buf + 12);
532+
dmi_base = get_unaligned_le64(buf + 16);
533+
534+
/*
535+
* The 64-bit SMBIOS 3.0 entry point no longer has a field
536+
* containing the number of structures present in the table.
537+
* Instead, it defines the table size as a maximum size, and
538+
* relies on the end-of-table structure type (#127) to be used
539+
* to signal the end of the table.
540+
* So let's define dmi_num as an upper bound as well: each
541+
* structure has a 4 byte header, so dmi_len / 4 is an upper
542+
* bound for the number of structures in the table.
543+
*/
544+
dmi_num = dmi_len / 4;
545+
546+
if (dmi_walk_early(dmi_decode) == 0) {
547+
pr_info("SMBIOS %d.%d present.\n",
548+
dmi_ver >> 8, dmi_ver & 0xFF);
549+
dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
550+
pr_debug("DMI: %s\n", dmi_ids_string);
551+
return 0;
552+
}
553+
}
554+
return 1;
555+
}
556+
517557
void __init dmi_scan_machine(void)
518558
{
519559
char __iomem *p, *q;
520560
char buf[32];
521561

522562
if (efi_enabled(EFI_CONFIG_TABLES)) {
563+
/*
564+
* According to the DMTF SMBIOS reference spec v3.0.0, it is
565+
* allowed to define both the 64-bit entry point (smbios3) and
566+
* the 32-bit entry point (smbios), in which case they should
567+
* either both point to the same SMBIOS structure table, or the
568+
* table pointed to by the 64-bit entry point should contain a
569+
* superset of the table contents pointed to by the 32-bit entry
570+
* point (section 5.2)
571+
* This implies that the 64-bit entry point should have
572+
* precedence if it is defined and supported by the OS. If we
573+
* have the 64-bit entry point, but fail to decode it, fall
574+
* back to the legacy one (if available)
575+
*/
576+
if (efi.smbios3 != EFI_INVALID_TABLE_ADDR) {
577+
p = dmi_early_remap(efi.smbios3, 32);
578+
if (p == NULL)
579+
goto error;
580+
memcpy_fromio(buf, p, 32);
581+
dmi_early_unmap(p, 32);
582+
583+
if (!dmi_smbios3_present(buf)) {
584+
dmi_available = 1;
585+
goto out;
586+
}
587+
}
523588
if (efi.smbios == EFI_INVALID_TABLE_ADDR)
524589
goto error;
525590

@@ -552,7 +617,7 @@ void __init dmi_scan_machine(void)
552617
memset(buf, 0, 16);
553618
for (q = p; q < p + 0x10000; q += 16) {
554619
memcpy_fromio(buf + 16, q, 16);
555-
if (!dmi_present(buf)) {
620+
if (!dmi_smbios3_present(buf) || !dmi_present(buf)) {
556621
dmi_available = 1;
557622
dmi_early_unmap(p, 0x10000);
558623
goto out;

drivers/firmware/efi/efi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct efi __read_mostly efi = {
3030
.acpi = EFI_INVALID_TABLE_ADDR,
3131
.acpi20 = EFI_INVALID_TABLE_ADDR,
3232
.smbios = EFI_INVALID_TABLE_ADDR,
33+
.smbios3 = EFI_INVALID_TABLE_ADDR,
3334
.sal_systab = EFI_INVALID_TABLE_ADDR,
3435
.boot_info = EFI_INVALID_TABLE_ADDR,
3536
.hcdp = EFI_INVALID_TABLE_ADDR,
@@ -86,6 +87,8 @@ static ssize_t systab_show(struct kobject *kobj,
8687
str += sprintf(str, "ACPI=0x%lx\n", efi.acpi);
8788
if (efi.smbios != EFI_INVALID_TABLE_ADDR)
8889
str += sprintf(str, "SMBIOS=0x%lx\n", efi.smbios);
90+
if (efi.smbios3 != EFI_INVALID_TABLE_ADDR)
91+
str += sprintf(str, "SMBIOS3=0x%lx\n", efi.smbios3);
8992
if (efi.hcdp != EFI_INVALID_TABLE_ADDR)
9093
str += sprintf(str, "HCDP=0x%lx\n", efi.hcdp);
9194
if (efi.boot_info != EFI_INVALID_TABLE_ADDR)
@@ -260,6 +263,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
260263
{MPS_TABLE_GUID, "MPS", &efi.mps},
261264
{SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
262265
{SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
266+
{SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3},
263267
{UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
264268
{NULL_GUID, NULL, NULL},
265269
};

drivers/firmware/efi/libstub/arm-stub.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,18 @@ unsigned long __init efi_entry(void *handle, efi_system_table_t *sys_table,
247247
goto fail_free_cmdline;
248248
}
249249
}
250-
if (!fdt_addr)
250+
251+
if (fdt_addr) {
252+
pr_efi(sys_table, "Using DTB from command line\n");
253+
} else {
251254
/* Look for a device tree configuration table entry. */
252255
fdt_addr = (uintptr_t)get_fdt(sys_table);
256+
if (fdt_addr)
257+
pr_efi(sys_table, "Using DTB from configuration table\n");
258+
}
259+
260+
if (!fdt_addr)
261+
pr_efi(sys_table, "Generating empty DTB\n");
253262

254263
status = handle_cmdline_files(sys_table, image, cmdline_ptr,
255264
"initrd=", dram_base + SZ_512M,

drivers/xen/efi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ static const struct efi efi_xen __initconst = {
294294
.acpi = EFI_INVALID_TABLE_ADDR,
295295
.acpi20 = EFI_INVALID_TABLE_ADDR,
296296
.smbios = EFI_INVALID_TABLE_ADDR,
297+
.smbios3 = EFI_INVALID_TABLE_ADDR,
297298
.sal_systab = EFI_INVALID_TABLE_ADDR,
298299
.boot_info = EFI_INVALID_TABLE_ADDR,
299300
.hcdp = EFI_INVALID_TABLE_ADDR,

0 commit comments

Comments
 (0)