Skip to content

Commit 00b1248

Browse files
qzedandersson
authored andcommitted
firmware: qcom_scm: Add support for Qualcomm Secure Execution Environment SCM interface
Add support for SCM calls to Secure OS and the Secure Execution Environment (SEE) residing in the TrustZone (TZ) via the QSEECOM interface. This allows communication with Secure/TZ applications, for example 'uefisecapp' managing access to UEFI variables. For better separation, make qcom_scm spin up a dedicated child (platform) device in case QSEECOM support has been detected. The corresponding driver for this device is then responsible for managing any QSEECOM clients. Specifically, this driver attempts to automatically detect known and supported applications, creating a client (auxiliary) device for each one. The respective client/auxiliary driver is then responsible for managing and communicating with the application. While this patch introduces only a very basic interface without the more advanced features (such as re-entrant and blocking SCM calls and listeners/callbacks), this is enough to talk to the aforementioned 'uefisecapp'. Signed-off-by: Maximilian Luz <[email protected]> Reviewed-by: Johan Hovold <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent e4c89f9 commit 00b1248

File tree

7 files changed

+603
-0
lines changed

7 files changed

+603
-0
lines changed

MAINTAINERS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17800,6 +17800,12 @@ S: Maintained
1780017800
F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
1780117801
F: drivers/mtd/nand/raw/qcom_nandc.c
1780217802

17803+
QUALCOMM QSEECOM DRIVER
17804+
M: Maximilian Luz <[email protected]>
17805+
17806+
S: Maintained
17807+
F: drivers/firmware/qcom_qseecom.c
17808+
1780317809
QUALCOMM RMNET DRIVER
1780417810
M: Subash Abhinov Kasiviswanathan <[email protected]>
1780517811
M: Sean Tranchetti <[email protected]>

drivers/firmware/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,22 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
226226

227227
Say Y here to enable "download mode" by default.
228228

229+
config QCOM_QSEECOM
230+
bool "Qualcomm QSEECOM interface driver"
231+
depends on QCOM_SCM=y
232+
help
233+
Various Qualcomm SoCs have a Secure Execution Environment (SEE) running
234+
in the Trust Zone. This module provides an interface to that via the
235+
QSEECOM mechanism, using SCM calls.
236+
237+
The QSEECOM interface allows, among other things, access to applications
238+
running in the SEE. An example of such an application is 'uefisecapp',
239+
which is required to access UEFI variables on certain systems. If
240+
selected, the interface will also attempt to detect and register client
241+
devices for supported applications.
242+
243+
Select Y here to enable the QSEECOM interface driver.
244+
229245
config SYSFB
230246
bool
231247
select BOOT_VESA_SUPPORT

drivers/firmware/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
2020
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
2121
obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
2222
qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
23+
obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
2324
obj-$(CONFIG_SYSFB) += sysfb.o
2425
obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o
2526
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o

drivers/firmware/qcom_qseecom.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Driver for Qualcomm Secure Execution Environment (SEE) interface (QSEECOM).
4+
* Responsible for setting up and managing QSEECOM client devices.
5+
*
6+
* Copyright (C) 2023 Maximilian Luz <[email protected]>
7+
*/
8+
#include <linux/auxiliary_bus.h>
9+
#include <linux/module.h>
10+
#include <linux/platform_device.h>
11+
#include <linux/slab.h>
12+
#include <linux/types.h>
13+
14+
#include <linux/firmware/qcom/qcom_qseecom.h>
15+
#include <linux/firmware/qcom/qcom_scm.h>
16+
17+
struct qseecom_app_desc {
18+
const char *app_name;
19+
const char *dev_name;
20+
};
21+
22+
static void qseecom_client_release(struct device *dev)
23+
{
24+
struct qseecom_client *client;
25+
26+
client = container_of(dev, struct qseecom_client, aux_dev.dev);
27+
kfree(client);
28+
}
29+
30+
static void qseecom_client_remove(void *data)
31+
{
32+
struct qseecom_client *client = data;
33+
34+
auxiliary_device_delete(&client->aux_dev);
35+
auxiliary_device_uninit(&client->aux_dev);
36+
}
37+
38+
static int qseecom_client_register(struct platform_device *qseecom_dev,
39+
const struct qseecom_app_desc *desc)
40+
{
41+
struct qseecom_client *client;
42+
u32 app_id;
43+
int ret;
44+
45+
/* Try to find the app ID, skip device if not found */
46+
ret = qcom_scm_qseecom_app_get_id(desc->app_name, &app_id);
47+
if (ret)
48+
return ret == -ENOENT ? 0 : ret;
49+
50+
dev_info(&qseecom_dev->dev, "setting up client for %s\n", desc->app_name);
51+
52+
/* Allocate and set-up the client device */
53+
client = kzalloc(sizeof(*client), GFP_KERNEL);
54+
if (!client)
55+
return -ENOMEM;
56+
57+
client->aux_dev.name = desc->dev_name;
58+
client->aux_dev.dev.parent = &qseecom_dev->dev;
59+
client->aux_dev.dev.release = qseecom_client_release;
60+
client->app_id = app_id;
61+
62+
ret = auxiliary_device_init(&client->aux_dev);
63+
if (ret) {
64+
kfree(client);
65+
return ret;
66+
}
67+
68+
ret = auxiliary_device_add(&client->aux_dev);
69+
if (ret) {
70+
auxiliary_device_uninit(&client->aux_dev);
71+
return ret;
72+
}
73+
74+
ret = devm_add_action_or_reset(&qseecom_dev->dev, qseecom_client_remove, client);
75+
if (ret)
76+
return ret;
77+
78+
return 0;
79+
}
80+
81+
/*
82+
* List of supported applications. One client device will be created per entry,
83+
* assuming the app has already been loaded (usually by firmware bootloaders)
84+
* and its ID can be queried successfully.
85+
*/
86+
static const struct qseecom_app_desc qcom_qseecom_apps[] = {};
87+
88+
static int qcom_qseecom_probe(struct platform_device *qseecom_dev)
89+
{
90+
int ret;
91+
int i;
92+
93+
/* Set up client devices for each base application */
94+
for (i = 0; i < ARRAY_SIZE(qcom_qseecom_apps); i++) {
95+
ret = qseecom_client_register(qseecom_dev, &qcom_qseecom_apps[i]);
96+
if (ret)
97+
return ret;
98+
}
99+
100+
return 0;
101+
}
102+
103+
static struct platform_driver qcom_qseecom_driver = {
104+
.driver = {
105+
.name = "qcom_qseecom",
106+
},
107+
.probe = qcom_qseecom_probe,
108+
};
109+
110+
static int __init qcom_qseecom_init(void)
111+
{
112+
return platform_driver_register(&qcom_qseecom_driver);
113+
}
114+
subsys_initcall(qcom_qseecom_init);
115+
116+
MODULE_AUTHOR("Maximilian Luz <[email protected]>");
117+
MODULE_DESCRIPTION("Driver for the Qualcomm SEE (QSEECOM) interface");
118+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)