arm64 EFI patches for 3.19
Subsystems (4)
v2 cover arm64 EFI patches for 3.19
Version v2 of arm64/efi patches for 3.19.
Changes since previous version:
- dropped patch #6 'arm64/efi: use UEFI memory map unconditionally if available' (will be revisited later, but due to other changes in the pipeline regarding the virtual mapping of UEFI Runtime Services, it makes sense to defer this to 3.20)
- added patch #10 'efi: efi-stub: notify on DTB absence'
Note that Matt Fleming has given his approval for taking all of these through the arm64 tree.
@Matt: may we have your ack on patches #6, #7 and #10 please? Patch #7 covers DMI not EFI but get_maintainer.pl is not very helpful here. (The patch is cc'ed to akpm and Tony Luck [ia64 maintainer])
Patches #1 - #3 are fixes for compliance with the UEFI and PE/COFF specs. No issues are known that require these patches, so there is no reason to pull them into a stable release.
Patch #4 fixes is_reserve_region() to correctly identify UEFI memory regions that need to be reserved by the OS. This patch supersedes the patch sent as part of the v1 series: 'arm64/efi: reserve regions of type ACPI_MEMORY_NVS'
Patch #5 removes a redundant set_bit(EFI_CONFIG_TABLES) call.
Patches #6 - #9 implement DMI/SMBIOS for arm64, both the existing 32-bit version and the upcoming 3.0 version that allows the SMBIOS structure table to reside at a physical offset that cannot be encoded in 32-bits. It also installs a 'Hardware name: xxx' string that is printed along with oopses and kernel call stack dumps on systems that implement DMI/SMBIOS.
Patch #10 is a patch from Mark Rutland I picked up that improves the diagnostic output of the EFI stub regarding the origin of the device tree blob.
Please refer to the patches themselves for version history. Acks and/or comments appreciated.
Ard Biesheuvel (8):
arm64/efi: efistub: jump to 'stext' directly, not through the header arm64/efi: set PE/COFF section alignment to 4 KB arm64/efi: set PE/COFF file alignment to 512 bytes arm64/efi: invert UEFI memory region reservation logic arm64/efi: drop redundant set_bit(EFI_CONFIG_TABLES)
efi: dmi: add support for SMBIOS 3.0 UEFI configuration table
dmi: add support for SMBIOS 3.0 64-bit entry point
arm64: dmi: set DMI string as dump stack arch description
Mark Rutland (1):
efi: efi-stub: notify on DTB absence
Yi Li (1):
arm64: dmi: Add SMBIOS/DMI support
arch/arm64/Kconfig | 11 ++++++ arch/arm64/include/asm/dmi.h | 31 +++++++++++++++ arch/arm64/kernel/efi-entry.S | 3 +- arch/arm64/kernel/efi.c | 37 +++++++++++------ arch/arm64/kernel/head.S | 24 +++++++---- arch/arm64/kernel/vmlinux.lds.S | 17 ++++++++ drivers/firmware/dmi_scan.c | 70 ++++++++++++++++++++++++++++++++- drivers/firmware/efi/efi.c | 4 ++ drivers/firmware/efi/libstub/arm-stub.c | 11 +++++- drivers/xen/efi.c | 1 + include/linux/efi.h | 6 ++- 11 files changed, 191 insertions(+), 24 deletions(-) create mode 100644 arch/arm64/include/asm/dmi.h
Signature · 1 line
1.8.3.2
PATCH v2 1/10 arm64/efi: efistub: jump to 'stext' directly, not through the header
After the EFI stub has done its business, it jumps into the kernel by branching to offset #0 of the loaded Image, which is where it expects to find the header containing a 'branch to stext' instruction.
However, the UEFI spec 2.1.1 states the following regarding PE/COFF image loading:
"A UEFI image is loaded into memory through the LoadImage() Boot Service. This service loads an image with a PE32+ format into memory. This PE32+ loader is required to load all sections of the PE32+ image into memory."
In other words, it is /not/ required to load parts of the image that are not covered by a PE/COFF section, so it may not have loaded the header at the expected offset, as it is not covered by any PE/COFF section.
So instead, jump to 'stext' directly, which is at the base of the PE/COFF .text section, by supplying a symbol 'stext_offset' to efi-entry.o which contains the relative offset of stext into the Image. Also replace other open coded calculations of the same value with a reference to 'stext_offset'
---
v3:
- rebased onto 3.17+
- added spec reference to commit message
v2:
- drop :lo12: relocation against stext_offset in favor of using a literal '=stext_offset' which is safer
--- arch/arm64/kernel/efi-entry.S | 3 ++- arch/arm64/kernel/head.S | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-)
arch/arm64/kernel/efi-entry.S +2 -1
@@ -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
arch/arm64/kernel/head.S +6 -4
@@ -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,7 +157,7 @@ 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
@@ -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,9 +219,9 @@ 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)
Signature · 1 line
1.8.3.2
PATCH v2 2/10 arm64/efi: set PE/COFF section alignment to 4 KB
In reply to Ard BiesheuvelPosition independent AArch64 code needs to be linked and loaded at the same relative offset from a 4 KB boundary, or adrp/add and adrp/ldr pairs will not work correctly. (This is how PC relative symbol references with a 4 GB reach are emitted)
We need to declare this in the PE/COFF header, otherwise the PE/COFF loader may load the Image and invoke the stub at an offset which violates this rule.
---
v2: added comment explaining '.align 12' in head.S
--- arch/arm64/kernel/head.S | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
arch/arm64/kernel/head.S +10 -2
@@ -161,7 +161,7 @@ optional_header: extra_header_fields: .quad 0 // ImageBase - .long 0x20 // SectionAlignment + .long 0x1000 // SectionAlignment .long 0x8 // FileAlignment .short 0 // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion
@@ -228,7 +228,15 @@ section_table: .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)
Signature · 1 line
1.8.3.2
PATCH v2 3/10 arm64/efi: set PE/COFF file alignment to 512 bytes
In reply to Ard BiesheuvelChange our PE/COFF header to use the minimum file alignment of 512 bytes (0x200), as mandated by the PE/COFF spec v8.3
Also update the linker script so that the Image file itself is also a round multiple of FileAlignment.
--- arch/arm64/kernel/head.S | 2 +- arch/arm64/kernel/vmlinux.lds.S | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-)
arch/arm64/kernel/head.S +1 -1
@@ -162,7 +162,7 @@ optional_header: extra_header_fields: .quad 0 // ImageBase .long 0x1000 // SectionAlignment - .long 0x8 // FileAlignment + .long PECOFF_FILE_ALIGNMENT // FileAlignment .short 0 // MajorOperatingSystemVersion .short 0 // MinorOperatingSystemVersion .short 0 // MajorImageVersion
arch/arm64/kernel/vmlinux.lds.S +17 -0
@@ -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)
Signature · 1 line
1.8.3.2
PATCH v2 4/10 arm64/efi: invert UEFI memory region reservation logic
In reply to Ard BiesheuvelInstead of reserving the memory regions based on which types we know need to be reserved, consider only regions of the following types as free for general use by the OS:
EFI_LOADER_CODEEFI_LOADER_DATAEFI_BOOT_SERVICES_CODEEFI_BOOT_SERVICES_DATAEFI_CONVENTIONAL_MEMORY
Note that this also fixes a problem with the original code, which would misidentify a EFI_RUNTIME_SERVICES_DATA region as not reserved if it does not have the EFI_MEMORY_RUNTIME attribute set. However, it is perfectly legal for the firmware not to request a virtual mapping for EFI_RUNTIME_SERVICES_DATA regions that contain configuration tables, in which case the EFI_MEMORY_RUNTIME attribute would not be set.
--- arch/arm64/kernel/efi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
arch/arm64/kernel/efi.c +10 -10
@@ -125,17 +125,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 )
Signature · 1 line
1.8.3.2
Mark Rutland
reviewerPATCH v2 4/10 arm64/efi: invert UEFI memory region reservation logic
Quoted 41 lines · Ard Biesheuvel
Instead of reserving the memory regions based on which types we know need to be reserved, consider only regions of the following types as free for general use by the OS:
EFI_LOADER_CODEEFI_LOADER_DATAEFI_BOOT_SERVICES_CODEEFI_BOOT_SERVICES_DATAEFI_CONVENTIONAL_MEMORYNote that this also fixes a problem with the original code, which would misidentify a
EFI_RUNTIME_SERVICES_DATAregion as not reserved if it does not have theEFI_MEMORY_RUNTIMEattribute set. However, it is perfectly legal for the firmware not to request a virtual mapping forEFI_RUNTIME_SERVICES_DATAregions that contain configuration tables, in which case theEFI_MEMORY_RUNTIMEattribute would not be set.Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/kernel/efi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)arch/arm64/kernel/efi.c +6
-4@@ -125,17 +125,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 ;
arch/arm64/kernel/efi.c out: · line 138
Quoted 10 lines
arch/arm64/kernel/efi.c +4
-6- -if (md->type ==EFI_ACPI_RECLAIM_MEMORY || - md->type ==EFI_RESERVED_TYPE ) -return 1 ; - -return 0 ; +default : +break ; + } +return is_normal_ram (md);
Just to check: did we figure out if UnusableMemory was allowed to have EFI_MEMORY_WB attributes? If it isn't, this looks fine to me.
If it is, then we will need to remove that memory (rather than reserving it) to prevent speculative accesses.
Thanks,
Mark.
PATCH v2 4/10 arm64/efi: invert UEFI memory region reservation logic
Quoted 56 lines · Mark Rutland
Quoted 41 lines · Ard Biesheuvel
Instead of reserving the memory regions based on which types we know need to be reserved, consider only regions of the following types as free for general use by the OS:
EFI_LOADER_CODEEFI_LOADER_DATAEFI_BOOT_SERVICES_CODEEFI_BOOT_SERVICES_DATAEFI_CONVENTIONAL_MEMORYNote that this also fixes a problem with the original code, which would misidentify a
EFI_RUNTIME_SERVICES_DATAregion as not reserved if it does not have theEFI_MEMORY_RUNTIMEattribute set. However, it is perfectly legal for the firmware not to request a virtual mapping forEFI_RUNTIME_SERVICES_DATAregions that contain configuration tables, in which case theEFI_MEMORY_RUNTIMEattribute would not be set.Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/kernel/efi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)arch/arm64/kernel/efi.c +6
-4@@ -125,17 +125,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 ;arch/arm64/kernel/efi.c out: · line 138
Quoted 10 lines
arch/arm64/kernel/efi.c +4
-6- -if (md->type ==EFI_ACPI_RECLAIM_MEMORY || - md->type ==EFI_RESERVED_TYPE ) -return 1 ; - -return 0 ; +default : +break ; + } +return is_normal_ram (md);Just to check: did we figure out if UnusableMemory was allowed to have
EFI_MEMORY_WBattributes? If it isn't, this looks fine to me.
Quoted 3 lines
If it is, then we will need to remove that memory (rather than reserving it) to prevent speculative accesses.
The spec does not mention at all how EfiUnusableMemory should be used, and I would assume any such regions to have the EFI_MEMORY_WB attribute set, as it is carved out of the normal system RAM, and the way Tianocore/EDK2 implements it at least, all those attributes (including the write-protect/execute-protect ones) are copied straight from the underlying regions and never set to reflect the nature of the actual contents.
However, for 3.20 I intend to propose another change to this code, so that only non-reserved, usable memory gets memblock_add()'ed in the first place, and I suppose this should cover your concern as well. The reason for doing that is to allow tools like dmidecode and lshw access to the SMBIOS and other tables through /dev/mem, which is currently disallowed when STRICT_DEVMEM is set.
Signature · 1 line
Ard.
Mark Rutland
reviewerPATCH v2 4/10 arm64/efi: invert UEFI memory region reservation logic
Quoted 61 lines · Ard Biesheuvel
Quoted 56 lines · Mark Rutland
Quoted 41 lines · Ard Biesheuvel
Instead of reserving the memory regions based on which types we know need to be reserved, consider only regions of the following types as free for general use by the OS:
EFI_LOADER_CODEEFI_LOADER_DATAEFI_BOOT_SERVICES_CODEEFI_BOOT_SERVICES_DATAEFI_CONVENTIONAL_MEMORYNote that this also fixes a problem with the original code, which would misidentify a
EFI_RUNTIME_SERVICES_DATAregion as not reserved if it does not have theEFI_MEMORY_RUNTIMEattribute set. However, it is perfectly legal for the firmware not to request a virtual mapping forEFI_RUNTIME_SERVICES_DATAregions that contain configuration tables, in which case theEFI_MEMORY_RUNTIMEattribute would not be set.Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/kernel/efi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)arch/arm64/kernel/efi.c +6
-4@@ -125,17 +125,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 ;arch/arm64/kernel/efi.c out: · line 138
Quoted 10 lines
arch/arm64/kernel/efi.c +4
-6- -if (md->type ==EFI_ACPI_RECLAIM_MEMORY || - md->type ==EFI_RESERVED_TYPE ) -return 1 ; - -return 0 ; +default : +break ; + } +return is_normal_ram (md);Just to check: did we figure out if UnusableMemory was allowed to have
EFI_MEMORY_WBattributes? If it isn't, this looks fine to me.Quoted 3 lines
If it is, then we will need to remove that memory (rather than reserving it) to prevent speculative accesses.
Quoted 7 lines
The spec does not mention at all how EfiUnusableMemory should be used, and I would assume any such regions to have the
EFI_MEMORY_WBattribute set, as it is carved out of the normal system RAM, and the way Tianocore/EDK2 implements it at least, all those attributes (including the write-protect/execute-protect ones) are copied straight from the underlying regions and never set to reflect the nature of the actual contents.
Ok. That's precisely the case I was concerned about.
Quoted 6 lines
However, for 3.20 I intend to propose another change to this code, so that only non-reserved, usable memory gets memblock_add()'ed in the first place, and I suppose this should cover your concern as well. The reason for doing that is to allow tools like dmidecode and lshw access to the SMBIOS and other tables through
/dev/mem, which is currently disallowed whenSTRICT_DEVMEMis set.
So long as said memory is not later passed to memblock_reserve, that should be ok for the EfiUnusableMemory case. I guess we haven't actually seen such memory yet anyhow?
I not all that keen on the usage of /dev/mem for those given the availability of other interfaces.
Mark.
PATCH v2 4/10 arm64/efi: invert UEFI memory region reservation logic
In reply to Ard BiesheuvelQuoted 55 lines · Ard Biesheuvel
Instead of reserving the memory regions based on which types we know need to be reserved, consider only regions of the following types as free for general use by the OS:
EFI_LOADER_CODEEFI_LOADER_DATAEFI_BOOT_SERVICES_CODEEFI_BOOT_SERVICES_DATAEFI_CONVENTIONAL_MEMORYNote that this also fixes a problem with the original code, which would misidentify a
EFI_RUNTIME_SERVICES_DATAregion as not reserved if it does not have theEFI_MEMORY_RUNTIMEattribute set. However, it is perfectly legal for the firmware not to request a virtual mapping forEFI_RUNTIME_SERVICES_DATAregions that contain configuration tables, in which case theEFI_MEMORY_RUNTIMEattribute would not be set.Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/kernel/efi.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)arch/arm64/kernel/efi.c +10
-11@@ -125,17 +125,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 ) --
Quoted 2 lines
1.8.3.2
Looks good, as I expect most new types of memory that are added will need some special treatment, and shouldn't just
be added to the available general use memory.
PATCH v2 5/10 arm64/efi: drop redundant set_bit(EFI_CONFIG_TABLES)
In reply to Ard BiesheuvelThe EFI_CONFIG_TABLES bit already gets set by efi_config_init(), so there is no reason to set it again after this function returns successfully.
--- arch/arm64/kernel/efi.c | 2 -- 1 file changed, 2 deletions(-)
arch/arm64/kernel/efi.c +0 -2
@@ -112,8 +112,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));
Signature · 1 line
1.8.3.2
PATCH v2 6/10 efi: dmi: add support for SMBIOS 3.0 UEFI configuration table
In reply to Ard BiesheuvelThis adds support to the UEFI side for detecting the presence of a SMBIOS 3.0 64-bit entry point. This allows the actual SMBIOS structure table to reside at a physical offset over 4 GB, which cannot be supported by the legacy SMBIOS 32-bit entry point.
Since the firmware can legally provide both entry points, store the SMBIOS 3.0 entry point in a separate variable, and let the DMI decoding layer decide which one will be used.
--- drivers/firmware/efi/efi.c | 4 ++++ drivers/xen/efi.c | 1 + include/linux/efi.h | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-)
drivers/firmware/efi/efi.c +4 -0
@@ -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}, };
drivers/xen/efi.c +1 -0
@@ -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,
include/linux/efi.h +5 -1
@@ -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 */
Signature · 1 line
1.8.3.2
PATCH v2 6/10 efi: dmi: add support for SMBIOS 3.0 UEFI configuration table
Quoted 9 lines · Ard Biesheuvel
This adds support to the UEFI side for detecting the presence of a SMBIOS 3.0 64-bit entry point. This allows the actual SMBIOS structure table to reside at a physical offset over 4 GB, which cannot be supported by the legacy SMBIOS 32-bit entry point.
Since the firmware can legally provide both entry points, store the SMBIOS 3.0 entry point in a separate variable, and let the DMI decoding layer decide which one will be used.
Quoted 8 lines
Acked-by Leif Lindholm <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>--- drivers/firmware/efi/efi.c | 4 ++++ drivers/xen/efi.c | 1 + include/linux/efi.h | 6 +++++- 3 files changed, 10 insertions(+), 1 deletion(-)
Signature · 1 line
Matt Fleming, Intel Open Source Technology Center
PATCH v2 7/10 dmi: add support for SMBIOS 3.0 64-bit entry point
In reply to Ard BiesheuvelThe DMTF SMBIOS reference spec v3.0.0 defines a new 64-bit entry point, which enables support for SMBIOS structure tables residing at a physical offset over 4 GB. This is especially important for upcoming arm64 platforms whose system RAM resides entirely above the 4 GB boundary.
For the UEFI case, this code attempts to detect the new SMBIOS 3.0 header magic at the offset passed in the SMBIOS3_TABLE_GUID UEFI configuration table. If this configuration table is not provided, or if we fail to parse the header, we fall back to using the legacy SMBIOS_TABLE_GUID configuration table. This is in line with the spec, that allows both configuration tables to be provided, but mandates that they must point to the same structure table, unless the version pointed to by the 64-bit entry point is a superset of the 32-bit one.
For the non-UEFI case, the detection logic is modified to look for the SMBIOS 3.0 header magic before it looks for the legacy header magic.
Note that this patch is based on version 3.0.0d [draft] of the specification, which is expected not to deviate from the final version in ways that would affect the correctness of this implementation.
--- drivers/firmware/dmi_scan.c | 70 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-)
drivers/firmware/dmi_scan.c +68 -2
@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num,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 ==127 ) +break ; + +/* * We want to know the total length (formatted area and * strings) before decoding to make sure we won't run off the * table in dmi_decode or dmi_string
@@ -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;
@@ -514,12 +520,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 +618,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;
Signature · 1 line
1.8.3.2
PATCH v2 1/1 dmi: add support for SMBIOS 3.0 64-bit entry point
The DMTF SMBIOS reference spec v3.0.0 defines a new 64-bit entry point, which enables support for SMBIOS structure tables residing at a physical offset over 4 GB. This is especially important for upcoming arm64 platforms whose system RAM resides entirely above the 4 GB boundary.
For the UEFI case, this code attempts to detect the new SMBIOS 3.0 header magic at the offset passed in the SMBIOS3_TABLE_GUID UEFI configuration table. If this configuration table is not provided, or if we fail to parse the header, we fall back to using the legacy SMBIOS_TABLE_GUID configuration table. This is in line with the spec, that allows both configuration tables to be provided, but mandates that they must point to the same structure table, unless the version pointed to by the 64-bit entry point is a superset of the 32-bit one.
For the non-UEFI case, the detection logic is modified to look for the SMBIOS 3.0 header magic before it looks for the legacy header magic.
Note that this patch is based on version 3.0.0d [draft] of the specification, which is expected not to deviate from the final version in ways that would affect the correctness of this implementation.
---
v2: since dmi_base is now a phys_addr_t, prevent surprises caused by GCC's type
promotion rules by replacing the open coded shifts/ORs with get_unaligned_leXX()
--- drivers/firmware/dmi_scan.c | 79 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-)
drivers/firmware/dmi_scan.c +72 -7
@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num,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 ==127 ) +break ; + +/* * We want to know the total length (formatted area and * strings) before decoding to make sure we won't run off the * table in dmi_decode or dmi_string
@@ -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;
Signature · 1 line
1.8.3.2
PATCH v2 1/1 dmi: add support for SMBIOS 3.0 64-bit entry point
Quoted 17 lines · Ard Biesheuvel
The DMTF SMBIOS reference spec v3.0.0 defines a new 64-bit entry point, which enables support for SMBIOS structure tables residing at a physical offset over 4 GB. This is especially important for upcoming arm64 platforms whose system RAM resides entirely above the 4 GB boundary.
For the UEFI case, this code attempts to detect the new SMBIOS 3.0 header magic at the offset passed in the
SMBIOS3_TABLE_GUIDUEFI configuration table. If this configuration table is not provided, or if we fail to parse the header, we fall back to using the legacySMBIOS_TABLE_GUIDconfiguration table. This is in line with the spec, that allows both configuration tables to be provided, but mandates that they must point to the same structure table, unless the version pointed to by the 64-bit entry point is a superset of the 32-bit one.For the non-UEFI case, the detection logic is modified to look for the SMBIOS 3.0 header magic before it looks for the legacy header magic.
Quoted 6 lines
Note that this patch is based on version 3.0.0d [draft] of the specification, which is expected not to deviate from the final version in ways that would affect the correctness of this implementation.
Acked-by Leif Lindholm <[email protected]>
Also, for SMBIOS 2 on X64 Ovmf and FVP Base AEMv8-A (with UEFI),
Quoted 145 lines
Cc Andrew Morton <[email protected]>Cc Tony Luck <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>---
v2: sincedmi_baseis now aphys_addr_t, prevent surprises caused by GCC's type
promotion rules by replacing the open coded shifts/ORs withget_unaligned_leXX()--- drivers/firmware/dmi_scan.c | 79 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-)drivers/firmware/dmi_scan.c +72
-7@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num,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 ==127 ) +break ; + +/* * We want to know the total length (formatted area and * strings) before decoding to make sure we won't run off the * table in dmi_decode or dmi_string @@ -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;Signature · 1 line
1.8.3.2
PATCH v2 7/10 dmi: add support for SMBIOS 3.0 64-bit entry point
In reply to Ard BiesheuvelQuoted 5 lines · Ard Biesheuvel
drivers/firmware/dmi_scan.c +0
-0
drivers/firmware/dmi_scan.c static void dmi_table(u8 *buf, int len, int num, · line 101
Quoted 9 lines
drivers/firmware/dmi_scan.c +6
-0@@ -93,6 +93,12 @@ static void dmi_table(u8 *buf, int len, int num,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 ==127 ) +break ; + +/*
Hmm.. tiny nit, but s/127/DMI_ENTRY_END_OF_TABLE/ we already have a symbol for this constant.
But other than that,
Signature · 1 line
Matt Fleming, Intel Open Source Technology Center
PATCH v2 8/10 arm64: dmi: Add SMBIOS/DMI support
In reply to Ard BiesheuvelFrom: Yi Li <[email protected]>
SMBIOS is important for server hardware vendors. It implements a spec for providing descriptive information about the platform. Things like serial numbers, physical layout of the ports, build configuration data, and the like.
---
A short history of this patch:
v4: Moved call to dmi_scan_machine() to separate core_initcall(), so that it is
called unconditionally, i.e., even if UEFI fails to initialize. Otherwise, any drivers that attempt to consult DMI info for quirks handling start spewing errors, as Catalin unfortunately found out after merging (and subsequently reverting) this patch for the second time.
v3: Moved call to dmi_scan_machine() into arm64_enter_virtual_mode(). This is
necessary, because dmi_scan_machine() needs to be called before dmi_id_init(), which itself is invoked using an arch_initcall(). DMI depends on UEFI on arm64, so it is legal to only invoke dmi_scan_machine() when building with UEFI support. However, calling it from arm64_enter_virtual_mode() was a mistake, as it could result in dmi_scan_machine() not being called at all.
v2: Use efi_lookup_mapped_addr() to obtain the virtual address of the SMBIOS
structure table instead of calling ioremap_cache(). This seemed a good idea at the time, as the UEFI memory map covers those regions, so the virtual mapping should be known as well. However, this is only true if the firmware has requested a virtual remapping of the region by setting the EFI_MEMORY_RUNTIME bit, which Tianocore/EDK2 appears to do, but violates the UEFI spec. ("In general, UEFI Configuration Tables loaded at boot time (e.g., SMBIOS table) can be contained in memory of type EfiRuntimeServicesData (recommended and the system firmware must not request a virtual mapping), [...]", section 2.3.6, UEFI spec v2.4B). This version was merged into the arm64 for-next/core branch and reverted again per our request.
--- arch/arm64/Kconfig | 11 +++++++++++ arch/arm64/include/asm/dmi.h | 31 +++++++++++++++++++++++++++++++ arch/arm64/kernel/efi.c | 13 +++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 arch/arm64/include/asm/dmi.h
arch/arm64/Kconfig +11 -0
@@ -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"
arch/arm64/include/asm/dmi.h new file +31 -0
@@ -0,0 +1,31 @@ +/* +* arch/arm64/include/asm/dmi.h +* +* Copyright (C) 2013 Linaro Limited. +* Written by: Yi Li (yi.li at 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
arch/arm64/kernel/efi.c +13 -0
@@ -11,6 +11,7 @@* */ +#include <linux/dmi.h> #include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h>
@@ -469,3 +470,15 @@ 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 (); +return 0 ; +} +core_initcall (arm64_dmi_init);
Signature · 1 line
1.8.3.2
PATCH v2 8/10 arm64: dmi: Add SMBIOS/DMI support
Quoted 9 lines · Ard Biesheuvel
From: Yi Li <[email protected]>
SMBIOS is important for server hardware vendors. It implements a spec for providing descriptive information about the platform. Things like serial numbers, physical layout of the ports, build configuration data, and the like.
Signed-off-by Yi Li <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>
On FVP Base AEMv8-A (UEFI), and qemu (-kernel, so non-UEFI):
Quoted 126 lines
---
A short history of this patch:v4: Moved call to
dmi_scan_machine()to separatecore_initcall(), so that it is
called unconditionally, i.e., even if UEFI fails to initialize. Otherwise, any drivers that attempt to consult DMI info for quirks handling start spewing errors, as Catalin unfortunately found out after merging (and subsequently reverting) this patch for the second time.v3: Moved call to
dmi_scan_machine()intoarm64_enter_virtual_mode(). This is
necessary, becausedmi_scan_machine()needs to be called beforedmi_id_init(), which itself is invoked using anarch_initcall(). DMI depends on UEFI on arm64, so it is legal to only invokedmi_scan_machine()when building with UEFI support. However, calling it fromarm64_enter_virtual_mode()was a mistake, as it could result indmi_scan_machine()not being called at all.v2: Use
efi_lookup_mapped_addr()to obtain the virtual address of the SMBIOS
structure table instead of callingioremap_cache(). This seemed a good idea at the time, as the UEFI memory map covers those regions, so the virtual mapping should be known as well. However, this is only true if the firmware has requested a virtual remapping of the region by setting theEFI_MEMORY_RUNTIMEbit, which Tianocore/EDK2 appears to do, but violates the UEFI spec. ("In general, UEFI Configuration Tables loaded at boot time (e.g., SMBIOS table) can be contained in memory of type EfiRuntimeServicesData (recommended and the system firmware must not request a virtual mapping), [...]", section 2.3.6, UEFI spec v2.4B). This version was merged into the arm64 for-next/core branch and reverted again per our request.--- arch/arm64/Kconfig | 11 +++++++++++ arch/arm64/include/asm/dmi.h | 31 +++++++++++++++++++++++++++++++ arch/arm64/kernel/efi.c | 13 +++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 arch/arm64/include/asm/dmi.harch/arm64/Kconfig +11
-0@@ -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"arch/arm64/include/asm/dmi.h new file +31
-0@@ -0,0 +1,31 @@ +/* +* arch/arm64/include/asm/dmi.h +* +* Copyright (C) 2013 Linaro Limited. +* Written by: Yi Li (yi.li at 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 arch/arm64/kernel/efi.c +13
-0@@ -11,6 +11,7 @@* */ +#include <linux/dmi.h> #include <linux/efi.h> #include <linux/export.h> #include <linux/memblock.h> @@ -469,3 +470,15 @@ 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 (); +return 0 ; +} +core_initcall (arm64_dmi_init);Signature · 1 line
1.8.3.2
PATCH v2 9/10 arm64: dmi: set DMI string as dump stack arch description
In reply to Ard BiesheuvelThis sets the DMI string, containing system type, serial number, firmware version etc. as dump stack arch description, so that oopses and other kernel stack dumps automatically have this information included, if available.
--- arch/arm64/kernel/efi.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm64/kernel/efi.c +2 -0
@@ -479,6 +479,8 @@ static int __init arm64_dmi_init(void)* 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);
Signature · 1 line
1.8.3.2
PATCH v2 9/10 arm64: dmi: set DMI string as dump stack arch description
Quoted 25 lines · Ard Biesheuvel
This sets the DMI string, containing system type, serial number, firmware version etc. as dump stack arch description, so that oopses and other kernel stack dumps automatically have this information included, if available.
Signed-off-by Ard Biesheuvel <[email protected]>--- arch/arm64/kernel/efi.c | 2 ++ 1 file changed, 2 insertions(+)arch/arm64/kernel/efi.c +2
-0@@ -479,6 +479,8 @@ static int __init arm64_dmi_init(void)* 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);Signature · 1 line
1.8.3.2
Tested-by/Acked-by: Leif Lindholm <[email protected]>
PATCH v2 10/10 efi: efi-stub: notify on DTB absence
In reply to Ard BiesheuvelFrom: Mark Rutland <[email protected]>
In the absence of a DTB configuration table, the EFI stub will happily continue attempting to boot a kernel, despite the fact that this kernel may not function without a description of the hardware. In this case, as with a typo'd "dtb=" option (e.g. "dbt=") or many other possible failures, the only output seen by the user will be the rather terse output from the EFI stub:
EFI stub: Booting Linux Kernel...
To aid those attempting to debug such failures, this patch adds a notice when no DTB is found, making the output more helpful:
EFI stub: Booting Linux Kernel...
EFI stub: Generating empty DTB
Additionally, a positive acknowledgement is added when a user-specified DTB is in use:
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from command line
Similarly, a positive acknowledgement is added when a DTB from a configuration table is in use:
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
--- drivers/firmware/efi/libstub/arm-stub.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/firmware/efi/libstub/arm-stub.c +10 -1
@@ -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,
Signature · 1 line
1.8.3.2
PATCH v2 10/10 efi: efi-stub: notify on DTB absence
Quoted 36 lines · Ard Biesheuvel
From: Mark Rutland <[email protected]>
In the absence of a DTB configuration table, the EFI stub will happily continue attempting to boot a kernel, despite the fact that this kernel may not function without a description of the hardware. In this case, as with a typo'd "dtb=" option (e.g. "dbt=") or many other possible failures, the only output seen by the user will be the rather terse output from the EFI stub:
EFI stub: Booting Linux Kernel...
To aid those attempting to debug such failures, this patch adds a notice when no DTB is found, making the output more helpful:
EFI stub: Booting Linux Kernel...
EFI stub: Generating empty DTBAdditionally, a positive acknowledgement is added when a user-specified DTB is in use:
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from command lineSimilarly, a positive acknowledgement is added when a DTB from a configuration table is in use:
EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration tableSigned-off-by Mark Rutland <[email protected]>Acked-by Leif Lindholm <[email protected]>Acked-by Ard Biesheuvel <[email protected]>Cc Mark Salter <[email protected]>Cc Matt Fleming <[email protected]>Acked-by Roy Franz <[email protected]>Signed-off-by Ard Biesheuvel <[email protected]>
Quoted 3 lines
--- drivers/firmware/efi/libstub/arm-stub.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
Can't really argue with this.
Signature · 1 line
Matt Fleming, Intel Open Source Technology Center
v2 cover arm64 EFI patches for 3.19
In reply to Ard BiesheuvelQuoted 31 lines · Ard Biesheuvel
Version v2 of arm64/efi patches for 3.19.
Changes since previous version:
- dropped patch #6 'arm64/efi: use UEFI memory map unconditionally if available' (will be revisited later, but due to other changes in the pipeline regarding the virtual mapping of UEFI Runtime Services, it makes sense to defer this to 3.20)
- added patch #10 'efi: efi-stub: notify on DTB absence'Note that Matt Fleming has given his approval for taking all of these through the arm64 tree.
@Matt: may we have your ack on patches #6, #7 and #10 please? Patch #7 covers DMI not EFI but get_maintainer.pl is not very helpful here. (The patch is cc'ed to akpm and Tony Luck [ia64 maintainer])
Patches #1 - #3 are fixes for compliance with the UEFI and PE/COFF specs. No issues are known that require these patches, so there is no reason to pull them into a stable release.
Patch #4 fixes
is_reserve_region()to correctly identify UEFI memory regions that need to be reserved by the OS. This patch supersedes the patch sent as part of the v1 series: 'arm64/efi: reserve regions of typeACPI_MEMORY_NVS'Patch #5 removes a redundant
set_bit(EFI_CONFIG_TABLES)call.Patches #6 - #9 implement DMI/SMBIOS for arm64, both the existing 32-bit version and the upcoming 3.0 version that allows the SMBIOS structure table to reside at a physical offset that cannot be encoded in 32-bits. It also installs a 'Hardware name: xxx' string that is printed along with oopses and kernel call stack dumps on systems that implement DMI/SMBIOS.
Quoted 7 lines
Patch #10 is a patch from Mark Rutland I picked up that improves the diagnostic output of the EFI stub regarding the origin of the device tree blob.
Please refer to the patches themselves for version history. Acks and/or comments appreciated.
OK, it appears we're good to go with this series.
@Will: would you like me to repost one final time? Or would you prefer a pull request instead? The only changes are added acks and a single code change where an open-coded constant 127 is replaced with its symbolic name DMI_ENTRY_END_OF_TABLE.
Regards,
Ard.
v2 cover arm64 EFI patches for 3.19
Quoted 6 lines · Ard Biesheuvel
OK, it appears we're good to go with this series.
@Will: would you like me to repost one final time? Or would you prefer a pull request instead? The only changes are added acks and a single code change where an open-coded constant 127 is replaced with its symbolic name
DMI_ENTRY_END_OF_TABLE.
A pull request is fine, cheers.
Will