diff options
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/arm_scmi/driver.c | 4 | ||||
-rw-r--r-- | drivers/firmware/arm_scmi/smc.c | 42 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 2 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/arm64-stub.c | 4 | ||||
-rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 11 | ||||
-rw-r--r-- | drivers/firmware/google/coreboot_table.c | 5 | ||||
-rw-r--r-- | drivers/firmware/google/coreboot_table.h | 2 | ||||
-rw-r--r-- | drivers/firmware/google/framebuffer-coreboot.c | 4 | ||||
-rw-r--r-- | drivers/firmware/google/memconsole-coreboot.c | 4 | ||||
-rw-r--r-- | drivers/firmware/google/vpd.c | 4 | ||||
-rw-r--r-- | drivers/firmware/qcom_scm.c | 16 | ||||
-rw-r--r-- | drivers/firmware/smccc/smccc.c | 6 |
12 files changed, 80 insertions, 24 deletions
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 5392e1fc6b4e..cacdf1589b10 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -848,8 +848,6 @@ static int scmi_remove(struct platform_device *pdev) struct scmi_info *info = platform_get_drvdata(pdev); struct idr *idr = &info->tx_idr; - scmi_notification_exit(&info->handle); - mutex_lock(&scmi_list_mutex); if (info->users) ret = -EBUSY; @@ -860,6 +858,8 @@ static int scmi_remove(struct platform_device *pdev) if (ret) return ret; + scmi_notification_exit(&info->handle); + /* Safe to free channels since no more users */ ret = idr_for_each(idr, info->desc->ops->chan_free, idr); idr_destroy(&info->tx_idr); diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c index 82a82a5dc86a..fcbe2677f84b 100644 --- a/drivers/firmware/arm_scmi/smc.c +++ b/drivers/firmware/arm_scmi/smc.c @@ -9,9 +9,11 @@ #include <linux/arm-smccc.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/interrupt.h> #include <linux/mutex.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/slab.h> #include "common.h" @@ -23,6 +25,8 @@ * @shmem: Transmit/Receive shared memory area * @shmem_lock: Lock to protect access to Tx/Rx shared memory area * @func_id: smc/hvc call function id + * @irq: Optional; employed when platforms indicates msg completion by intr. + * @tx_complete: Optional, employed only when irq is valid. */ struct scmi_smc { @@ -30,8 +34,19 @@ struct scmi_smc { struct scmi_shared_mem __iomem *shmem; struct mutex shmem_lock; u32 func_id; + int irq; + struct completion tx_complete; }; +static irqreturn_t smc_msg_done_isr(int irq, void *data) +{ + struct scmi_smc *scmi_info = data; + + complete(&scmi_info->tx_complete); + + return IRQ_HANDLED; +} + static bool smc_chan_available(struct device *dev, int idx) { struct device_node *np = of_parse_phandle(dev->of_node, "shmem", 0); @@ -51,7 +66,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, struct resource res; struct device_node *np; u32 func_id; - int ret; + int ret, irq; if (!tx) return -ENODEV; @@ -79,6 +94,24 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev, if (ret < 0) return ret; + /* + * If there is an interrupt named "a2p", then the service and + * completion of a message is signaled by an interrupt rather than by + * the return of the SMC call. + */ + irq = of_irq_get_byname(cdev->of_node, "a2p"); + if (irq > 0) { + ret = devm_request_irq(dev, irq, smc_msg_done_isr, + IRQF_NO_SUSPEND, + dev_name(dev), scmi_info); + if (ret) { + dev_err(dev, "failed to setup SCMI smc irq\n"); + return ret; + } + init_completion(&scmi_info->tx_complete); + scmi_info->irq = irq; + } + scmi_info->func_id = func_id; scmi_info->cinfo = cinfo; mutex_init(&scmi_info->shmem_lock); @@ -110,7 +143,14 @@ static int smc_send_message(struct scmi_chan_info *cinfo, shmem_tx_prepare(scmi_info->shmem, xfer); + if (scmi_info->irq) + reinit_completion(&scmi_info->tx_complete); + arm_smccc_1_1_invoke(scmi_info->func_id, 0, 0, 0, 0, 0, 0, 0, &res); + + if (scmi_info->irq) + wait_for_completion(&scmi_info->tx_complete); + scmi_rx_callback(scmi_info->cinfo, shmem_read_header(scmi_info->shmem)); mutex_unlock(&scmi_info->shmem_lock); diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 8a94388e38b3..c23466e05e60 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -38,6 +38,8 @@ KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \ # remove SCS flags from all objects in this directory KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_SCS), $(KBUILD_CFLAGS)) +# disable LTO +KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO), $(KBUILD_CFLAGS)) GCOV_PROFILE := n # Sanitizer runtimes are unavailable and cannot be linked here. diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index 22ece1ad68a8..b69d63143e0d 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -61,10 +61,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, status = efi_get_random_bytes(sizeof(phys_seed), (u8 *)&phys_seed); if (status == EFI_NOT_FOUND) { - efi_info("EFI_RNG_PROTOCOL unavailable, KASLR will be disabled\n"); + efi_info("EFI_RNG_PROTOCOL unavailable\n"); efi_nokaslr = true; } else if (status != EFI_SUCCESS) { - efi_err("efi_get_random_bytes() failed (0x%lx), KASLR will be disabled\n", + efi_err("efi_get_random_bytes() failed (0x%lx)\n", status); efi_nokaslr = true; } diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index b50a6c67d9bd..cde0a2ef507d 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -672,7 +672,7 @@ typedef union efi_tcg2_protocol efi_tcg2_protocol_t; union efi_tcg2_protocol { struct { void *get_capability; - efi_status_t (__efiapi *get_event_log)(efi_handle_t, + efi_status_t (__efiapi *get_event_log)(efi_tcg2_protocol_t *, efi_tcg2_event_log_format, efi_physical_addr_t *, efi_physical_addr_t *, @@ -849,4 +849,13 @@ void efi_handle_post_ebs_state(void); enum efi_secureboot_mode efi_get_secureboot(void); +#ifdef CONFIG_RESET_ATTACK_MITIGATION +void efi_enable_reset_attack_mitigation(void); +#else +static inline void +efi_enable_reset_attack_mitigation(void) { } +#endif + +void efi_retrieve_tpm2_eventlog(void); + #endif diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index 0205987a4fd4..dc83ea118c67 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -46,14 +46,13 @@ static int coreboot_bus_probe(struct device *dev) static int coreboot_bus_remove(struct device *dev) { - int ret = 0; struct coreboot_device *device = CB_DEV(dev); struct coreboot_driver *driver = CB_DRV(dev->driver); if (driver->remove) - ret = driver->remove(device); + driver->remove(device); - return ret; + return 0; } static struct bus_type coreboot_bus_type = { diff --git a/drivers/firmware/google/coreboot_table.h b/drivers/firmware/google/coreboot_table.h index 7b7b4a6eedda..beb778674acd 100644 --- a/drivers/firmware/google/coreboot_table.h +++ b/drivers/firmware/google/coreboot_table.h @@ -72,7 +72,7 @@ struct coreboot_device { /* A driver for handling devices described in coreboot tables. */ struct coreboot_driver { int (*probe)(struct coreboot_device *); - int (*remove)(struct coreboot_device *); + void (*remove)(struct coreboot_device *); struct device_driver drv; u32 tag; }; diff --git a/drivers/firmware/google/framebuffer-coreboot.c b/drivers/firmware/google/framebuffer-coreboot.c index 916f26adc595..c6dcc1ef93ac 100644 --- a/drivers/firmware/google/framebuffer-coreboot.c +++ b/drivers/firmware/google/framebuffer-coreboot.c @@ -72,13 +72,11 @@ static int framebuffer_probe(struct coreboot_device *dev) return PTR_ERR_OR_ZERO(pdev); } -static int framebuffer_remove(struct coreboot_device *dev) +static void framebuffer_remove(struct coreboot_device *dev) { struct platform_device *pdev = dev_get_drvdata(&dev->dev); platform_device_unregister(pdev); - - return 0; } static struct coreboot_driver framebuffer_driver = { diff --git a/drivers/firmware/google/memconsole-coreboot.c b/drivers/firmware/google/memconsole-coreboot.c index d17e4d6ac9bc..74b5286518ee 100644 --- a/drivers/firmware/google/memconsole-coreboot.c +++ b/drivers/firmware/google/memconsole-coreboot.c @@ -91,11 +91,9 @@ static int memconsole_probe(struct coreboot_device *dev) return memconsole_sysfs_init(); } -static int memconsole_remove(struct coreboot_device *dev) +static void memconsole_remove(struct coreboot_device *dev) { memconsole_exit(); - - return 0; } static struct coreboot_driver memconsole_driver = { diff --git a/drivers/firmware/google/vpd.c b/drivers/firmware/google/vpd.c index d23c5c69ab52..ee6e08c0592b 100644 --- a/drivers/firmware/google/vpd.c +++ b/drivers/firmware/google/vpd.c @@ -298,14 +298,12 @@ static int vpd_probe(struct coreboot_device *dev) return 0; } -static int vpd_remove(struct coreboot_device *dev) +static void vpd_remove(struct coreboot_device *dev) { vpd_section_destroy(&ro_vpd); vpd_section_destroy(&rw_vpd); kobject_put(vpd_kobj); - - return 0; } static struct coreboot_driver vpd_driver = { diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c index 7be48c1bec96..f57779fc7ee9 100644 --- a/drivers/firmware/qcom_scm.c +++ b/drivers/firmware/qcom_scm.c @@ -965,8 +965,11 @@ EXPORT_SYMBOL(qcom_scm_ice_available); * qcom_scm_ice_invalidate_key() - Invalidate an inline encryption key * @index: the keyslot to invalidate * - * The UFSHCI standard defines a standard way to do this, but it doesn't work on - * these SoCs; only this SCM call does. + * The UFSHCI and eMMC standards define a standard way to do this, but it + * doesn't work on these SoCs; only this SCM call does. + * + * It is assumed that the SoC has only one ICE instance being used, as this SCM + * call doesn't specify which ICE instance the keyslot belongs to. * * Return: 0 on success; -errno on failure. */ @@ -995,10 +998,13 @@ EXPORT_SYMBOL(qcom_scm_ice_invalidate_key); * units, e.g. 1 = 512 bytes, 8 = 4096 bytes, etc. * * Program a key into a keyslot of Qualcomm ICE (Inline Crypto Engine), where it - * can then be used to encrypt/decrypt UFS I/O requests inline. + * can then be used to encrypt/decrypt UFS or eMMC I/O requests inline. + * + * The UFSHCI and eMMC standards define a standard way to do this, but it + * doesn't work on these SoCs; only this SCM call does. * - * The UFSHCI standard defines a standard way to do this, but it doesn't work on - * these SoCs; only this SCM call does. + * It is assumed that the SoC has only one ICE instance being used, as this SCM + * call doesn't specify which ICE instance the keyslot belongs to. * * Return: 0 on success; -errno on failure. */ diff --git a/drivers/firmware/smccc/smccc.c b/drivers/firmware/smccc/smccc.c index 00c88b809c0c..d52bfc5ed5e4 100644 --- a/drivers/firmware/smccc/smccc.c +++ b/drivers/firmware/smccc/smccc.c @@ -5,16 +5,22 @@ #define pr_fmt(fmt) "smccc: " fmt +#include <linux/cache.h> #include <linux/init.h> #include <linux/arm-smccc.h> +#include <asm/archrandom.h> static u32 smccc_version = ARM_SMCCC_VERSION_1_0; static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE; +bool __ro_after_init smccc_trng_available = false; + void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit) { smccc_version = version; smccc_conduit = conduit; + + smccc_trng_available = smccc_probe_trng(); } enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void) |