tee_dyn_shm_alloc_helper() derives nr_pages from a caller-supplied size
and passes it to alloc_pages_exact() without checking it. For size == 0
nr_pages is 0, and alloc_pages_exact(0) calls get_order(0), which is
documented as undefined and returns BITS_PER_LONG - PAGE_SHIFT. The page
allocator then trips its order > MAX_PAGE_ORDER warning and fails the
allocation; on a panic_on_warn kernel that ends the boot.
This can be triggered by TEE_IOC_SHM_ALLOC with struct
tee_ioctl_shm_alloc_data where size is 0.
Reject a zero page count, as register_shm_helper() already does for the
register path.
Fixes: cf4441503e20 ("tee: optee: Move pool_op helper functions")
Cc: stable(a)vger.kernel.org
Cc: lvc-project(a)linuxtesting.org
Signed-off-by: Georgiy Osokin <g.osokin(a)auroraos.dev>
---
drivers/tee/tee_shm.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 6742b3579..daa4af1e0 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -343,6 +343,10 @@ int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align,
unsigned int i;
int rc = 0;
+ /* get_order(0) is undefined and exceeds MAX_PAGE_ORDER. */
+ if (!nr_pages)
+ return -EINVAL;
+
/*
* Ignore alignment since this is already going to be page aligned
* and there's no need for any larger alignment.
base-commit: 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e
--
2.54.0
On Qualcomm SoC based platforms, UEFI stores EFI variables within the
Replay Protected Memory Block (RPMB) located within either the UFS,
eMMC or SPI-NOR storage. The RPMB key which is one-time programmed into
the storage controller to allow authentication of the RPMB frames is
generated by and only available to the Qualcomm Trusted Execution
Environment (QTEE). Thus, only QTEE can prepare the RPMB frames which
will be accepted by the storage controller.
The legacy QSEECOM protocol used for communicating with the QTEE is
deprecated and replaced with the use-case agnostic SMCInvoke protocol
starting with the Qualcomm SM8x50 series. On platforms where the QSEECOM
protocol still works (the QSEECOM driver probes) the driver does not
support a listener interface with QTEE to enable writing of non-volatile
EFI variables (via listener requests to Linux from QTEE) to the RPMB
for UFS and eMMC storage. (Qualcomm Compute platforms with SPI-NOR storage
are an exception to this and work with QSEECOM, see the NOTE below)
Therefore on such platforms, a TEE client driver (which communicates with
QTEE via the SMCInvoke protocol implemented by the QCOMTEE driver
registered with the TEE subsystem) must be used to update such EFI variables
through the RPMB service hosted in the QTEE supplicant user-space daemon
[1] which forwards RPMB packets to the RPMB device.
This series introduces such a uefisecapp TEE client driver for the
aforementioned Qualcomm platforms which installs efi-var operations _if_
the QCOMTEE driver registers support for an object-IPC based uefisecapp
service on the TEE bus during its probe. Only new QTEE firmware versions
available at [2] provide access to the uefisecapp service via the SMCInvoke
protocol.
Thus, QCOMTEE now maintains a static list of always-available object-IPC
based secure services exposed by QTEE. These services are implemented either
within the QTEE kernel or within a pre-loaded Trusted Application (TA)
usually loaded by the bootloader. The uefisecapp TA is an example of a
preloaded TA loaded by UEFI. A static list is required since QTEE does not
yet expose any way to dynamically query and enumerate the services exposed
by it.
To facilitate object-IPC interactions from the kernel-space, this
series also introduces a tee_client_object_invoke_func() to allow
invocation of TEE objects similar to the existing tee_client_invoke_func()
API exported by the TEE subsystem which allows invocation of TEE functions.
Some suporting changes are also introduced to track and handle operations
for TEE contexts opened from the kernel-space in the back-end QCOM-TEE
driver.
Finally and as previously mentioned, access to the object-IPC based uefisecapp
service is restricted on older QTEE firmware versions. A new QTEE firmware
release must be picked up from QArtifactory [2] for all upstream supported
Qualcomm SoCs to enable access to uefisecapp service via the TEE client
driver.
This patch series has been validated on Kodiak RB3Gen2 platform with UFS
storage by attempting to read/write EFI variables via the efivar tool [3]
after mounting the efivarfs filesystem. See [4] for an example.
NOTE: Since Compute platforms do not have a firmware running on their SPI-NOR
storage controller which must be programmed with a RPMB key, QTEE has a
SPI-NOR driver which holds the key, and so the QSEECOM driver can be used
for updating EFI variables on these platforms because QTEE never makes a
listener request to Linux (QTEE doesn't need the Linux SPI-NOR driver).
Such platforms are outlined in the following static list [5].
Merge Strategy:
This patch series could either be taken from the OP-TEE tree or the
QCOM soc tree. I would prefer it to be picked by the OP-TEE tree since
all except the uefisecapp TEE client driver patch in this series make
changes relevant to the TEE subsystem. It would be great if the QCOM soc
tree maintainers can Ack the uefisecapp driver patch.
[1] https://github.com/qualcomm/minkipc
[2] https://shorturl.at/zQU07
[3] https://github.com/rhboot/efivar
[4] https://docs.qualcomm.com/doc/80-70020-27/topic/manage_uefi_environment_var…
[5] https://elixir.bootlin.com/linux/v7.3-rc5/source/drivers/firmware/qcom/qcom…
Signed-off-by: Harshal Dev <harshal.dev(a)oss.qualcomm.com>
---
Changes in v3:
- Updated the cover letter and commit messages to highlight the following:
1. Only QTEE has the ability to prepare RPMB frames since it generates and
holds the RPMB key.
2. The QSEECOM protocol is deprecated on new platforms and so this series
migrates the uefisecapp to SMCInvoke which is a use-case agnostic, transport
focused and easier to maintain protocol.
- Use single if statement to update both flags and addr/uaddr.
- Remove redundant use of new error variable in qcomtee_get_qtee_feature_list().
- Minor fixes such as concise error prints and use of better error codes.
- Fix a double free in qtee_enumerate_service().
- Re-org the qcomtee_enumerate_services() function to re-use the same oic and
client_env object.
- Remove depends on !QCOM_QSEECOM_UEFISECAPP from Kconfig since both drivers
can co-exist even on platforms that support both QSEECOM and SMCInvoke protocols.
- Update the Kconfig description to better help the user understand when to enable
the TEE based uefisecapp driver.
- Removed qcom_tee_uefisecapp.h file and inline the header in qcom_tee_uefisecapp.c
- Rebased patch series onto the latest linux next tag: next-20260930.
- Link to v2: https://lore.kernel.org/r/20260722-qcom_uefisecapp_migrate_qcomtee-v2-0-b8a…
Changes in v2:
- Drop using MSB of the object_id to distingush kernel and user object invoke contexts.
- Introduce enum tee_object_invoke_origin to check the context of object invocation.
- Link to v1: https://lore.kernel.org/r/20260707-qcom_uefisecapp_migrate_qcomtee-v1-0-f65…
---
Amirreza Zarrabi (2):
tee: Add kernel client object invoke helper
tee: qcomtee: Allow object invokes from kernel clients
Harshal Dev (4):
tee: qcomtee: Track the object invocation context
tee: Export uuidv5 generation for TEE backends
tee: qcomtee: Add support for registering QTEE services on TEE bus
firmware: qcom: Add support for TEE based EFI-var client driver
MAINTAINERS | 6 +
arch/arm64/configs/defconfig | 1 +
drivers/firmware/qcom/Kconfig | 31 ++
drivers/firmware/qcom/Makefile | 1 +
drivers/firmware/qcom/qcom_tee_uefisecapp.c | 636 ++++++++++++++++++++++++++++
drivers/tee/qcomtee/call.c | 206 ++++++++-
drivers/tee/qcomtee/core.c | 9 +-
drivers/tee/qcomtee/qcomtee.h | 12 +
drivers/tee/qcomtee/qcomtee_msg.h | 1 +
drivers/tee/qcomtee/qcomtee_object.h | 16 +-
drivers/tee/tee_core.c | 24 +-
include/linux/tee_core.h | 23 +-
include/linux/tee_drv.h | 18 +-
13 files changed, 952 insertions(+), 32 deletions(-)
---
base-commit: 6c2cb8b8b843d216ab549b678a0d8831c43153e0
change-id: 20260408-qcom_uefisecapp_migrate_qcomtee-13869d45e014
Best regards,
--
Harshal Dev <harshal.dev(a)oss.qualcomm.com>
This series is a follow-up to the discussion that has started here [1].
When memory is lent to the Secure world via FF-A, CPU speculative
accesses from NS to the lent pages can still occur as long as it retains
a cacheable mapping to it.
Ideally, lent memory would be "no-map" but that would mean giving up
MiBs of useful memory, so let's try to do better with the help of a CMA
pool.
On arm64, modifying the direct map at runtime is generally restricted
because the linear map defaults to block mapping and splitting blocks at
runtime may trigger fatal page fault, unless the CPU implements BBML3
or the entire direct map was mapped at page granularity from boot.
Forcing last-level mappings system-wide incurs a severe penalty we want
to avoid. Instead, this series introduces targeted last-level mappings
for designated memory regions, along with the "arm,ffa-lend-pool" CMA
driver to manage unmapping and remapping on lend/reclaim transitions:
1. memblock:
- Introduce MEMBLOCK_PTEMAP to force PTE mappings only for a specific region.
2. set_memory infrastructure:
- Introduce can_set_direct_map_range() to check if a specific address
range is mapped with last-level entries and can be modified safely.
- Introduce __set_direct_map_*() variants that bypass redundant checks
when the caller has already validated the range.
3. "arm,ffa-lend-pool" driver
- Introduce the "arm,ffa-lend-pool" CMA reserved-memory driver, which
unmaps pages prior to lending (ffa_prepare_lend()) and restores them
when reclaimed (ffa_lend_reclaimed()).
4. Optee support
- Hook OP-TEE dynamic protected memory pools to "arm,ffa-lend-pool" for
both SMC (via DT memory-region phandle) and FF-A (via
ffa_lend_pool_attach()) transports.
Testing:
========
Tested with QEMU v8 using OP-TEE OS (built with CFG_CORE_DYN_PROTMEM=y)
under both SMC and FF-A transports [2]
static void dump_direct_map(const char *label)
{
printf("\n=== %s ===\n", label);
fflush(stdout);
system("sed -n '/Linear Mapping start/,/Linear Mapping end/p' /sys/kernel/debug/kernel_page_tables");
fflush(stdout);
}
int main(int argc, char *argv[])
{
int heap_fd;
int dmabuf_fd;
struct dma_heap_allocation_data data = { 0 };
size_t size = 1024 * 1024; /* 1MB */
if (argc > 1)
size = strtoul(argv[1], NULL, 0);
dump_direct_map("BEFORE ALLOCATION");
heap_fd = open("/dev/dma_heap/protected,secure-video", O_RDWR);
if (heap_fd < 0) {
perror("open /dev/dma_heap/protected,secure-video");
return 1;
}
printf("\nOpened /dev/dma_heap/protected,secure-video\n");
printf("Allocating %zu bytes of protected memory via DMA heap...\n", size);
data.len = size;
data.fd_flags = O_RDWR | O_CLOEXEC;
if (ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, &data) < 0) {
perror("ioctl DMA_HEAP_IOCTL_ALLOC");
close(heap_fd);
return 1;
}
dmabuf_fd = data.fd;
printf("Successfully allocated %zu bytes! dmabuf_fd = %d\n", size, dmabuf_fd);
dump_direct_map("DURING LEND (EXPECT HOLE IN DIRECT MAP)");
printf("\nReleasing dmabuf_fd...\n");
close(dmabuf_fd);
close(heap_fd);
dump_direct_map("AFTER RECLAIM (RESTORED DIRECT MAP)");
return 0;
}
[1] https://lore.kernel.org/all/20260807-tegra-vpr-v4-7-5510d16af89e@nvidia.com/
[2] https://optee.readthedocs.io/en/latest/building/gits/build.html#qemu-v8
Changelog:
v2:
- Rename MEMBLOCK_LLMAP to MEMBLOCK_PTEMAP (Mike)
- Warn on conflicting MEMBLOCK_NOMAP and MEMBLOCK_PTEMAP flags (Mike)
- Drop DT "ll-map" property and mark MEMBLOCK_PTEMAP from ffa_lend_pool_setup() (Rob, Thierry)
- Drop "reusable" and "no-map" property checks from ffa_lend_pool_setup() (Rob)
- dt-bindings: Document arm,ffa-lend-pool (Rob)
- Rework the Optee support with a separate ffa_lend_pool.c file.
- use walk_kernel_page_table_range_lockless() for
can_set_direct_map_range() to fix folded page table (Sashiko)
- Add missing TLB flush in ffa_prepare_lend()
- Disable hibernation
- Rebase on linux-next (next-20260918) to use the new set_direct_map*() ranges (Mike)
v1 (https://lore.kernel.org/all/20260902104712.2399797-1-vdonnefort@google.com/)
Vincent Donnefort (8):
memblock: Introduce MEMBLOCK_PTEMAP
arm64: Introduce can_set_direct_map_range()
arm64: Introduce __set_direct_map*()
arm64: Add support for MEMBLOCK_PTEMAP
firmware: arm_ffa: Introduce ffa-lend-pool
optee: Add support for arm,ffa-lend-pool
dt-bindings: reserved-memory: Add Arm FF-A lend pool
dt-bindings: firmware: optee: Add memory-region property
.../arm/firmware/linaro,optee-tz.yaml | 5 +
.../reserved-memory/arm,ffa-lend-pool.yaml | 55 ++++
arch/arm64/include/asm/set_memory.h | 7 +
arch/arm64/mm/mmu.c | 23 +-
arch/arm64/mm/pageattr.c | 72 ++++-
drivers/firmware/arm_ffa/Kconfig | 5 +
drivers/firmware/arm_ffa/Makefile | 1 +
drivers/firmware/arm_ffa/lend_pool.c | 261 ++++++++++++++++++
drivers/tee/optee/Makefile | 1 +
drivers/tee/optee/core.c | 6 +
drivers/tee/optee/ffa_abi.c | 13 +-
drivers/tee/optee/ffa_lend_pool.c | 72 +++++
drivers/tee/optee/optee_private.h | 4 +
drivers/tee/optee/protmem.c | 20 +-
drivers/tee/optee/smc_abi.c | 21 +-
include/linux/arm_ffa.h | 23 ++
include/linux/memblock.h | 18 ++
mm/memblock.c | 30 ++
18 files changed, 608 insertions(+), 29 deletions(-)
create mode 100644 Documentation/devicetree/bindings/reserved-memory/arm,ffa-lend-pool.yaml
create mode 100644 drivers/firmware/arm_ffa/lend_pool.c
create mode 100644 drivers/tee/optee/ffa_lend_pool.c
base-commit: 3f2425f5b5bbbdd991ca9cdfd5502e68d8895998
--
2.55.0.1082.g2b9226bbc0-goog
Hi Kuldeep,
A data point from retail hardware, in case it is useful for this
series: on an ASUS Zenbook A14 UX3407NA (Glymur, X2E-88-100, BIOS
UX3407NA.315) the TPM TA is not reachable as QTEE service 81, but it
is present as the QSEECOM application "qcom.tz.tpm".
With the qcomtee driver on a 7.3-rc3 based kernel, QTEE reports
version 5.2.0, and service discovery finds neither 81 (TPM) nor 413
(UEFI secure app). On the same boot, qseecom (version 0x1402000) works
and backs efivars through "qcom.tz.uefisecapp" (app id 7). An app-id
lookup for "qcom.tz.tpm" returns app id 1; a made-up name returns
-ENOENT.
The Windows driver for this machine agrees: QcTrEE8480.inf configures
the TPM service with AppName="qcom.tz.tpm", SecureApp=1, LoadApp=0
(preloaded by firmware). The EFI configuration table carries the
TPMEventLog and TPMFinalLog entries, so the firmware TPM is active.
Through that app, using a QSEECOM transport (based on Xilin Wu's
out-of-tree SC8280XP driver: QUERY_INFO_2 / SEND_COMMAND with a
CRB-style control area, here at 0x81d10000), /dev/tpm0 works: TPM 2.0,
manufacturer QCOM, vendor string "xCG fTPM", firmware 0x40000, real
PCR 0-7 values, GetRandom, ECC and RSA-2048 primaries, sign and
verify, and a sealed object that persists across reboots.
So, as far as I can tell, retail Glymur laptops may ship firmware on
which this driver finds no TPM, while the same TA is available over
QSEECOM.
The same applies to the prerequisite series that moves uefisecapp to
QCOMTEE [1]: on this firmware service 413 is absent and EFI variables
work only through the QSEECOM uefisecapp. If the QSEECOM path were
dropped for Glymur, efivars would stop working on this machine, so it
would be good to keep it as a fallback when the QTEE service is not
found.
Two questions:
- Is service 81 expected to appear on retail firmware through an
update, or is it specific to the CRD firmware?
- Would you consider a QSEECOM-based path for such firmware? I am
happy to test this series, or any other service UID you would like
checked, on this machine, and to share the transport code.
[1] https://lore.kernel.org/lkml/20260722-qcom_uefisecapp_migrate_qcomtee-v2-0-…
Thanks,
zeroknots
Assisted-by: LLM (analysis and drafting; the measurements were made on
the hardware and reviewed by me)
This RFC series adds the RISC-V RPMI TEE service group transport [1],
which provides RISC-V systems a mechanism for Linux to communicate
with TEE endpoints. Linux and a TEE act as endpoints of the RPMI TEE
service group, while the RPMI framework in machine-mode firmware
mediates communication between them over an SBI MPXY [2] mailbox
channel.
The series is layered as follows:
- Two mailbox patches add a direct synchronous send mode
(mbox_send_message_sync()) and its implementation for RPMI MPXY
channels, needed because RPMI TEE requests must complete
synchronously in the calling context.
- The RPMI TEE bus registers one device per discovered TEE endpoint
and service UUID pair, following the device-per-service model,
so individual service drivers can bind independently.
- The RPMI TEE transport core binds to the mailbox channel and
validates the RPMI and TEE service-group versions before any
discovery or service traffic is attempted.
- System-information parsing and discovery walk the firmware-provided
descriptor tables to find physical TEE endpoints and the services
they expose, registering a bus device for each.
- Memory parcel operations (lend, share, reclaim) let a consumer
driver share memory with a TEE endpoint. Linux creates a parcel and
the parcel identifier is then used by the consumer's own protocol to
refer to that memory.
- Signal buses let a consumer driver exchange asynchronous
notifications with its TEE endpoint in both directions.
This series only establishes the transport, bus, and discovery layer.
A consumer driver - an OP-TEE backend mapped onto these services,
analogous to drivers/tee/optee/ffa_abi.c — is intended to follow in a
later series once this transport is reviewed.
Feedback on the overall architecture, the bus/device model, and the
memory-parcel and signal-bus abstractions is especially welcome at
this stage in this RFC series.
[1] https://github.com/riscv-non-isa/riscv-rpmi/commits/main/src/srvgrp-tee.adoc
[2] https://github.com/riscv-non-isa/riscv-sbi-doc/releases
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi(a)oss.qualcomm.com>
---
Amirreza Zarrabi (10):
mailbox: add direct synchronous send support
mailbox: mpxy: add direct synchronous send
firmware: add RPMI TEE bus support
dt-bindings: firmware: add RISC-V RPMI TEE transport
firmware: add RPMI TEE transport core
firmware: riscv: rpmi-tee: parse system information tables
firmware: riscv: rpmi-tee: discover TEE services
firmware: riscv: rpmi-tee: cache TEE capabilities
firmware: riscv: rpmi-tee: add memory parcel operations
firmware: riscv: rpmi-tee: add signal bus support
.../bindings/firmware/riscv,rpmi-tee.yaml | 35 +
drivers/firmware/Kconfig | 2 +
drivers/firmware/Makefile | 1 +
drivers/firmware/riscv_rpmi_tee/Kconfig | 8 +
drivers/firmware/riscv_rpmi_tee/Makefile | 8 +
drivers/firmware/riscv_rpmi_tee/bus.c | 202 +++
drivers/firmware/riscv_rpmi_tee/driver.c | 1816 ++++++++++++++++++++
drivers/firmware/riscv_rpmi_tee/sysinfo.c | 385 +++++
drivers/firmware/riscv_rpmi_tee/sysinfo.h | 244 +++
drivers/mailbox/mailbox.c | 72 +-
drivers/mailbox/riscv-sbi-mpxy-mbox.c | 196 ++-
include/linux/mailbox/riscv-rpmi-message.h | 13 +
include/linux/mailbox_client.h | 3 +
include/linux/mailbox_controller.h | 10 +
include/linux/rpmi_tee.h | 175 ++
15 files changed, 3098 insertions(+), 72 deletions(-)
---
base-commit: 6375e61c01e93e35ee7acd336a689ac1fae4b509
change-id: 20260928-riscv-rpmi-tee-abi-603e9a3b4399
Best regards,
--
Amirreza Zarrabi <amirreza.zarrabi(a)oss.qualcomm.com>
Qualcomm platforms with a discrete TPM (dTPM) talked to it directly over
a non-secure SPI channel from the kernel. Arm's Base Boot Security
Requirements (BBSR) v1.4 require that access to go through TrustZone
instead, so on affected Qualcomm platforms the TPM 2.0 instance is now
fronted by a Trusted Application (TA) running inside Qualcomm's Trusted
Execution Environment (QTEE), which talks to the dTPM (or implements an
fTPM) on the kernel's behalf.
This series adds a kernel driver for that TA, built on the QCOMTEE
object-IPC transport (drivers/tee/qcomtee/) already used to reach other
QTEE services.
This patch series functionally depends on below(patch 5/6 specifically)
for qtee service discovery.
- https://lore.kernel.org/lkml/20260722-qcom_uefisecapp_migrate_qcomtee-v2-0-…
Tested on Glymur-crd target with tpm2-tools utility.
Validations:
- Get capabilities
- Random number generator
- RSA key creation, encryption and decryption.
Signed-off-by: Kuldeep Singh <kuldeep.singh(a)oss.qualcomm.com>
---
Changes in v2:
- Use QCOMTEE_TPM_UID as 81 for service discovery in patch 1.
- Use FIELD_GET, zero initialised array and log improvement (Konrad)
- Improve commit title and other fixes (Jarkko)
- Split MAINTAINERS entry as separate patch.
- Link to v1: https://patch.msgid.link/20260831-tpm_qcom_driver-v1-0-6f16fa6924fa@oss.qua…
To: Amirreza Zarrabi <amirreza.zarrabi(a)oss.qualcomm.com>
To: Jens Wiklander <jenswi(a)kernel.org>
To: Sumit Garg <sumit.garg(a)kernel.org>
To: Peter Huewe <peterhuewe(a)gmx.de>
To: Jarkko Sakkinen <jarkko(a)kernel.org>
To: Jason Gunthorpe <jgg(a)ziepe.ca>
To: Kuldeep Singh <kuldeep.singh(a)oss.qualcomm.com>
Cc: linux-arm-msm(a)vger.kernel.org
Cc: op-tee(a)lists.trustedfirmware.org
Cc: linux-kernel(a)vger.kernel.org
Cc: linux-integrity(a)vger.kernel.org
---
Kuldeep Singh (3):
tee: qcomtee: Register qcom.tz.tpm service for discovery
tpm: Introduce Qualcomm TPM driver
MAINTAINERS: Add Qualcomm TPM driver entry
MAINTAINERS | 7 +
drivers/char/tpm/Kconfig | 9 +
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/tpm_qcom.c | 354 ++++++++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm_qcom.h | 83 +++++++++
drivers/tee/qcomtee/call.c | 4 +-
drivers/tee/qcomtee/qcomtee_msg.h | 2 +
7 files changed, 459 insertions(+), 1 deletion(-)
---
base-commit: f3e6330d7fe42b204af05a2dbc68b379e0ad179e
change-id: 20260831-tpm_qcom_driver-d21c720e73b2
prerequisite-change-id: 20260408-qcom_uefisecapp_migrate_qcomtee-13869d45e014:v2
prerequisite-patch-id: 4dc81445c9baf36f420da8c2e2bed96e71b31a5b
prerequisite-patch-id: b487dfe2fbc076f4815dc6c73b9e68b0b78c961f
prerequisite-patch-id: c5df2b3696520a96f95b2d3535ed84cdc21cc315
prerequisite-patch-id: bbdd5327c15aeaa99ce9b74bab324a98f084ed48
prerequisite-patch-id: 07d9c4e9fe9fd61f60e3f35b30b9d81716f0734c
prerequisite-patch-id: 10ff88d87586f21f3cff3f72dbd21c27adbfbbcc
Best regards,
--
Kuldeep Singh <kuldeep.singh(a)oss.qualcomm.com>
On Qualcomm SoC based platforms, UEFI stores EFI variables within the
Replay Protected Memory Block (RPMB) which is only accessible by the
Qualcomm Trusted Execution Environment (QTEE).
For Qualcomm platforms without emulated RPMB support, specifically
platforms where RPMB is not located within SPI-NOR storage and instead
located on UFS/EMMC storage, non-volatile EFI variables can only be set via
a callback request from the UEFI Secure Application to the RPMB service
running in user-space (within the QTEE supplicant [1]).
Unlike the QCOM-TEE driver, the QSEECOM driver (used by the current
QSEECOM based uefisecapp) does not support callback requests. And on
certain Qualcomm platforms such as the RB3Gen2, attempts to access the
QSEECOM interface fail due to lack of support within Qualcomm TEE.
On these platforms, a TEE based uefisecapp client driver is required to:
1. Access cached & volatile EFI variables stored in uefisecapp's memory.
2. Ensure persistence of non-volatile EFI variables via writes through
the RPMB service hosted in the QTEE supplicant.
This series introduces such a uefisecapp TEE client driver for the
aforementioned Qualcomm platforms which installs efi-var operations _if_
the QCOMTEE driver registers support for an object-IPC based uefisecapp
service on the TEE bus during its probe. Only new QTEE firmware versions
available at [2] provide this support.
Thus, QCOMTEE now maintains a static list of always-available object-IPC
based secure services exposed by QTEE. These services are implemented either
within the QTEE kernel or within a pre-loaded Trusted Application (TA)
usually loaded by the bootloader. The uefisecapp TA is an example of a
preloaded TA loaded by UEFI. A static list is required since QTEE does not
yet expose any way to dynamically query and enumerate the services exposed by
it.
To facilitate object-IPC interactions from the kernel-space, this
series also introduces a tee_client_object_invoke_func() to allow
invocation of TEE objects similar to the existing tee_client_invoke_func()
API exported by the TEE subsystem which allows invocation of TEE functions.
Some suporting changes are also introduced to track and handle operations
for TEE contexts opened from the kernel-space in the back-end QCOM-TEE
driver.
Finally and as previously mentioned, access to the object-IPC based uefisecapp
service is restricted on older QTEE firmware versions. A new QTEE firmware
release must be picked up from QArtifactory [2] for all upstream supported
Qualcomm SoCs to enable access to uefisecapp service via the TEE client
driver.
This patch series has been validated on Kodiak RB3Gen2 platform with UFS
storage by attempting to read/write EFI variables via the efivar tool [3]
after mounting the efivarfs filesystem. See [4] for an example.
Merge Strategy:
This patch series could either be taken from the OP-TEE tree or the
QCOM soc tree. I would prefer it to be picked by the OP-TEE tree since
all except the uefisecapp TEE client driver patch in this series make
changes relevant to the TEE subsystem. It would be great if the QCOM soc
tree maintainers can Ack the uefisecapp driver patch.
[1] https://github.com/qualcomm/minkipc
[2] https://shorturl.at/zQU07
[3] https://github.com/rhboot/efivar
[4] https://docs.qualcomm.com/doc/80-70020-27/topic/manage_uefi_environment_var…
Signed-off-by: Harshal Dev <harshal.dev(a)oss.qualcomm.com>
---
Changes in v2:
- Drop using MSB of the object_id to distingush kernel and user object invoke contexts.
- Introduce enum tee_object_invoke_origin to check the context of object invocation.
- Link to v1: https://lore.kernel.org/r/20260707-qcom_uefisecapp_migrate_qcomtee-v1-0-f65…
---
Amirreza Zarrabi (2):
tee: Add kernel client object invoke helper
tee: qcomtee: Allow object invokes from kernel clients
Harshal Dev (4):
tee: qcomtee: Track the object invocation context
tee: Export uuidv5 generation for TEE backends
tee: qcomtee: Add support for registering QTEE services on TEE bus
firmware: qcom: Add support for TEE based EFI-var client driver
MAINTAINERS | 7 +
drivers/firmware/qcom/Kconfig | 24 ++
drivers/firmware/qcom/Makefile | 1 +
drivers/firmware/qcom/qcom_tee_uefisecapp.c | 525 ++++++++++++++++++++++++++++
drivers/firmware/qcom/qcom_tee_uefisecapp.h | 120 +++++++
drivers/tee/qcomtee/call.c | 205 ++++++++++-
drivers/tee/qcomtee/core.c | 9 +-
drivers/tee/qcomtee/qcomtee.h | 12 +
drivers/tee/qcomtee/qcomtee_msg.h | 1 +
drivers/tee/qcomtee/qcomtee_object.h | 16 +-
drivers/tee/tee_core.c | 24 +-
include/linux/tee_core.h | 23 +-
include/linux/tee_drv.h | 18 +-
13 files changed, 952 insertions(+), 33 deletions(-)
---
base-commit: f3e6330d7fe42b204af05a2dbc68b379e0ad179e
change-id: 20260408-qcom_uefisecapp_migrate_qcomtee-13869d45e014
Best regards,
--
Harshal Dev <harshal.dev(a)oss.qualcomm.com>
optee_probe() called tee_device_register() on both the client and the
supplicant device before the rest of struct optee had been initialized.
tee_device_register() calls cdev_device_add(), which does two things at
once: it creates /dev/tee0 and /dev/teepriv0, and it links the device
into the tee class so that class_find_device() can find it. From that
moment on the device is reachable both from user space via tee_open()
and from kernel space via tee_client_open_context(). The only gate in
teedev_open() is tee_device_get(), which merely checks that
teedev->desc is non-NULL, which was already set by tee_device_alloc().
Therefore, there is effectively no gate at all.
A context opened in that window can run against a struct optee where
- optee->call_queue.mutex is not initialized by optee_cq_init()
- optee->supp mutex and completions is not initialized by
optee_supp_init()
- optee->rpmb_dev_mutex is not initialized yet,
- the message argument cache is not initialized by
optee_shm_arg_cache_init()
- optee->ctx is still NULL
Any open session or invoke during this window takes uninitialized
mutexes and dereferences a NULL pointer.
Fix it by moving both tee_device_register() calls down to the point
where all of struct optee is set up.
Signed-off-by: Shao-Fu Chen <shf.chen(a)mediatek.com>
---
drivers/tee/optee/ffa_abi.c | 16 ++++++++--------
drivers/tee/optee/smc_abi.c | 17 ++++++++---------
2 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 633715b98625..d3cc7c5fc1e9 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -1123,14 +1123,6 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
optee_set_dev_group(optee);
- rc = tee_device_register(optee->teedev);
- if (rc)
- goto err_unreg_supp_teedev;
-
- rc = tee_device_register(optee->supp_teedev);
- if (rc)
- goto err_unreg_supp_teedev;
-
rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
if (rc)
goto err_unreg_supp_teedev;
@@ -1159,6 +1151,14 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
if (optee_ffa_protmem_pool_init(optee, sec_caps))
pr_info("Protected memory service not available\n");
+ rc = tee_device_register(optee->teedev);
+ if (rc)
+ goto err_unregister_devices;
+
+ rc = tee_device_register(optee->supp_teedev);
+ if (rc)
+ goto err_unregister_devices;
+
rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
if (rc)
goto err_unregister_devices;
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index b8a2bdac3208..51624443359b 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1849,14 +1849,6 @@ static int optee_probe(struct platform_device *pdev)
optee_set_dev_group(optee);
- rc = tee_device_register(optee->teedev);
- if (rc)
- goto err_unreg_supp_teedev;
-
- rc = tee_device_register(optee->supp_teedev);
- if (rc)
- goto err_unreg_supp_teedev;
-
optee_cq_init(&optee->call_queue, thread_count);
optee_supp_init(&optee->supp);
optee->smc.memremaped_shm = memremaped_shm;
@@ -1916,6 +1908,14 @@ static int optee_probe(struct platform_device *pdev)
if (optee->smc.sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
pr_info("dynamic shared memory is enabled\n");
+ rc = tee_device_register(optee->teedev);
+ if (rc)
+ goto err_disable_shm_cache;
+
+ rc = tee_device_register(optee->supp_teedev);
+ if (rc)
+ goto err_disable_shm_cache;
+
rc = optee_enumerate_devices(PTA_CMD_GET_DEVICES);
if (rc)
goto err_disable_shm_cache;
@@ -1942,7 +1942,6 @@ static int optee_probe(struct platform_device *pdev)
optee_shm_arg_cache_uninit(optee);
optee_supp_uninit(&optee->supp);
mutex_destroy(&optee->call_queue.mutex);
-err_unreg_supp_teedev:
tee_device_unregister(optee->supp_teedev);
err_unreg_teedev:
tee_device_unregister(optee->teedev);
--
2.45.2
From: Marouene Boubakri <marouene.boubakri(a)oss.nxp.com>
The OP-TEE driver reaches OP-TEE through the SMC ABI or the FF-A ABI,
both specific to Arm, yet builds both unconditionally together with the
SMC Calling Convention definitions they rely on: ffa_abi.c is always
compiled and only its registration is conditioned on
IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT), and optee_private.h includes
<linux/arm-smccc.h> and defines the SMC and FF-A specific types for
every file of the driver. This is fine as long as the driver depends on
HAVE_ARM_SMCCC, but it keeps the driver from being built for an
architecture without SMCCC, such as RISC-V.
Build smc_abi.c only when HAVE_ARM_SMCCC is set and ffa_abi.c only when
the FF-A transport is enabled, and provide stubs for their registration
otherwise, so that it fails with -EOPNOTSUPP as the FF-A ABI already
does when the FF-A transport is not reachable. Keep the SMCCC header,
the SMC invoke function type, the SMC and FF-A specific structures and
the SMC RPC register parameters in optee_private.h under the same
conditions, and drop the unused <linux/arm-smccc.h> include from
notif.c.
Make OPTEE depend on ARM_FFA_TRANSPORT || !ARM_FFA_TRANSPORT, as it
already does for RPMB, so that the driver is limited to a module when
the FF-A transport is one, rather than built in without FF-A support.
ffa_abi.c is thus built exactly when the FF-A transport is reachable
from the driver, and the IS_REACHABLE() checks in
optee_ffa_abi_register() and optee_ffa_abi_unregister() are always
true, so drop them.
OPTEE still depends on HAVE_ARM_SMCCC, so smc_abi.c is still always
built. The only visible change is that OPTEE=y can no longer be
combined with ARM_FFA_TRANSPORT=m: such a configuration now resolves to
OPTEE=m, with the FF-A ABI available.
Signed-off-by: Marouene Boubakri <marouene.boubakri(a)oss.nxp.com>
---
Changes in v4:
- Make OPTEE depend on ARM_FFA_TRANSPORT || !ARM_FFA_TRANSPORT so that
the driver is limited to =m when the FF-A transport is =m (Jens).
- Update the commit message accordingly.
v3: https://lore.kernel.org/all/20260922131735.524635-1-marouene.boubakri@oss.n…
Changes in v3:
- Dropped the RPMI ABI placeholder and the RISC-V enablement patches,
this is now a single patch (Jens).
- Key the FF-A parts of optee_private.h on IS_REACHABLE() instead of
IS_ENABLED(): with OPTEE=y and ARM_FFA_TRANSPORT=m kbuild drops
ffa_abi.o from the built-in optee.o while optee_ffa_abi_register()
was still declared, which does not link.
- Drop the now always true IS_REACHABLE() checks in
optee_ffa_abi_register() and optee_ffa_abi_unregister().
- Describe the current FF-A conditional compilation accurately in the
commit message.
- Posted as a new thread with a proper subject prefix.
v2: https://lore.kernel.org/op-tee/20260915020235.507302-2-marouene.boubakri@os…
Changes in v2:
- No code change, the testing section of the cover letter was completed.
v1: https://lore.kernel.org/op-tee/20260914175435.118303-2-marouene.boubakri@os…
drivers/tee/optee/Kconfig | 1 +
drivers/tee/optee/Makefile | 4 ++--
drivers/tee/optee/ffa_abi.c | 8 ++-----
drivers/tee/optee/notif.c | 1 -
drivers/tee/optee/optee_private.h | 39 ++++++++++++++++++++++++++++++-
5 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index 50d2051..891dac6 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -5,6 +5,7 @@ config OPTEE
depends on HAVE_ARM_SMCCC
depends on MMU
depends on RPMB || !RPMB
+ depends on ARM_FFA_TRANSPORT || !ARM_FFA_TRANSPORT
help
This implements the OP-TEE Trusted Execution Environment (TEE)
driver.
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index ad7049c..183cdde 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -7,8 +7,8 @@ optee-objs += rpc.o
optee-objs += protmem.o
optee-objs += supp.o
optee-objs += device.o
-optee-objs += smc_abi.o
-optee-objs += ffa_abi.o
+optee-$(CONFIG_HAVE_ARM_SMCCC) += smc_abi.o
+optee-$(CONFIG_ARM_FFA_TRANSPORT) += ffa_abi.o
# for tracing framework to find optee_trace.h
CFLAGS_smc_abi.o := -I$(src)
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 633715b..08236d8 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -1212,14 +1212,10 @@ static struct ffa_driver optee_ffa_driver = {
int optee_ffa_abi_register(void)
{
- if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
- return ffa_register(&optee_ffa_driver);
- else
- return -EOPNOTSUPP;
+ return ffa_register(&optee_ffa_driver);
}
void optee_ffa_abi_unregister(void)
{
- if (IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT))
- ffa_unregister(&optee_ffa_driver);
+ ffa_unregister(&optee_ffa_driver);
}
diff --git a/drivers/tee/optee/notif.c b/drivers/tee/optee/notif.c
index 6e85f2f..6801422 100644
--- a/drivers/tee/optee/notif.c
+++ b/drivers/tee/optee/notif.c
@@ -5,7 +5,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/arm-smccc.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index aefe1e6..02d6f79 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -6,7 +6,6 @@
#ifndef OPTEE_PRIVATE_H
#define OPTEE_PRIVATE_H
-#include <linux/arm-smccc.h>
#include <linux/notifier.h>
#include <linux/rhashtable.h>
#include <linux/rpmb.h>
@@ -15,6 +14,10 @@
#include <linux/types.h>
#include "optee_msg.h"
+#ifdef CONFIG_HAVE_ARM_SMCCC
+#include <linux/arm-smccc.h>
+#endif
+
#define DRIVER_NAME "optee"
#define OPTEE_MAX_ARG_SIZE 1024
@@ -42,10 +45,12 @@
*/
#define OPTEE_DEFAULT_MAX_NOTIF_VALUE 255
+#ifdef CONFIG_HAVE_ARM_SMCCC
typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long, unsigned long,
unsigned long, unsigned long,
struct arm_smccc_res *);
+#endif
/**
* struct optee_call_waiter - TEE entry may need to wait for a free TEE thread
@@ -119,6 +124,7 @@ struct optee_supp {
struct completion reqs_c;
};
+#ifdef CONFIG_HAVE_ARM_SMCCC
/**
* struct optee_pcpu - per cpu notif private struct passed to work functions
* @optee: optee device reference
@@ -149,7 +155,9 @@ struct optee_smc {
struct work_struct notif_pcpu_work;
unsigned int notif_cpuhp_state;
};
+#endif
+#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
/**
* struct optee_ffa - FFA communication struct
* @ffa_dev: FFA device, contains the destination id, the id of
@@ -170,6 +178,7 @@ struct optee_ffa {
struct workqueue_struct *notif_wq;
struct work_struct notif_work;
};
+#endif
struct optee;
@@ -257,8 +266,12 @@ struct optee {
const struct optee_ops *ops;
struct tee_context *ctx;
union {
+#ifdef CONFIG_HAVE_ARM_SMCCC
struct optee_smc smc;
+#endif
+#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
struct optee_ffa ffa;
+#endif
};
struct optee_shm_arg_cache shm_arg_cache;
struct optee_call_queue call_queue;
@@ -290,6 +303,7 @@ struct optee_context_data {
struct list_head sess_list;
};
+#ifdef CONFIG_HAVE_ARM_SMCCC
struct optee_rpc_param {
u32 a0;
u32 a1;
@@ -300,6 +314,7 @@ struct optee_rpc_param {
u32 a6;
u32 a7;
};
+#endif
/* Holds context that is preserved during one STD call */
struct optee_call_ctx {
@@ -422,9 +437,31 @@ static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
}
/* Registration of the ABIs */
+#ifdef CONFIG_HAVE_ARM_SMCCC
int optee_smc_abi_register(void);
void optee_smc_abi_unregister(void);
+#else
+static inline int optee_smc_abi_register(void)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void optee_smc_abi_unregister(void)
+{
+}
+#endif
+#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
int optee_ffa_abi_register(void);
void optee_ffa_abi_unregister(void);
+#else
+static inline int optee_ffa_abi_register(void)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void optee_ffa_abi_unregister(void)
+{
+}
+#endif
#endif /*OPTEE_PRIVATE_H*/
base-commit: 827751b699b79a6e569983359c02dce67f81b94c
--
2.43.0
[BCC all OP-TEE maintainers]
Hi OP-TEE maintainers & contributors,
OP-TEE version 4.11.0 is now scheduled for release on 2026-10-16. So,
now is a good time to start testing the master branch across various
platforms and report or fix any bugs.
The GitHub pull request for collecting Tested-by tags or any other
comments is https://github.com/OP-TEE/optee_os/pull/8054.
We will create the release candidate tag 4.11.0-rc1 next Friday, October 2.
You can find more information related to releases here:
https://optee.readthedocs.io/en/latest/general/releases.html
Thanks,
Jens