From f20a20b1e3f513e0075c87d3b406f95bd9ed7df2 Mon Sep 17 00:00:00 2001 From: Boyuan Zhang Date: Wed, 13 May 2020 20:08:55 -0400 Subject: [PATCH] radeon/vcn: program drm message buffer Add a function to handle drm message buffer using input decryption parameters. Acked-by: Pierre-Eric Pelloux-Prayer Part-of: --- src/gallium/drivers/radeon/radeon_vcn_dec.c | 117 ++++++++++++++++++-- 1 file changed, 109 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/radeon/radeon_vcn_dec.c b/src/gallium/drivers/radeon/radeon_vcn_dec.c index 04d879af03e..15781d3036e 100644 --- a/src/gallium/drivers/radeon/radeon_vcn_dec.c +++ b/src/gallium/drivers/radeon/radeon_vcn_dec.c @@ -34,6 +34,7 @@ #include "util/u_video.h" #include "vl/vl_mpeg12_decoder.h" #include "vl/vl_probs_table.h" +#include "pspdecryptionparam.h" #include #include @@ -550,6 +551,47 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, return result; } +static void set_drm_keys(rvcn_dec_message_drm_t *drm, DECRYPT_PARAMETERS *decrypted) +{ + int cbc = decrypted->u.s.cbc; + int ctr = decrypted->u.s.ctr; + int id = decrypted->u.s.drm_id; + int ekc = 1; + int data1 = 1; + int data2 = 1; + + drm->drm_cmd = 0; + drm->drm_cntl = 0; + + drm->drm_cntl = 1 << DRM_CNTL_BYPASS_SHIFT; + + if (cbc || ctr) { + drm->drm_cntl = 0 << DRM_CNTL_BYPASS_SHIFT; + drm->drm_cmd |= 0xff << DRM_CMD_BYTE_MASK_SHIFT; + + if (ctr) + drm->drm_cmd |= 0x00 << DRM_CMD_ALGORITHM_SHIFT; + else if (cbc) + drm->drm_cmd |= 0x02 << DRM_CMD_ALGORITHM_SHIFT; + + drm->drm_cmd |= 1 << DRM_CMD_GEN_MASK_SHIFT; + drm->drm_cmd |= ekc << DRM_CMD_UNWRAP_KEY_SHIFT; + drm->drm_cmd |= 0 << DRM_CMD_OFFSET_SHIFT; + drm->drm_cmd |= data2 << DRM_CMD_CNT_DATA_SHIFT; + drm->drm_cmd |= data1 << DRM_CMD_CNT_KEY_SHIFT; + drm->drm_cmd |= ekc << DRM_CMD_KEY_SHIFT; + drm->drm_cmd |= id << DRM_CMD_SESSION_SEL_SHIFT; + + if (ekc) + memcpy(drm->drm_wrapped_key, decrypted->encrypted_key, 16); + if (data1) + memcpy(drm->drm_key, decrypted->session_iv, 16); + if (data2) + memcpy(drm->drm_counter, decrypted->encrypted_iv, 16); + drm->drm_offset = 0; + } +} + static unsigned calc_ctx_size_h265_main(struct radeon_decoder *dec) { unsigned width = align(dec->base.width, VL_MACROBLOCK_WIDTH); @@ -796,29 +838,51 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) { + DECRYPT_PARAMETERS *decrypt = (DECRYPT_PARAMETERS *)picture->decrypt_key; + bool encrypted = (DECRYPT_PARAMETERS *)picture->protected_playback; struct si_texture *luma = (struct si_texture *)((struct vl_video_buffer *)target)->resources[0]; struct si_texture *chroma = (struct si_texture *)((struct vl_video_buffer *)target)->resources[1]; + ASSERTED struct si_screen *sscreen = (struct si_screen *)dec->screen; rvcn_dec_message_header_t *header; + rvcn_dec_message_index_t *index_drm; rvcn_dec_message_index_t *index; rvcn_dec_message_decode_t *decode; unsigned sizes = 0, offset_decode, offset_codec; + unsigned int offset_drm; void *codec; + rvcn_dec_message_drm_t *drm = NULL; header = dec->msg; sizes += sizeof(rvcn_dec_message_header_t); - index = (void *)header + sizeof(rvcn_dec_message_header_t); - sizes += sizeof(rvcn_dec_message_index_t); + if (encrypted) { + index_drm = (void*)header + sizeof(rvcn_dec_message_header_t); + sizes += sizeof(rvcn_dec_message_index_t); + index = (void*)index_drm + sizeof(rvcn_dec_message_index_t); + sizes += sizeof(rvcn_dec_message_index_t); + } else { + index = (void*)header + sizeof(rvcn_dec_message_header_t); + sizes += sizeof(rvcn_dec_message_index_t); + } offset_decode = sizes; decode = (void *)index + sizeof(rvcn_dec_message_index_t); sizes += sizeof(rvcn_dec_message_decode_t); + if (encrypted) { + offset_drm = sizes; + drm = (void*)decode + sizeof(rvcn_dec_message_decode_t); + sizes += sizeof(rvcn_dec_message_drm_t); + codec = (void*)drm + sizeof(rvcn_dec_message_drm_t); + } else + codec = (void*)decode + sizeof(rvcn_dec_message_decode_t); offset_codec = sizes; - codec = (void *)decode + sizeof(rvcn_dec_message_decode_t); memset(dec->msg, 0, sizes); header->header_size = sizeof(rvcn_dec_message_header_t); header->total_size = sizes; - header->num_buffers = 2; + if (encrypted) + header->num_buffers = 3; + else + header->num_buffers = 2; header->msg_type = RDECODE_MSG_DECODE; header->stream_handle = dec->stream_handle; header->status_report_feedback_number = dec->frame_number; @@ -827,6 +891,12 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, header->index[0].offset = offset_decode; header->index[0].size = sizeof(rvcn_dec_message_decode_t); header->index[0].filled = 0; + if (encrypted) { + index_drm->message_id = RDECODE_MESSAGE_DRM; + index_drm->offset = offset_drm; + index_drm->size = sizeof(rvcn_dec_message_drm_t); + index_drm->filled = 0; + } index->offset = offset_codec; index->size = sizeof(rvcn_dec_message_avc_t); @@ -843,7 +913,12 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, unsigned dpb_size = calc_dpb_size(dec); bool r; if (dpb_size) { - r = si_vid_create_buffer(dec->screen, &dec->dpb, dpb_size, PIPE_USAGE_DEFAULT); + if (encrypted) { + r = si_vid_create_tmz_buffer(dec->screen, &dec->dpb, dpb_size, PIPE_USAGE_DEFAULT); + } else { + r = si_vid_create_buffer(dec->screen, &dec->dpb, dpb_size, PIPE_USAGE_DEFAULT); + } + assert(encrypted == (bool)(dec->dpb.res->flags & RADEON_FLAG_ENCRYPTED)); if (!r) { RVID_ERR("Can't allocated dpb.\n"); return NULL; @@ -857,7 +932,12 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, if (dec->stream_type == RDECODE_CODEC_H264_PERF) { unsigned ctx_size = calc_ctx_size_h264_perf(dec); bool r; - r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + if (encrypted) { + r = si_vid_create_tmz_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + } else { + r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + } + assert(encrypted == (bool)(dec->ctx.res->flags & RADEON_FLAG_ENCRYPTED)); if (!r) { RVID_ERR("Can't allocated context buffer.\n"); @@ -888,7 +968,11 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, if (dec->base.profile == PIPE_VIDEO_PROFILE_VP9_PROFILE2) ctx_size += 8 * 2 * 4096; - r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + if (encrypted) { + r = si_vid_create_tmz_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + } else { + r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + } if (!r) { RVID_ERR("Can't allocated context buffer.\n"); return NULL; @@ -903,15 +987,27 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, dec->bs_ptr = NULL; } else if (fmt == PIPE_VIDEO_FORMAT_HEVC) { unsigned ctx_size; + bool r; if (dec->base.profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10) ctx_size = calc_ctx_size_h265_main10(dec, (struct pipe_h265_picture_desc *)picture); else ctx_size = calc_ctx_size_h265_main(dec); - if (!si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT)) + + if (encrypted) { + r = si_vid_create_tmz_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + } else { + r = si_vid_create_buffer(dec->screen, &dec->ctx, ctx_size, PIPE_USAGE_DEFAULT); + } + if (!r) { RVID_ERR("Can't allocated context buffer.\n"); + return NULL; + } si_vid_clear_buffer(dec->base.context, &dec->ctx); } } + if (encrypted != dec->ws->cs_is_secure(dec->cs)) { + dec->ws->cs_flush(dec->cs, RADEON_FLUSH_TOGGLE_SECURE_SUBMISSION, NULL); + } decode->dpb_size = dec->dpb.res->buf->size; decode->dt_size = si_resource(((struct vl_video_buffer *)target)->resources[0])->buf->size + @@ -953,6 +1049,11 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, decode->dt_chroma_bottom_offset = decode->dt_chroma_top_offset; } + if (encrypted) { + assert(sscreen->info.has_tmz_support); + set_drm_keys(drm, decrypt); + } + switch (u_reduce_video_profile(picture->profile)) { case PIPE_VIDEO_FORMAT_MPEG4_AVC: { rvcn_dec_message_avc_t avc = get_h264_msg(dec, (struct pipe_h264_picture_desc *)picture);