| From ca71e59446e970c1c5fc1b1d3634cd81a1a52896 Mon Sep 17 00:00:00 2001 |
| From: Jeffrey Kardatzke <jkardatzke@google.com> |
| Date: Wed, 11 Nov 2020 12:26:03 -0800 |
| Subject: [PATCH] Protected content patches |
| |
| Rebased onto 2.9.0 from upstream pull request: |
| https://github.com/intel/libva/pull/457 |
| |
| --- |
| doc/Makefile.am | 1 + |
| doc/meson.build | 1 + |
| va/Makefile.am | 2 + |
| va/meson.build | 2 + |
| va/va.c | 145 ++++++++++++++++ |
| va/va.h | 44 ++++- |
| va/va_backend.h | 9 +- |
| va/va_backend_prot.h | 88 ++++++++++ |
| va/va_prot.h | 404 +++++++++++++++++++++++++++++++++++++++++++ |
| va/va_str.c | 6 + |
| 10 files changed, 700 insertions(+), 2 deletions(-) |
| create mode 100644 va/va_backend_prot.h |
| create mode 100644 va/va_prot.h |
| |
| diff --git a/doc/Makefile.am b/doc/Makefile.am |
| index 85c012c..2ff3323 100644 |
| --- a/doc/Makefile.am |
| +++ b/doc/Makefile.am |
| @@ -44,6 +44,7 @@ VA_HEADER_FILES = \ |
| $(VA_HEADER_DIR)/va_dec_jpeg.h \ |
| $(VA_HEADER_DIR)/va_dec_vp8.h \ |
| $(VA_HEADER_DIR)/va_dec_vp9.h \ |
| + $(VA_HEADER_DIR)/va_prot.h \ |
| $(VA_HEADER_DIR)/va_vpp.h \ |
| $(NULL) |
| |
| diff --git a/doc/meson.build b/doc/meson.build |
| index 3c1b8f9..bc15e2b 100644 |
| --- a/doc/meson.build |
| +++ b/doc/meson.build |
| @@ -16,6 +16,7 @@ libva_headers_doc = [ |
| 'va_dec_jpeg.h', |
| 'va_dec_vp8.h', |
| 'va_dec_vp9.h', |
| + 'va_prot.h', |
| 'va_vpp.h' |
| ] |
| |
| diff --git a/va/Makefile.am b/va/Makefile.am |
| index e67c588..4a655e6 100644 |
| --- a/va/Makefile.am |
| +++ b/va/Makefile.am |
| @@ -40,6 +40,7 @@ libva_source_c = \ |
| libva_source_h = \ |
| va.h \ |
| va_backend.h \ |
| + va_backend_prot.h \ |
| va_backend_vpp.h \ |
| va_compat.h \ |
| va_dec_av1.h \ |
| @@ -61,6 +62,7 @@ libva_source_h = \ |
| va_str.h \ |
| va_tpi.h \ |
| va_version.h \ |
| + va_prot.h \ |
| va_vpp.h \ |
| $(NULL) |
| |
| diff --git a/va/meson.build b/va/meson.build |
| index 45707b6..dcf2220 100644 |
| --- a/va/meson.build |
| +++ b/va/meson.build |
| @@ -20,6 +20,7 @@ libva_sources = [ |
| libva_headers = [ |
| 'va.h', |
| 'va_backend.h', |
| + 'va_backend_prot.h', |
| 'va_backend_vpp.h', |
| 'va_compat.h', |
| 'va_dec_hevc.h', |
| @@ -40,6 +41,7 @@ libva_headers = [ |
| 'va_enc_vp9.h', |
| 'va_str.h', |
| 'va_tpi.h', |
| + 'va_prot.h', |
| 'va_vpp.h', |
| version_file, |
| ] |
| diff --git a/va/va.c b/va/va.c |
| index 4f06a34..15436e7 100644 |
| --- a/va/va.c |
| +++ b/va/va.c |
| @@ -26,6 +26,7 @@ |
| #include "sysdeps.h" |
| #include "va.h" |
| #include "va_backend.h" |
| +#include "va_backend_prot.h" |
| #include "va_backend_vpp.h" |
| #include "va_internal.h" |
| #include "va_trace.h" |
| @@ -495,6 +496,7 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name) |
| } else { |
| struct VADriverVTable *vtable = ctx->vtable; |
| struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp; |
| + struct VADriverVTableProt *vtable_prot = ctx->vtable_prot; |
| |
| vaStatus = VA_STATUS_SUCCESS; |
| if (!vtable) { |
| @@ -513,6 +515,15 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name) |
| } |
| ctx->vtable_vpp = vtable_vpp; |
| |
| + if (!vtable_prot) { |
| + vtable_prot = calloc(1, sizeof(*vtable_prot)); |
| + if (vtable_prot) |
| + vtable_prot->version = VA_DRIVER_VTABLE_PROT_VERSION; |
| + else |
| + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; |
| + } |
| + ctx->vtable_prot = vtable_prot; |
| + |
| if (init_func && VA_STATUS_SUCCESS == vaStatus) |
| vaStatus = (*init_func)(ctx); |
| |
| @@ -778,6 +789,8 @@ VAStatus vaTerminate ( |
| old_ctx->vtable = NULL; |
| free(old_ctx->vtable_vpp); |
| old_ctx->vtable_vpp = NULL; |
| + free(old_ctx->vtable_prot); |
| + old_ctx->vtable_prot = NULL; |
| |
| if (old_ctx->override_driver_name) { |
| free(old_ctx->override_driver_name); |
| @@ -2286,3 +2299,135 @@ vaQueryVideoProcPipelineCaps( |
| VA_TRACE_RET(dpy, status); |
| return status; |
| } |
| + |
| +/* Protection */ |
| +#define VA_PROT_INIT_CONTEXT(ctx, dpy) do { \ |
| + CHECK_DISPLAY(dpy); \ |
| + ctx = CTX(dpy); \ |
| + if (!ctx) \ |
| + return VA_STATUS_ERROR_INVALID_DISPLAY; \ |
| + } while (0) |
| + |
| +#define VA_PROT_INVOKE(dpy, func, args) do { \ |
| + if (!ctx->vtable_prot->va##func) \ |
| + return VA_STATUS_ERROR_UNIMPLEMENTED; \ |
| + status = ctx->vtable_prot->va##func args; \ |
| + } while (0) |
| + |
| +VAStatus vaCreateProtectedSession( |
| + VADisplay dpy, |
| + VAConfigID config_id, |
| + VAProtectedSessionID *protected_session |
| +) |
| +{ |
| + VADriverContextP ctx; |
| + VAStatus status; |
| + |
| + VA_PROT_INIT_CONTEXT(ctx, dpy); |
| + VA_PROT_INVOKE( |
| + ctx, |
| + CreateProtectedSession, |
| + (ctx, config_id, protected_session) |
| + ); |
| + VA_TRACE_RET(dpy, status); |
| + |
| + return status; |
| +} |
| + |
| +VAStatus vaDestroyProtectedSession( |
| + VADisplay dpy, |
| + VAProtectedSessionID protected_session |
| +) |
| +{ |
| + VADriverContextP ctx; |
| + VAStatus status; |
| + |
| + VA_PROT_INIT_CONTEXT(ctx, dpy); |
| + VA_PROT_INVOKE( |
| + ctx, |
| + DestroyProtectedSession, |
| + (ctx, protected_session) |
| + ); |
| + VA_TRACE_RET(dpy, status); |
| + |
| + return status; |
| +} |
| + |
| +VAStatus vaAttachProtectedSession( |
| + VADisplay dpy, |
| + VAContextID context, |
| + VAProtectedSessionID protected_session |
| +) |
| +{ |
| + VADriverContextP ctx; |
| + VAStatus status; |
| + |
| + VA_PROT_INIT_CONTEXT(ctx, dpy); |
| + VA_PROT_INVOKE( |
| + ctx, |
| + AttachProtectedSession, |
| + (ctx, context, protected_session) |
| + ); |
| + VA_TRACE_RET(dpy, status); |
| + |
| + return status; |
| +} |
| + |
| +VAStatus vaDetachProtectedSession( |
| + VADisplay dpy, |
| + VAContextID context |
| +) |
| +{ |
| + VADriverContextP ctx; |
| + VAStatus status; |
| + |
| + VA_PROT_INIT_CONTEXT(ctx, dpy); |
| + VA_PROT_INVOKE( |
| + ctx, |
| + DetachProtectedSession, |
| + (ctx, context) |
| + ); |
| + VA_TRACE_RET(dpy, status); |
| + |
| + return status; |
| +} |
| + |
| +VAStatus vaProtectedSessionExecute( |
| + VADisplay dpy, |
| + VAProtectedSessionID protected_session, |
| + VABufferID data |
| +) |
| +{ |
| + VADriverContextP ctx; |
| + VAStatus status; |
| + |
| + VA_PROT_INIT_CONTEXT(ctx, dpy); |
| + VA_PROT_INVOKE( |
| + ctx, |
| + ProtectedSessionExecute, |
| + (ctx, protected_session, data) |
| + ); |
| + VA_TRACE_RET(dpy, status); |
| + |
| + return status; |
| +} |
| + |
| +VAStatus vaProtectedSessionHwUpdate( |
| + VADisplay dpy, |
| + VAProtectedSessionID protected_session, |
| + VABufferID data |
| +) |
| +{ |
| + VADriverContextP ctx; |
| + VAStatus status; |
| + |
| + VA_PROT_INIT_CONTEXT(ctx, dpy); |
| + VA_PROT_INVOKE( |
| + ctx, |
| + ProtectedSessionHwUpdate, |
| + (ctx, protected_session, data) |
| + ); |
| + VA_TRACE_RET(dpy, status); |
| + |
| + return status; |
| +} |
| diff --git a/va/va.h b/va/va.h |
| index 6577cf5..2525dec 100644 |
| --- a/va/va.h |
| +++ b/va/va.h |
| @@ -126,6 +126,7 @@ extern "C" { |
| * - \ref api_dec_vp9 |
| * - \ref api_dec_av1 |
| * - \ref api_vpp |
| + * - \ref api_prot |
| * - FEI (H264, HEVC) |
| * - \ref api_fei |
| * - \ref api_fei_h264 |
| @@ -405,7 +406,8 @@ typedef enum |
| VAProfileHEVCSccMain444 = 31, |
| VAProfileAV1Profile0 = 32, |
| VAProfileAV1Profile1 = 33, |
| - VAProfileHEVCSccMain444_10 = 34 |
| + VAProfileHEVCSccMain444_10 = 34, |
| + VAProfileProtected = 35 |
| } VAProfile; |
| |
| /** |
| @@ -464,6 +466,21 @@ typedef enum |
| * and VAStatsMVBufferType) are needed for this entry point. |
| **/ |
| VAEntrypointStats = 12, |
| + /** |
| + * \brief VAEntrypointProtectedTEEComm |
| + * |
| + * A function for communicating with TEE (Trusted Execution Environment) directly if application does not |
| + * want to operate on protected display link. |
| + * |
| + **/ |
| + VAEntrypointProtectedTEEComm = 13, |
| + /** |
| + * \brief VAEntrypointProtectedDisplayLink |
| + * |
| + * A display link protection function for establishing protected display link. |
| + * |
| + **/ |
| + VAEntrypointProtectedDisplayLink = 14 |
| } VAEntrypoint; |
| |
| /** Currently defined configuration attribute types */ |
| @@ -794,6 +811,13 @@ typedef enum |
| * attribute value is \c VAConfigAttribValContextPriority |
| */ |
| VAConfigAttribContextPriority = 41, |
| + /** |
| + * \brief TEE firmware version. Read-only |
| + * This attribute is for TEE firmware version. The value will be an integer. |
| + * [31-16] Major version, [15-0] Minor version. |
| + **/ |
| + VAConfigAttribProtectedTeeFwVersion = 42, |
| + |
| /**@}*/ |
| VAConfigAttribTypeMax |
| } VAConfigAttribType; |
| @@ -1776,6 +1800,22 @@ typedef enum |
| */ |
| VASubsetsParameterBufferType = 57, |
| |
| + /** |
| + * \brief Protected session execution buffer type |
| + * |
| + * It's for TEE execution usage (vaProtectedSessionExecute()). The buffer structure is in |
| + * \c VAProtectedSessionExecuteBuffer |
| + */ |
| + VAProtectedSessionExecuteBufferType = 58, |
| + |
| + /** |
| + * \brief Update protected session status buffer type |
| + * |
| + * The buffer allows the driver to update IHV specific hardware status of the protected session. |
| + * The buffer structure is in \c VAProtectedSessionHwUpdateBuffer |
| + */ |
| + VAProtectedSessionHwUpdateBufferType = 59, |
| + |
| VABufferTypeMax |
| } VABufferType; |
| |
| @@ -2547,6 +2587,7 @@ typedef struct _VAEncMiscParameterCustomRoundingControl |
| uint32_t value; |
| } rounding_offset_setting; |
| } VAEncMiscParameterCustomRoundingControl; |
| + |
| /** |
| * There will be cases where the bitstream buffer will not have enough room to hold |
| * the data for the entire slice, and the following flags will be used in the slice |
| @@ -4757,6 +4798,7 @@ typedef struct _VAPictureHEVC |
| #include <va/va_fei.h> |
| #include <va/va_fei_h264.h> |
| #include <va/va_vpp.h> |
| +#include <va/va_prot.h> |
| |
| /**@}*/ |
| |
| diff --git a/va/va_backend.h b/va/va_backend.h |
| index 5ab8f6a..eda1de0 100644 |
| --- a/va/va_backend.h |
| +++ b/va/va_backend.h |
| @@ -631,7 +631,14 @@ struct VADriverContext |
| void (*info_callback)(VADriverContextP pDriverContext, |
| const char *message); |
| |
| - unsigned long reserved[38]; /* reserve for future add-ins, decrease the subscript accordingly */ |
| + /** |
| + * \brief The VA/Protected implementation hooks. |
| + * |
| + * This structure is allocated from libva with calloc(). |
| + */ |
| + struct VADriverVTableProt *vtable_prot; |
| + |
| + unsigned long reserved[37]; /* reserve for future add-ins, decrease the subscript accordingly */ |
| }; |
| |
| #define VA_DISPLAY_MAGIC 0x56414430 /* VAD0 */ |
| diff --git a/va/va_backend_prot.h b/va/va_backend_prot.h |
| new file mode 100644 |
| index 0000000..b89a1b7 |
| --- /dev/null |
| +++ b/va/va_backend_prot.h |
| @@ -0,0 +1,88 @@ |
| +/* |
| + * Copyright (c) 2020 Intel Corporation. All Rights Reserved. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a |
| + * copy of this software and associated documentation files (the |
| + * "Software"), to deal in the Software without restriction, including |
| + * without limitation the rights to use, copy, modify, merge, publish, |
| + * distribute, sub license, and/or sell copies of the Software, and to |
| + * permit persons to whom the Software is furnished to do so, subject to |
| + * the following conditions: |
| + * |
| + * The above copyright notice and this permission notice (including the |
| + * next paragraph) shall be included in all copies or substantial portions |
| + * of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| + * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR |
| + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| + */ |
| + |
| +#ifndef VA_BACKEND_PROT_H |
| +#define VA_BACKEND_PROT_H |
| + |
| +#include <va/va_prot.h> |
| + |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| +/** \brief VTable version for VA/PROTECTION hooks. */ |
| +#define VA_DRIVER_VTABLE_PROT_VERSION 1 |
| + |
| +struct VADriverVTableProt { |
| + unsigned int version; |
| + |
| + VAStatus |
| + (*vaCreateProtectedSession)( |
| + VADriverContextP ctx, |
| + VAConfigID config_id, |
| + VAProtectedSessionID *protected_session |
| + ); |
| + |
| + VAStatus |
| + (*vaDestroyProtectedSession)( |
| + VADriverContextP ctx, |
| + VAProtectedSessionID protected_session |
| + ); |
| + |
| + VAStatus |
| + (*vaAttachProtectedSession)( |
| + VADriverContextP ctx, |
| + VAContextID context, |
| + VAProtectedSessionID protected_session |
| + ); |
| + |
| + VAStatus |
| + (*vaDetachProtectedSession)( |
| + VADriverContextP ctx, |
| + VAContextID context |
| + ); |
| + |
| + VAStatus |
| + (*vaProtectedSessionExecute)( |
| + VADriverContextP ctx, |
| + VAProtectedSessionID protected_session, |
| + VABufferID buf_id |
| + ); |
| + |
| + VAStatus |
| + (*vaProtectedSessionHwUpdate)( |
| + VADriverContextP ctx, |
| + VAProtectedSessionID protected_session, |
| + VABufferID buf_id |
| + ); |
| + |
| + /** \brief Reserved bytes for future use, must be zero */ |
| + unsigned long reserved[VA_PADDING_MEDIUM]; |
| +}; |
| + |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| + |
| +#endif /* VA_BACKEND_PROT_H */ |
| diff --git a/va/va_prot.h b/va/va_prot.h |
| new file mode 100644 |
| index 0000000..c53ce25 |
| --- /dev/null |
| +++ b/va/va_prot.h |
| @@ -0,0 +1,404 @@ |
| +/* |
| + * Copyright (c) 2020 Intel Corporation. All Rights Reserved. |
| + * |
| + * Permission is hereby granted, free of charge, to any person obtaining a |
| + * copy of this software and associated documentation files (the |
| + * "Software"), to deal in the Software without restriction, including |
| + * without limitation the rights to use, copy, modify, merge, publish, |
| + * distribute, sub license, and/or sell copies of the Software, and to |
| + * permit persons to whom the Software is furnished to do so, subject to |
| + * the following conditions: |
| + * |
| + * The above copyright notice and this permission notice (including the |
| + * next paragraph) shall be included in all copies or substantial portions |
| + * of the Software. |
| + * |
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
| + * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR |
| + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
| + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
| + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| + */ |
| + |
| +/** |
| + * \file va_prot.h |
| + * \brief Protected Session API. |
| + * |
| + * This file contains the \ref api_prot "Protected Session API". |
| + */ |
| + |
| +#ifndef VA_PROT_H |
| +#define VA_PROT_H |
| + |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| +/** |
| + * \defgroup api_prot Protected Session API |
| + * |
| + * @{ |
| + * |
| + * The Protected Session API. uses the following paradigm: |
| + * - \ref api_prot_caps |
| + * - \ref api_prot_create |
| + * - \ref api_prot_exec |
| + * - \ref api_prot_update |
| + * - \ref api_prot_attach |
| + * |
| + * \section api_prot_caps Query for capabilities of the protected session |
| + * |
| + * Checking whether specific protected session is supported or not via |
| + * performing with vaQueryConfigEntrypoints() and the profile argument set to |
| + * #VAProfileProtected. If the protected display link is supported, then the |
| + * list of returned entry-points will include #VAEntrypointProtectedDisplayLink. |
| + * If the protected TEE session is supported, then #VAEntrypointProtectedTEEComm |
| + * will be included. |
| + * |
| + * \code |
| + * VAEntrypoint *entrypoints; |
| + * int i, max_num_entrypoints, supportsProtectedDisplayLink = 0; |
| + * |
| + * max_num_entrypoints = vaMaxNumEntrypoints(); |
| + * entrypoints = malloc(max_num_entrypoints * sizeof(entrypoints[0]); |
| + * vaQueryConfigEntrypoints(va_dpy, VAProfileProtected, entrypoints, |
| + * &num_entrypoints); |
| + * |
| + * for (i = 0; i < max_num_entrypoints; i++) { |
| + * if (entrypoints[i] == VAEntrypointProtectedDisplayLink) { |
| + * supportsProtectedDisplayLink = 1; |
| + * break; |
| + * } |
| + * } |
| + * \endcode |
| + * |
| + * After that, vaGetConfigAttributes() function is used to query the protected |
| + * session capabilities. |
| + * |
| + * \code |
| + * VAConfigAttrib attrib_prot[2]; |
| + * VAConfigAttribValProtectedDisplayLink wired; |
| + * VAConfigAttribValProtectedDisplayLink wireless |
| + * attrib_prot[0].type = VAConfigAttribDisplayLinkHdcpWired; |
| + * attrib_prot[1].type = VAConfigAttribDisplayLinkHdcpWireless; |
| + * vaGetConfigAttributes(va_dpy, VAProfileProtected, VAEntrypointProtectedDisplayLink, attrib_prot, 2); |
| + * wired = attrib_prot[0].value; |
| + * VAConfigAttribDisplayLinkHdcpWireless = attrib_prot[0].value; |
| + * if ((wired.bits.session_type & VA_PROTECTED_DISPLAY_LINK_SESSION_TYPE0) == 0) { |
| + * // not find desired mode |
| + * assert(0); |
| + * } |
| + * \endcode |
| + * |
| + * \section api_prot_create Create a protected session |
| + * |
| + * A protected session is a session between application and GPU hardware. |
| + * This protected session can be attached to the display. Also with protected session, |
| + * application can do specific TEE execution functionality with TEE inside GPU, but it depends |
| + * on IHV's implementation. |
| + * Before creating a protected session, it needs to create a config first via |
| + * vaCreateConfig(). Then using this config id to create a protected session via |
| + * vaCreateProtectedSession(). |
| + * |
| + * The general control flow is demonstrated by the following pseudo-code: |
| + * \code |
| + * // Create config |
| + * VAConfigID config_id; |
| + * |
| + * wired.bits.session_type = VA_PROTECTED_DISPLAY_LINK_SESSION_TYPE0; |
| + * wired.bits.protocol_version = VA_PROTECTED_DISPLAY_LINK_HDCP_VERSION_22; |
| + * attrib_prot[0].value = wired.value; |
| + * va_status = vaCreateConfig(va_dpy, VAProfileProtected, VAEntrypointProtectedDisplayLink, attrib_prot, 1, &config_id); |
| + * CHECK_VASTATUS(va_status, "vaCreateConfig"); |
| + * \endcode |
| + * |
| + * Once the config is set up, we can create protected session via vaCreateProtectedSession(). |
| + * \code |
| + * // Create a protected session |
| + * VAProtectedSessionID protected_session; |
| + * |
| + * va_status = vaCreateProtectedSession( |
| + * va_dpy, |
| + * config_id, |
| + * &protected_session); |
| + * CHECK_VASTATUS(va_status, "vaCreateProtectedSession"); |
| + * \endcode |
| + * |
| + * \section api_prot_exec TEE communication via vaProtectedSessionExecute() |
| + * |
| + * A function for communicating with TEE (Trusted Execution Environment) |
| + * directly . It needs to create a VA buffer first with type |
| + * #VAProtectedSessionExecuteBufferType. It has a function_id to specify which |
| + * function to execute. The following pseudo-code demonstrates getting TEE |
| + * version via vaProtectedSessionExecute() as an example. |
| + * |
| + * If the protected session is for protected content, we may need to use |
| + * vaProtectedSessionExecute to do handshaking with TEE to retrieve some |
| + * information and this information will be used later in |
| + * vaProtectedSessionHwUpdate(). |
| + * |
| + * \code |
| + * uint16_t version = 0xFF; |
| + * VABufferID buffer; |
| + * VAProtectedSessionExecuteBuffer exec_buff = {0}; |
| + * |
| + * exec_buff.function_id = GET_TEE_VERSION |
| + * exec_buff.input.data = nullptr; |
| + * exec_buff.input.data_size = 0; |
| + * exec_buff.output.data = &version; |
| + * exec_buff.output.max_data_size = (uint16_t); |
| + * va_status = vaCreateBuffer( |
| + * va_dpy, |
| + * protected_session, |
| + * (VABufferType) VAProtectedSessionExecuteBufferType, |
| + * sizeof(exec_buff), |
| + * 1, |
| + * &exec_buff, |
| + * &buffer); |
| + * |
| + * va_status = vaProtectedSessionExecute(va_dpy, protected_session, buffer); |
| + * |
| + * vaDestroyBuffer(va_dpy, buffer); |
| + * \endcode |
| + * |
| + * \section api_prot_update Updating protected session status |
| + * |
| + * A function for updating protected session status related to hardware. |
| + * Sometimes the status is in init when protected session created. Then |
| + * information is gathered from TEE via vaProtectedSessionExecute(). After some |
| + * information gathered, we can use the information to update the protected |
| + * session status with vaProtectedSessionHwUpdate(). |
| + |
| + * For example, if the protected session is for protected content, we will get |
| + * policy blobs from TEE and then pass these infomation with |
| + * vaProtectedSessionHwUpdate to create hardware session. |
| + * |
| + * \code |
| + * INFO *info = &oem_policy_blobs; |
| + * VABufferID buffer; |
| + * VAProtectedSessionHwUpdateBuffer update_buff = {0}; |
| + * |
| + * update_buff.input.data = info; |
| + * update_buff.input.data_size = sizeof(info); |
| + * va_status = vaCreateBuffer( |
| + * va_dpy, |
| + * protected_session, |
| + * (VABufferType) VAProtectedSessionHwUpdateBufferType, |
| + * sizeof(update_buff), |
| + * 1, |
| + * &update_buff, |
| + * &buffer); |
| + * |
| + * va_status = vaProtectedSessionHwUpdate(va_dpy, protected_session, buffer); |
| + * |
| + * vaDestroyBuffer(va_dpy, buffer); |
| + * \endcode |
| + * |
| + * \section api_prot_attach Attach/Detach to enable/disable protection |
| + * |
| + * After hardware session is created, we can attach the protected session to |
| + * the decode/encode/vp context to enable decryption/encryption. |
| + * |
| + * We can attach/detach at frame level. |
| + * |
| + * \code |
| + * foreach (iteration) { |
| + * if (frame_encrypted) { |
| + * vaAttachProtectedSession(va_dpy, decode_ctx, protected_session); |
| + * } |
| + * vaBeginPicture(va_dpy, decode_ctx, surface); |
| + * ... |
| + * vaRenderPicture(va_dpy, decode_ctx, &buf_id1, 1); |
| + * vaRenderPicture(va_dpy, decode_ctx, &buf_id2, 1); |
| + * ... |
| + * vaEndPicture(va_dpy, decode_ctx); |
| + * if (frame_encrypted) { |
| + * vaDetachProtectedSession(va_dpy, decode_ctx); |
| + * } |
| + * } |
| + * \endcode |
| + * |
| + * Or we can attach/detach for every frame |
| + * \code |
| + * vaAttachProtectedSession(va_dpy, decode_ctx, protected_session); |
| + * foreach (iteration) { |
| + * vaBeginPicture(va_dpy, decode_ctx, surface); |
| + * ... |
| + * vaRenderPicture(va_dpy, decode_ctx, &buf_id1, 1); |
| + * vaRenderPicture(va_dpy, decode_ctx, &buf_id2, 1); |
| + * ... |
| + * vaEndPicture(va_dpy, decode_ctx); |
| + * } |
| + * vaDetachProtectedSession(va_dpy, decode_ctx); |
| + * \endcode |
| + */ |
| + |
| +/** |
| + * ProtectedSessions and Contexts |
| + * |
| + * Context represents a "virtual" video decode, encode or video processing |
| + * pipeline. Surfaces are render targets for a given context. The data in the |
| + * surfaces are not accessible to the client except if derived image is supported |
| + * and the internal data format of the surface is implementation specific. |
| + * |
| + * A protected session is a session between application and GPU hardware. |
| + * Protected sessions can be attached to display to enable protection in the pipeline. |
| + * |
| + * Both contexts and protected sessions are identified by unique IDs and its |
| + * implementation specific internals are kept opaque to the clients |
| + */ |
| +typedef VAContextID VAProtectedSessionID; |
| + |
| +/** \brief Input/Output buffer of VAProtectedSessionExecuteBuffer or VAProtectedSessionHwUpdateBuffer */ |
| +typedef struct _VAProtectedSessionBuffer |
| +{ |
| + /* |
| + * This is used when this buffer refer to output buffer. The maximum size of data that the driver |
| + * can return in the output buffer. It is not used for input buffer. |
| + */ |
| + uint32_t max_data_size; |
| + /* |
| + * If it is used for input buffer, it is the size of the input data. If it is used for output buffer, |
| + * it is the returns size of the output data written by the driver. |
| + */ |
| + uint32_t data_size; |
| + /* |
| + * data pointer of this buffer |
| + */ |
| + void *data; |
| + uint32_t va_reserved[VA_PADDING_LOW]; |
| +} VAProtectedSessionBuffer; |
| + |
| +/** \brief Buffer for vaProtectedSessionExecute() */ |
| +typedef struct _VAProtectedSessionExecuteBuffer { |
| + /** \brief Specify the function to execute. It is IHV's implementation specific */ |
| + uint32_t function_id; |
| + /** \brief Input buffer */ |
| + VAProtectedSessionBuffer input; |
| + /** \brief Output buffer */ |
| + VAProtectedSessionBuffer output; |
| + /** \brief Return the result of this function. It is IHV's implementation specific */ |
| + uint32_t status; |
| + uint32_t va_reserved[VA_PADDING_LOW]; |
| +} VAProtectedSessionExecuteBuffer; |
| + |
| +/** \brief Buffer for vaProtectedSessionHwUpdate() */ |
| +typedef struct _VAProtectedSessionHwUpdateBuffer { |
| + /** \brief Input buffer */ |
| + VAProtectedSessionBuffer input; |
| + /** \brief Output buffer */ |
| + VAProtectedSessionBuffer output; |
| + /** \brief Return the result of this function. It is IHV's implementation specific */ |
| + uint32_t status; |
| + uint32_t va_reserved[VA_PADDING_LOW]; |
| +} VAProtectedSessionHwUpdateBuffer; |
| + |
| +/** |
| + * \brief Create a protected session |
| + * |
| + * Create a protected session |
| + * |
| + * @param[in] dpy the VA display |
| + * @param[in] config_id configuration for the protected session |
| + * @param[out] protected_session created protected session id upon return |
| + */ |
| +VAStatus vaCreateProtectedSession( |
| + VADisplay dpy, |
| + VAConfigID config_id, |
| + VAProtectedSessionID *protected_session |
| +); |
| + |
| +/** |
| + * \brief Destroy a protected session |
| + * |
| + * Destroy a protected session |
| + * |
| + * @param[in] dpy the VA display |
| + * @param[in] protected_session protected session to be destroyed |
| + */ |
| +VAStatus vaDestroyProtectedSession( |
| + VADisplay dpy, |
| + VAProtectedSessionID protected_session |
| +); |
| + |
| +/** |
| + * \brief Attach a protected session to the context |
| + * |
| + * Attach a protected session to the context to enable protected function. |
| + * For example, if the protected session is for protected content, attaching |
| + * will help decode context to do decrypt+decode. |
| + * |
| + * @param[in] dpy the VA display |
| + * @param[in] context the decode/encode/vp context |
| + * @param[in] protected_session the protected session to attach |
| + */ |
| +VAStatus vaAttachProtectedSession( |
| + VADisplay dpy, |
| + VAContextID context, |
| + VAProtectedSessionID protected_session |
| +); |
| + |
| +/** |
| + * \brief Detach the protected session of the context |
| + * |
| + * Detach protected session of the context to disable protected function. |
| + * For example, if the protected session is for protected content, detaching |
| + * will end the decode context to do decrypt. |
| + * |
| + * @param[in] dpy the VA display |
| + * @param[in] context the decode/encode/vp context |
| + */ |
| +VAStatus vaDetachProtectedSession( |
| + VADisplay dpy, |
| + VAContextID context |
| +); |
| + |
| +/** |
| + * \brief TEE execution for the particular protected session |
| + * |
| + * TEE execution for the particular protected session. For example, if this |
| + * protected session is TEE session, this function is to invoke TEE command. |
| + * If it is protected content session, this function is to invoke specific GPU |
| + * command like decryptionblt. |
| + * The implementation may differ between IHVs. |
| + * This is a synchronous API. |
| + * |
| + * @param[in] dpy the VA display |
| + * @param[in] protected_session the protected session |
| + * @param[in,out] buf_id the VA buffer |
| + */ |
| +VAStatus vaProtectedSessionExecute( |
| + VADisplay dpy, |
| + VAProtectedSessionID protected_session, |
| + VABufferID buf_id |
| +); |
| + |
| +/** |
| + * \brief Update protected hardware settings |
| + * |
| + * Allows the application to change protected session status which is related |
| + * to hardware. For example, if the protected session is for protected content, |
| + * this function is used to create the hardware session based on input policy |
| + * blobs. |
| + * The implementation may differ between IHVs. |
| + * This is a synchronous API. |
| + * |
| + * @param[in] dpy the VA display |
| + * @param[in] protected_session the protected session |
| + * @param[in,out] buf_id the VA buffer |
| + */ |
| +VAStatus vaProtectedSessionHwUpdate( |
| + VADisplay dpy, |
| + VAProtectedSessionID protected_session, |
| + VABufferID buf_id |
| +); |
| + |
| +/**@}*/ |
| + |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| + |
| +#endif /* VA_PROT_H */ |
| diff --git a/va/va_str.c b/va/va_str.c |
| index 4b631ca..5dfed6e 100644 |
| --- a/va/va_str.c |
| +++ b/va/va_str.c |
| @@ -64,6 +64,7 @@ const char *vaProfileStr(VAProfile profile) |
| TOSTR(VAProfileAV1Profile0); |
| TOSTR(VAProfileAV1Profile1); |
| TOSTR(VAProfileHEVCSccMain444_10); |
| + TOSTR(VAProfileProtected); |
| default: break; |
| } |
| return "<unknown profile>"; |
| @@ -84,6 +85,8 @@ const char *vaEntrypointStr(VAEntrypoint entrypoint) |
| TOSTR(VAEntrypointVideoProc); |
| TOSTR(VAEntrypointFEI); |
| TOSTR(VAEntrypointStats); |
| + TOSTR(VAEntrypointProtectedTEEComm); |
| + TOSTR(VAEntrypointProtectedDisplayLink); |
| } |
| return "<unknown entrypoint>"; |
| } |
| @@ -130,6 +133,7 @@ const char *vaConfigAttribTypeStr(VAConfigAttribType configAttribType) |
| TOSTR(VAConfigAttribPredictionDirection); |
| TOSTR(VAConfigAttribMultipleFrame); |
| TOSTR(VAConfigAttribContextPriority); |
| + TOSTR(VAConfigAttribProtectedTeeFwVersion); |
| case VAConfigAttribTypeMax: break; |
| } |
| return "<unknown config attribute type>"; |
| @@ -179,6 +183,8 @@ const char *vaBufferTypeStr(VABufferType bufferType) |
| TOSTR(VAEncFEICTBCmdBufferType); |
| TOSTR(VAEncFEICURecordBufferType); |
| TOSTR(VASubsetsParameterBufferType); |
| + TOSTR(VAProtectedSessionExecuteBufferType); |
| + TOSTR(VAProtectedSessionHwUpdateBufferType); |
| case VABufferTypeMax: break; |
| } |
| return "<unknown buffer type>"; |
| -- |
| 2.29.2.222.g5d2a92d10f8-goog |
| |