Skip to content

Commit 47a94c5

Browse files
Stuart Hayesandy-shev
authored andcommitted
platform/x86: dcdbas: Check SMBIOS for protected buffer address
Add support for a new method for BIOS to provide the address and length of the protected SMI communication buffer, via SMBIOS OEM strings. Signed-off-by: Stuart Hayes <[email protected]> Signed-off-by: Andy Shevchenko <[email protected]>
1 parent 30a44f7 commit 47a94c5

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

drivers/platform/x86/dcdbas.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/platform_device.h>
1616
#include <linux/acpi.h>
1717
#include <linux/dma-mapping.h>
18+
#include <linux/dmi.h>
1819
#include <linux/errno.h>
1920
#include <linux/cpu.h>
2021
#include <linux/gfp.h>
@@ -34,7 +35,7 @@
3435
#include "dcdbas.h"
3536

3637
#define DRIVER_NAME "dcdbas"
37-
#define DRIVER_VERSION "5.6.0-3.3"
38+
#define DRIVER_VERSION "5.6.0-3.4"
3839
#define DRIVER_DESCRIPTION "Dell Systems Management Base Driver"
3940

4041
static struct platform_device *dcdbas_pdev;
@@ -45,7 +46,7 @@ static unsigned long smi_data_buf_size;
4546
static unsigned long max_smi_data_buf_size = MAX_SMI_DATA_BUF_SIZE;
4647
static u32 smi_data_buf_phys_addr;
4748
static DEFINE_MUTEX(smi_data_lock);
48-
static u8 *eps_buffer;
49+
static u8 *bios_buffer;
4950

5051
static unsigned int host_control_action;
5152
static unsigned int host_control_smi_type;
@@ -518,8 +519,10 @@ static inline struct smm_eps_table *check_eps_table(u8 *addr)
518519

519520
static int dcdbas_check_wsmt(void)
520521
{
522+
const struct dmi_device *dev = NULL;
521523
struct acpi_table_wsmt *wsmt = NULL;
522524
struct smm_eps_table *eps = NULL;
525+
u64 bios_buf_paddr;
523526
u64 remap_size;
524527
u8 *addr;
525528

@@ -532,6 +535,17 @@ static int dcdbas_check_wsmt(void)
532535
!(wsmt->protection_flags & ACPI_WSMT_COMM_BUFFER_NESTED_PTR_PROTECTION))
533536
return 0;
534537

538+
/*
539+
* BIOS could provide the address/size of the protected buffer
540+
* in an SMBIOS string or in an EPS structure in 0xFxxxx.
541+
*/
542+
543+
/* Check SMBIOS for buffer address */
544+
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev)))
545+
if (sscanf(dev->name, "30[%16llx;%8llx]", &bios_buf_paddr,
546+
&remap_size) == 2)
547+
goto remap;
548+
535549
/* Scan for EPS (entry point structure) */
536550
for (addr = (u8 *)__va(0xf0000);
537551
addr < (u8 *)__va(0x100000 - sizeof(struct smm_eps_table));
@@ -542,34 +556,37 @@ static int dcdbas_check_wsmt(void)
542556
}
543557

544558
if (!eps) {
545-
dev_dbg(&dcdbas_pdev->dev, "found WSMT, but no EPS found\n");
559+
dev_dbg(&dcdbas_pdev->dev, "found WSMT, but no firmware buffer found\n");
546560
return -ENODEV;
547561
}
562+
bios_buf_paddr = eps->smm_comm_buff_addr;
563+
remap_size = eps->num_of_4k_pages * PAGE_SIZE;
548564

565+
remap:
549566
/*
550567
* Get physical address of buffer and map to virtual address.
551568
* Table gives size in 4K pages, regardless of actual system page size.
552569
*/
553-
if (upper_32_bits(eps->smm_comm_buff_addr + 8)) {
554-
dev_warn(&dcdbas_pdev->dev, "found WSMT, but EPS buffer address is above 4GB\n");
570+
if (upper_32_bits(bios_buf_paddr + 8)) {
571+
dev_warn(&dcdbas_pdev->dev, "found WSMT, but buffer address is above 4GB\n");
555572
return -EINVAL;
556573
}
557574
/*
558575
* Limit remap size to MAX_SMI_DATA_BUF_SIZE + 8 (since the first 8
559576
* bytes are used for a semaphore, not the data buffer itself).
560577
*/
561-
remap_size = eps->num_of_4k_pages * PAGE_SIZE;
562578
if (remap_size > MAX_SMI_DATA_BUF_SIZE + 8)
563579
remap_size = MAX_SMI_DATA_BUF_SIZE + 8;
564-
eps_buffer = memremap(eps->smm_comm_buff_addr, remap_size, MEMREMAP_WB);
565-
if (!eps_buffer) {
566-
dev_warn(&dcdbas_pdev->dev, "found WSMT, but failed to map EPS buffer\n");
580+
581+
bios_buffer = memremap(bios_buf_paddr, remap_size, MEMREMAP_WB);
582+
if (!bios_buffer) {
583+
dev_warn(&dcdbas_pdev->dev, "found WSMT, but failed to map buffer\n");
567584
return -ENOMEM;
568585
}
569586

570587
/* First 8 bytes is for a semaphore, not part of the smi_data_buf */
571-
smi_data_buf_phys_addr = eps->smm_comm_buff_addr + 8;
572-
smi_data_buf = eps_buffer + 8;
588+
smi_data_buf_phys_addr = bios_buf_paddr + 8;
589+
smi_data_buf = bios_buffer + 8;
573590
smi_data_buf_size = remap_size - 8;
574591
max_smi_data_buf_size = smi_data_buf_size;
575592
wsmt_enabled = true;
@@ -736,8 +753,8 @@ static void __exit dcdbas_exit(void)
736753
*/
737754
if (dcdbas_pdev)
738755
smi_data_buf_free();
739-
if (eps_buffer)
740-
memunmap(eps_buffer);
756+
if (bios_buffer)
757+
memunmap(bios_buffer);
741758
platform_device_unregister(dcdbas_pdev_reg);
742759
platform_driver_unregister(&dcdbas_driver);
743760
}

0 commit comments

Comments
 (0)