blob: b568fb238af8eec8ac9cfecc903a10c6ac931ff9 [file]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "hwdrm-videoproc-ta/videoproc_ta_service.h"
#include <stdint.h>
#include <string.h>
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>
#include <util.h>
#include "hwdrm-videoproc-ta/h264_parser.h"
#define PTA_MEM_UUID \
{ \
0x4477588a, 0x8476, 0x11e2, { \
0xad, 0x15, 0xe4, 0x1f, 0x13, 0x90, 0xd6, 0x76 \
} \
}
#define TZCMD_TA_MEM_FIRST_CMD 0x1000
#define TZCMD_TA_MEM_MAP (TZCMD_TA_MEM_FIRST_CMD + 3)
#define FLAG_TA_MAP_CACHED (1 << 2)
TEE_Result ParseH264SliceHeader(uint32_t param_types,
TEE_Param params[TEE_NUM_PARAMS]) {
uint32_t ptypes = TEE_PARAM_TYPES(
TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT,
TEE_PARAM_TYPE_MEMREF_INPUT, TEE_PARAM_TYPE_MEMREF_OUTPUT);
if (param_types != ptypes) {
EMSG("ParseH264SliceHeader failed with unsupported param types");
return TEE_ERROR_NOT_SUPPORTED;
}
// Now we need to map the input handle to read from it.
TEE_Result res = TEE_ERROR_GENERIC;
const TEE_UUID uuid = PTA_MEM_UUID;
TEE_TASessionHandle sess = TEE_HANDLE_NULL;
TEE_Param map_params[TEE_NUM_PARAMS];
uint32_t map_param_types =
TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, TEE_PARAM_TYPE_VALUE_INPUT,
TEE_PARAM_TYPE_VALUE_INOUT, TEE_PARAM_TYPE_VALUE_INOUT);
res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, &sess, NULL);
if (res) {
EMSG("Failure opening mem PTA of %d", res);
return res;
}
// Input buffer secure buffer handle.
map_params[0].value.a = params[0].value.a;
map_params[0].value.b = FLAG_TA_MAP_CACHED;
map_params[1].value.a = map_params[1].value.b = 0; // offset
map_params[2].value.a = map_params[2].value.b = 0; // va
map_params[3].value.a = map_params[3].value.b = 0; // size
res = TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE, TZCMD_TA_MEM_MAP,
map_param_types, map_params, NULL);
if (res) {
TEE_CloseTASession(sess);
EMSG("Failure querying PTA mem of %d", res);
return res;
}
void* in_addr =
(void*)reg_pair_to_64(map_params[2].value.a, map_params[2].value.b);
size_t in_size = reg_pair_to_64(map_params[3].value.a, map_params[3].value.b);
// Verify the offset.
if (params[1].value.a >= in_size) {
res = TEE_ERROR_BAD_PARAMETERS;
goto out;
}
// Verify the size of the input/output structs.
if (params[2].memref.size != sizeof(struct StreamDataForSliceHeader) ||
params[3].memref.size != sizeof(struct H264SliceHeaderData)) {
res = TEE_ERROR_BAD_PARAMETERS;
goto out;
}
// Verify the memory types on the input/output data.
res = TEE_CheckMemoryAccessRights(
TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_NONSECURE |
TEE_MEMORY_ACCESS_ANY_OWNER,
params[2].memref.buffer, params[2].memref.size);
if (res != TEE_SUCCESS) {
EMSG("Invalid input memory");
goto out;
}
res = TEE_CheckMemoryAccessRights(
TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_NONSECURE |
TEE_MEMORY_ACCESS_ANY_OWNER,
params[3].memref.buffer, params[3].memref.size);
if (res != TEE_SUCCESS) {
EMSG("Invalid output memory");
goto out;
}
struct H264SliceHeaderData slice_hdr;
struct StreamDataForSliceHeader* stream_data = params[2].memref.buffer;
if (!ParseSliceHeader(((uint8_t*)in_addr) + params[1].value.a,
in_size - params[1].value.a, stream_data, &slice_hdr)) {
res = TEE_ERROR_BAD_FORMAT;
goto out;
}
// Copy the slice header to the memref so it gets sent back.
memcpy(params[3].memref.buffer, &slice_hdr, sizeof(slice_hdr));
params[3].memref.size = sizeof(slice_hdr);
res = TEE_SUCCESS;
out:
TEE_CloseTASession(sess);
tee_unmap(in_addr, in_size);
return res;
}