cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hdcp2_execution.c (26543B)


      1/*
      2 * Copyright 2018 Advanced Micro Devices, Inc.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included in
     12 * all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20 * OTHER DEALINGS IN THE SOFTWARE.
     21 *
     22 * Authors: AMD
     23 *
     24 */
     25
     26#include <linux/delay.h>
     27
     28#include "hdcp.h"
     29
     30static inline enum mod_hdcp_status check_receiver_id_list_ready(struct mod_hdcp *hdcp)
     31{
     32	uint8_t is_ready = 0;
     33
     34	if (is_dp_hdcp(hdcp))
     35		is_ready = HDCP_2_2_DP_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus_dp) ? 1 : 0;
     36	else
     37		is_ready = (HDCP_2_2_HDMI_RXSTATUS_READY(hdcp->auth.msg.hdcp2.rxstatus[1]) &&
     38				(HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
     39						hdcp->auth.msg.hdcp2.rxstatus[0])) ? 1 : 0;
     40	return is_ready ? MOD_HDCP_STATUS_SUCCESS :
     41			MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY;
     42}
     43
     44static inline enum mod_hdcp_status check_hdcp2_capable(struct mod_hdcp *hdcp)
     45{
     46	enum mod_hdcp_status status;
     47
     48	if (is_dp_hdcp(hdcp))
     49		status = (hdcp->auth.msg.hdcp2.rxcaps_dp[0] == HDCP_2_2_RX_CAPS_VERSION_VAL) &&
     50				HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[2]) ?
     51				MOD_HDCP_STATUS_SUCCESS :
     52				MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE;
     53	else
     54		status = (hdcp->auth.msg.hdcp2.hdcp2version_hdmi & HDCP_2_2_HDMI_SUPPORT_MASK) ?
     55				MOD_HDCP_STATUS_SUCCESS :
     56				MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE;
     57	return status;
     58}
     59
     60static inline enum mod_hdcp_status check_reauthentication_request(
     61		struct mod_hdcp *hdcp)
     62{
     63	uint8_t ret = 0;
     64
     65	if (is_dp_hdcp(hdcp))
     66		ret = HDCP_2_2_DP_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
     67				MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST :
     68				MOD_HDCP_STATUS_SUCCESS;
     69	else
     70		ret = HDCP_2_2_HDMI_RXSTATUS_REAUTH_REQ(hdcp->auth.msg.hdcp2.rxstatus[1]) ?
     71				MOD_HDCP_STATUS_HDCP2_REAUTH_REQUEST :
     72				MOD_HDCP_STATUS_SUCCESS;
     73	return ret;
     74}
     75
     76static inline enum mod_hdcp_status check_link_integrity_failure_dp(
     77		struct mod_hdcp *hdcp)
     78{
     79	return HDCP_2_2_DP_RXSTATUS_LINK_FAILED(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
     80			MOD_HDCP_STATUS_HDCP2_REAUTH_LINK_INTEGRITY_FAILURE :
     81			MOD_HDCP_STATUS_SUCCESS;
     82}
     83
     84static enum mod_hdcp_status check_ake_cert_available(struct mod_hdcp *hdcp)
     85{
     86	enum mod_hdcp_status status;
     87	uint16_t size;
     88
     89	if (is_dp_hdcp(hdcp)) {
     90		status = MOD_HDCP_STATUS_SUCCESS;
     91	} else {
     92		status = mod_hdcp_read_rxstatus(hdcp);
     93		if (status == MOD_HDCP_STATUS_SUCCESS) {
     94			size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
     95			       hdcp->auth.msg.hdcp2.rxstatus[0];
     96			status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_cert)) ?
     97					MOD_HDCP_STATUS_SUCCESS :
     98					MOD_HDCP_STATUS_HDCP2_AKE_CERT_PENDING;
     99		}
    100	}
    101	return status;
    102}
    103
    104static enum mod_hdcp_status check_h_prime_available(struct mod_hdcp *hdcp)
    105{
    106	enum mod_hdcp_status status;
    107	uint8_t size;
    108
    109	status = mod_hdcp_read_rxstatus(hdcp);
    110	if (status != MOD_HDCP_STATUS_SUCCESS)
    111		goto out;
    112
    113	if (is_dp_hdcp(hdcp)) {
    114		status = HDCP_2_2_DP_RXSTATUS_H_PRIME(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
    115				MOD_HDCP_STATUS_SUCCESS :
    116				MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING;
    117	} else {
    118		size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
    119		       hdcp->auth.msg.hdcp2.rxstatus[0];
    120		status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_h_prime)) ?
    121				MOD_HDCP_STATUS_SUCCESS :
    122				MOD_HDCP_STATUS_HDCP2_H_PRIME_PENDING;
    123	}
    124out:
    125	return status;
    126}
    127
    128static enum mod_hdcp_status check_pairing_info_available(struct mod_hdcp *hdcp)
    129{
    130	enum mod_hdcp_status status;
    131	uint8_t size;
    132
    133	status = mod_hdcp_read_rxstatus(hdcp);
    134	if (status != MOD_HDCP_STATUS_SUCCESS)
    135		goto out;
    136
    137	if (is_dp_hdcp(hdcp)) {
    138		status = HDCP_2_2_DP_RXSTATUS_PAIRING(hdcp->auth.msg.hdcp2.rxstatus_dp) ?
    139				MOD_HDCP_STATUS_SUCCESS :
    140				MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING;
    141	} else {
    142		size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
    143		       hdcp->auth.msg.hdcp2.rxstatus[0];
    144		status = (size == sizeof(hdcp->auth.msg.hdcp2.ake_pairing_info)) ?
    145				MOD_HDCP_STATUS_SUCCESS :
    146				MOD_HDCP_STATUS_HDCP2_PAIRING_INFO_PENDING;
    147	}
    148out:
    149	return status;
    150}
    151
    152static enum mod_hdcp_status poll_l_prime_available(struct mod_hdcp *hdcp)
    153{
    154	enum mod_hdcp_status status;
    155	uint8_t size;
    156	uint16_t max_wait = 20; // units of ms
    157	uint16_t num_polls = 5;
    158	uint16_t wait_time = max_wait / num_polls;
    159
    160	if (is_dp_hdcp(hdcp))
    161		status = MOD_HDCP_STATUS_INVALID_OPERATION;
    162	else
    163		for (; num_polls; num_polls--) {
    164			msleep(wait_time);
    165
    166			status = mod_hdcp_read_rxstatus(hdcp);
    167			if (status != MOD_HDCP_STATUS_SUCCESS)
    168				break;
    169
    170			size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
    171			       hdcp->auth.msg.hdcp2.rxstatus[0];
    172			status = (size == sizeof(hdcp->auth.msg.hdcp2.lc_l_prime)) ?
    173					MOD_HDCP_STATUS_SUCCESS :
    174					MOD_HDCP_STATUS_HDCP2_L_PRIME_PENDING;
    175			if (status == MOD_HDCP_STATUS_SUCCESS)
    176				break;
    177		}
    178	return status;
    179}
    180
    181static enum mod_hdcp_status check_stream_ready_available(struct mod_hdcp *hdcp)
    182{
    183	enum mod_hdcp_status status;
    184	uint8_t size;
    185
    186	if (is_dp_hdcp(hdcp)) {
    187		status = MOD_HDCP_STATUS_INVALID_OPERATION;
    188	} else {
    189		status = mod_hdcp_read_rxstatus(hdcp);
    190		if (status != MOD_HDCP_STATUS_SUCCESS)
    191			goto out;
    192		size = HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
    193		       hdcp->auth.msg.hdcp2.rxstatus[0];
    194		status = (size == sizeof(hdcp->auth.msg.hdcp2.repeater_auth_stream_ready)) ?
    195				MOD_HDCP_STATUS_SUCCESS :
    196				MOD_HDCP_STATUS_HDCP2_STREAM_READY_PENDING;
    197	}
    198out:
    199	return status;
    200}
    201
    202static inline uint8_t get_device_count(struct mod_hdcp *hdcp)
    203{
    204	return HDCP_2_2_DEV_COUNT_LO(hdcp->auth.msg.hdcp2.rx_id_list[2]) +
    205			(HDCP_2_2_DEV_COUNT_HI(hdcp->auth.msg.hdcp2.rx_id_list[1]) << 4);
    206}
    207
    208static enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp)
    209{
    210	/* Avoid device count == 0 to do authentication */
    211	if (0 == get_device_count(hdcp)) {
    212		return MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE;
    213	}
    214
    215	/* Some MST display may choose to report the internal panel as an HDCP RX.   */
    216	/* To update this condition with 1(because the immediate repeater's internal */
    217	/* panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). */
    218	/* Device count must be greater than or equal to tracked hdcp displays.      */
    219	return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ?
    220			MOD_HDCP_STATUS_HDCP2_DEVICE_COUNT_MISMATCH_FAILURE :
    221			MOD_HDCP_STATUS_SUCCESS;
    222}
    223
    224static uint8_t process_rxstatus(struct mod_hdcp *hdcp,
    225		struct mod_hdcp_event_context *event_ctx,
    226		struct mod_hdcp_transition_input_hdcp2 *input,
    227		enum mod_hdcp_status *status)
    228{
    229	if (!mod_hdcp_execute_and_set(mod_hdcp_read_rxstatus,
    230			&input->rxstatus_read, status,
    231			hdcp, "rxstatus_read"))
    232		goto out;
    233	if (!mod_hdcp_execute_and_set(check_reauthentication_request,
    234			&input->reauth_request_check, status,
    235			hdcp, "reauth_request_check"))
    236		goto out;
    237	if (is_dp_hdcp(hdcp)) {
    238		if (!mod_hdcp_execute_and_set(check_link_integrity_failure_dp,
    239				&input->link_integrity_check_dp, status,
    240				hdcp, "link_integrity_check_dp"))
    241			goto out;
    242	}
    243	if (hdcp->connection.is_repeater)
    244		if (check_receiver_id_list_ready(hdcp) ==
    245				MOD_HDCP_STATUS_SUCCESS) {
    246			HDCP_INPUT_PASS_TRACE(hdcp, "rx_id_list_ready");
    247			event_ctx->rx_id_list_ready = 1;
    248			if (is_dp_hdcp(hdcp))
    249				hdcp->auth.msg.hdcp2.rx_id_list_size =
    250						sizeof(hdcp->auth.msg.hdcp2.rx_id_list);
    251			else
    252				hdcp->auth.msg.hdcp2.rx_id_list_size =
    253					HDCP_2_2_HDMI_RXSTATUS_MSG_SZ_HI(hdcp->auth.msg.hdcp2.rxstatus[1]) << 8 |
    254					hdcp->auth.msg.hdcp2.rxstatus[0];
    255		}
    256out:
    257	return (*status == MOD_HDCP_STATUS_SUCCESS);
    258}
    259
    260static enum mod_hdcp_status known_hdcp2_capable_rx(struct mod_hdcp *hdcp,
    261		struct mod_hdcp_event_context *event_ctx,
    262		struct mod_hdcp_transition_input_hdcp2 *input)
    263{
    264	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    265
    266	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    267		event_ctx->unexpected_event = 1;
    268		goto out;
    269	}
    270
    271	if (!mod_hdcp_execute_and_set(mod_hdcp_read_hdcp2version,
    272			&input->hdcp2version_read, &status,
    273			hdcp, "hdcp2version_read"))
    274		goto out;
    275	if (!mod_hdcp_execute_and_set(check_hdcp2_capable,
    276			&input->hdcp2_capable_check, &status,
    277			hdcp, "hdcp2_capable"))
    278		goto out;
    279out:
    280	return status;
    281}
    282
    283static enum mod_hdcp_status send_ake_init(struct mod_hdcp *hdcp,
    284		struct mod_hdcp_event_context *event_ctx,
    285		struct mod_hdcp_transition_input_hdcp2 *input)
    286{
    287	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    288
    289	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    290		event_ctx->unexpected_event = 1;
    291		goto out;
    292	}
    293
    294	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_create_session,
    295			&input->create_session, &status,
    296			hdcp, "create_session"))
    297		goto out;
    298	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_ake_init,
    299			&input->ake_init_prepare, &status,
    300			hdcp, "ake_init_prepare"))
    301		goto out;
    302	if (!mod_hdcp_execute_and_set(mod_hdcp_write_ake_init,
    303			&input->ake_init_write, &status,
    304			hdcp, "ake_init_write"))
    305		goto out;
    306out:
    307	return status;
    308}
    309
    310static enum mod_hdcp_status validate_ake_cert(struct mod_hdcp *hdcp,
    311		struct mod_hdcp_event_context *event_ctx,
    312		struct mod_hdcp_transition_input_hdcp2 *input)
    313{
    314	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    315
    316
    317	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    318			event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    319		event_ctx->unexpected_event = 1;
    320		goto out;
    321	}
    322
    323	if (is_hdmi_dvi_sl_hdcp(hdcp))
    324		if (!mod_hdcp_execute_and_set(check_ake_cert_available,
    325				&input->ake_cert_available, &status,
    326				hdcp, "ake_cert_available"))
    327			goto out;
    328	if (!mod_hdcp_execute_and_set(mod_hdcp_read_ake_cert,
    329			&input->ake_cert_read, &status,
    330			hdcp, "ake_cert_read"))
    331		goto out;
    332	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_ake_cert,
    333			&input->ake_cert_validation, &status,
    334			hdcp, "ake_cert_validation"))
    335		goto out;
    336out:
    337	return status;
    338}
    339
    340static enum mod_hdcp_status send_no_stored_km(struct mod_hdcp *hdcp,
    341		struct mod_hdcp_event_context *event_ctx,
    342		struct mod_hdcp_transition_input_hdcp2 *input)
    343{
    344	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    345
    346	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    347		event_ctx->unexpected_event = 1;
    348		goto out;
    349	}
    350
    351	if (!mod_hdcp_execute_and_set(mod_hdcp_write_no_stored_km,
    352			&input->no_stored_km_write, &status,
    353			hdcp, "no_stored_km_write"))
    354		goto out;
    355out:
    356	return status;
    357}
    358
    359static enum mod_hdcp_status read_h_prime(struct mod_hdcp *hdcp,
    360		struct mod_hdcp_event_context *event_ctx,
    361		struct mod_hdcp_transition_input_hdcp2 *input)
    362{
    363	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    364
    365	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    366			event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
    367			event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    368		event_ctx->unexpected_event = 1;
    369		goto out;
    370	}
    371
    372	if (!mod_hdcp_execute_and_set(check_h_prime_available,
    373			&input->h_prime_available, &status,
    374			hdcp, "h_prime_available"))
    375		goto out;
    376
    377	if (!mod_hdcp_execute_and_set(mod_hdcp_read_h_prime,
    378			&input->h_prime_read, &status,
    379			hdcp, "h_prime_read"))
    380		goto out;
    381out:
    382	return status;
    383}
    384
    385static enum mod_hdcp_status read_pairing_info_and_validate_h_prime(
    386		struct mod_hdcp *hdcp,
    387		struct mod_hdcp_event_context *event_ctx,
    388		struct mod_hdcp_transition_input_hdcp2 *input)
    389{
    390	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    391
    392	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    393			event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
    394			event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    395		event_ctx->unexpected_event = 1;
    396		goto out;
    397	}
    398
    399	if (!mod_hdcp_execute_and_set(check_pairing_info_available,
    400			&input->pairing_available, &status,
    401			hdcp, "pairing_available"))
    402		goto out;
    403	if (!mod_hdcp_execute_and_set(mod_hdcp_read_pairing_info,
    404			&input->pairing_info_read, &status,
    405			hdcp, "pairing_info_read"))
    406		goto out;
    407	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_h_prime,
    408			&input->h_prime_validation, &status,
    409			hdcp, "h_prime_validation"))
    410		goto out;
    411out:
    412	return status;
    413}
    414
    415static enum mod_hdcp_status send_stored_km(struct mod_hdcp *hdcp,
    416		struct mod_hdcp_event_context *event_ctx,
    417		struct mod_hdcp_transition_input_hdcp2 *input)
    418{
    419	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    420
    421	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    422		event_ctx->unexpected_event = 1;
    423		goto out;
    424	}
    425
    426	if (!mod_hdcp_execute_and_set(mod_hdcp_write_stored_km,
    427			&input->stored_km_write, &status,
    428			hdcp, "stored_km_write"))
    429		goto out;
    430out:
    431	return status;
    432}
    433
    434static enum mod_hdcp_status validate_h_prime(struct mod_hdcp *hdcp,
    435		struct mod_hdcp_event_context *event_ctx,
    436		struct mod_hdcp_transition_input_hdcp2 *input)
    437{
    438	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    439
    440	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    441			event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
    442			event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    443		event_ctx->unexpected_event = 1;
    444		goto out;
    445	}
    446
    447	if (!mod_hdcp_execute_and_set(check_h_prime_available,
    448			&input->h_prime_available, &status,
    449			hdcp, "h_prime_available"))
    450		goto out;
    451	if (!mod_hdcp_execute_and_set(mod_hdcp_read_h_prime,
    452			&input->h_prime_read, &status,
    453			hdcp, "h_prime_read"))
    454		goto out;
    455	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_h_prime,
    456			&input->h_prime_validation, &status,
    457			hdcp, "h_prime_validation"))
    458		goto out;
    459out:
    460	return status;
    461}
    462
    463static enum mod_hdcp_status locality_check(struct mod_hdcp *hdcp,
    464		struct mod_hdcp_event_context *event_ctx,
    465		struct mod_hdcp_transition_input_hdcp2 *input)
    466{
    467	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    468
    469	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    470		event_ctx->unexpected_event = 1;
    471		goto out;
    472	}
    473
    474	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_lc_init,
    475			&input->lc_init_prepare, &status,
    476			hdcp, "lc_init_prepare"))
    477		goto out;
    478	if (!mod_hdcp_execute_and_set(mod_hdcp_write_lc_init,
    479			&input->lc_init_write, &status,
    480			 hdcp, "lc_init_write"))
    481		goto out;
    482	if (is_dp_hdcp(hdcp))
    483		msleep(16);
    484	else
    485		if (!mod_hdcp_execute_and_set(poll_l_prime_available,
    486				&input->l_prime_available_poll, &status,
    487				hdcp, "l_prime_available_poll"))
    488			goto out;
    489	if (!mod_hdcp_execute_and_set(mod_hdcp_read_l_prime,
    490			&input->l_prime_read, &status,
    491			hdcp, "l_prime_read"))
    492		goto out;
    493	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_l_prime,
    494			&input->l_prime_validation, &status,
    495			hdcp, "l_prime_validation"))
    496		goto out;
    497out:
    498	return status;
    499}
    500
    501static enum mod_hdcp_status exchange_ks_and_test_for_repeater(struct mod_hdcp *hdcp,
    502		struct mod_hdcp_event_context *event_ctx,
    503		struct mod_hdcp_transition_input_hdcp2 *input)
    504{
    505	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    506
    507	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    508		event_ctx->unexpected_event = 1;
    509		goto out;
    510	}
    511
    512	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_eks,
    513			&input->eks_prepare, &status,
    514			hdcp, "eks_prepare"))
    515		goto out;
    516	if (!mod_hdcp_execute_and_set(mod_hdcp_write_eks,
    517			&input->eks_write, &status,
    518			hdcp, "eks_write"))
    519		goto out;
    520out:
    521	return status;
    522}
    523
    524static enum mod_hdcp_status enable_encryption(struct mod_hdcp *hdcp,
    525		struct mod_hdcp_event_context *event_ctx,
    526		struct mod_hdcp_transition_input_hdcp2 *input)
    527{
    528	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    529
    530	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    531			event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
    532		event_ctx->unexpected_event = 1;
    533		goto out;
    534	}
    535	if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
    536		process_rxstatus(hdcp, event_ctx, input, &status);
    537		goto out;
    538	}
    539
    540	if (is_hdmi_dvi_sl_hdcp(hdcp)) {
    541		if (!process_rxstatus(hdcp, event_ctx, input, &status))
    542			goto out;
    543		if (event_ctx->rx_id_list_ready)
    544			goto out;
    545	}
    546	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_enable_encryption,
    547			&input->enable_encryption, &status,
    548			hdcp, "enable_encryption"))
    549		goto out;
    550	if (is_dp_mst_hdcp(hdcp)) {
    551		if (!mod_hdcp_execute_and_set(
    552				mod_hdcp_hdcp2_enable_dp_stream_encryption,
    553				&input->stream_encryption_dp, &status,
    554				hdcp, "stream_encryption_dp"))
    555			goto out;
    556	}
    557out:
    558	return status;
    559}
    560
    561static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp,
    562		struct mod_hdcp_event_context *event_ctx,
    563		struct mod_hdcp_transition_input_hdcp2 *input)
    564{
    565	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    566
    567	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    568			event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
    569		event_ctx->unexpected_event = 1;
    570		goto out;
    571	}
    572
    573	process_rxstatus(hdcp, event_ctx, input, &status);
    574out:
    575	return status;
    576}
    577
    578static enum mod_hdcp_status wait_for_rx_id_list(struct mod_hdcp *hdcp,
    579		struct mod_hdcp_event_context *event_ctx,
    580		struct mod_hdcp_transition_input_hdcp2 *input)
    581{
    582	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    583
    584	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    585			event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
    586			event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    587		event_ctx->unexpected_event = 1;
    588		goto out;
    589	}
    590
    591	if (!process_rxstatus(hdcp, event_ctx, input, &status))
    592		goto out;
    593	if (!event_ctx->rx_id_list_ready) {
    594		status = MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_NOT_READY;
    595		goto out;
    596	}
    597out:
    598	return status;
    599}
    600
    601static enum mod_hdcp_status verify_rx_id_list_and_send_ack(struct mod_hdcp *hdcp,
    602		struct mod_hdcp_event_context *event_ctx,
    603		struct mod_hdcp_transition_input_hdcp2 *input)
    604{
    605	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    606
    607	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    608			event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
    609		event_ctx->unexpected_event = 1;
    610		goto out;
    611	}
    612	if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
    613		process_rxstatus(hdcp, event_ctx, input, &status);
    614		goto out;
    615	}
    616
    617	if (!mod_hdcp_execute_and_set(mod_hdcp_read_rx_id_list,
    618			&input->rx_id_list_read,
    619			&status, hdcp, "receiver_id_list_read"))
    620		goto out;
    621	if (!mod_hdcp_execute_and_set(check_device_count,
    622			&input->device_count_check,
    623			&status, hdcp, "device_count_check"))
    624		goto out;
    625	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_rx_id_list,
    626			&input->rx_id_list_validation,
    627			&status, hdcp, "rx_id_list_validation"))
    628		goto out;
    629	if (!mod_hdcp_execute_and_set(mod_hdcp_write_repeater_auth_ack,
    630			&input->repeater_auth_ack_write,
    631			&status, hdcp, "repeater_auth_ack_write"))
    632		goto out;
    633out:
    634	return status;
    635}
    636
    637static enum mod_hdcp_status send_stream_management(struct mod_hdcp *hdcp,
    638		struct mod_hdcp_event_context *event_ctx,
    639		struct mod_hdcp_transition_input_hdcp2 *input)
    640{
    641	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    642
    643	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    644			event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
    645		event_ctx->unexpected_event = 1;
    646		goto out;
    647	}
    648	if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
    649		process_rxstatus(hdcp, event_ctx, input, &status);
    650		goto out;
    651	}
    652
    653	if (is_hdmi_dvi_sl_hdcp(hdcp)) {
    654		if (!process_rxstatus(hdcp, event_ctx, input, &status))
    655			goto out;
    656		if (event_ctx->rx_id_list_ready)
    657			goto out;
    658	}
    659	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_prepare_stream_management,
    660			&input->prepare_stream_manage,
    661			&status, hdcp, "prepare_stream_manage"))
    662		goto out;
    663
    664	if (!mod_hdcp_execute_and_set(mod_hdcp_write_stream_manage,
    665			&input->stream_manage_write,
    666			&status, hdcp, "stream_manage_write"))
    667		goto out;
    668out:
    669	return status;
    670}
    671
    672static enum mod_hdcp_status validate_stream_ready(struct mod_hdcp *hdcp,
    673		struct mod_hdcp_event_context *event_ctx,
    674		struct mod_hdcp_transition_input_hdcp2 *input)
    675{
    676	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    677
    678	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    679			event_ctx->event != MOD_HDCP_EVENT_CPIRQ &&
    680			event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) {
    681		event_ctx->unexpected_event = 1;
    682		goto out;
    683	}
    684	if (event_ctx->event == MOD_HDCP_EVENT_CPIRQ) {
    685		process_rxstatus(hdcp, event_ctx, input, &status);
    686		goto out;
    687	}
    688
    689	if (is_hdmi_dvi_sl_hdcp(hdcp)) {
    690		if (!process_rxstatus(hdcp, event_ctx, input, &status))
    691			goto out;
    692		if (event_ctx->rx_id_list_ready) {
    693			goto out;
    694		}
    695	}
    696	if (is_hdmi_dvi_sl_hdcp(hdcp))
    697		if (!mod_hdcp_execute_and_set(check_stream_ready_available,
    698				&input->stream_ready_available,
    699				&status, hdcp, "stream_ready_available"))
    700			goto out;
    701	if (!mod_hdcp_execute_and_set(mod_hdcp_read_stream_ready,
    702			&input->stream_ready_read,
    703			&status, hdcp, "stream_ready_read"))
    704		goto out;
    705	if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp2_validate_stream_ready,
    706			&input->stream_ready_validation,
    707			&status, hdcp, "stream_ready_validation"))
    708		goto out;
    709
    710out:
    711	return status;
    712}
    713
    714static enum mod_hdcp_status determine_rx_hdcp_capable_dp(struct mod_hdcp *hdcp,
    715		struct mod_hdcp_event_context *event_ctx,
    716		struct mod_hdcp_transition_input_hdcp2 *input)
    717{
    718	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    719
    720	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) {
    721		event_ctx->unexpected_event = 1;
    722		goto out;
    723	}
    724
    725	if (!mod_hdcp_execute_and_set(mod_hdcp_read_rxcaps,
    726			&input->rx_caps_read_dp,
    727			&status, hdcp, "rx_caps_read_dp"))
    728		goto out;
    729	if (!mod_hdcp_execute_and_set(check_hdcp2_capable,
    730			&input->hdcp2_capable_check, &status,
    731			hdcp, "hdcp2_capable_check"))
    732		goto out;
    733out:
    734	return status;
    735}
    736
    737static enum mod_hdcp_status send_content_stream_type_dp(struct mod_hdcp *hdcp,
    738		struct mod_hdcp_event_context *event_ctx,
    739		struct mod_hdcp_transition_input_hdcp2 *input)
    740{
    741	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    742
    743	if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK &&
    744			event_ctx->event != MOD_HDCP_EVENT_CPIRQ) {
    745		event_ctx->unexpected_event = 1;
    746		goto out;
    747	}
    748
    749	if (!process_rxstatus(hdcp, event_ctx, input, &status))
    750		goto out;
    751	if (!mod_hdcp_execute_and_set(mod_hdcp_write_content_type,
    752			&input->content_stream_type_write, &status,
    753			hdcp, "content_stream_type_write"))
    754		goto out;
    755out:
    756	return status;
    757}
    758
    759enum mod_hdcp_status mod_hdcp_hdcp2_execution(struct mod_hdcp *hdcp,
    760	struct mod_hdcp_event_context *event_ctx,
    761	struct mod_hdcp_transition_input_hdcp2 *input)
    762{
    763	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    764
    765	switch (current_state(hdcp)) {
    766	case H2_A0_KNOWN_HDCP2_CAPABLE_RX:
    767		status = known_hdcp2_capable_rx(hdcp, event_ctx, input);
    768		break;
    769	case H2_A1_SEND_AKE_INIT:
    770		status = send_ake_init(hdcp, event_ctx, input);
    771		break;
    772	case H2_A1_VALIDATE_AKE_CERT:
    773		status = validate_ake_cert(hdcp, event_ctx, input);
    774		break;
    775	case H2_A1_SEND_NO_STORED_KM:
    776		status = send_no_stored_km(hdcp, event_ctx, input);
    777		break;
    778	case H2_A1_READ_H_PRIME:
    779		status = read_h_prime(hdcp, event_ctx, input);
    780		break;
    781	case H2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
    782		status = read_pairing_info_and_validate_h_prime(hdcp,
    783				event_ctx, input);
    784		break;
    785	case H2_A1_SEND_STORED_KM:
    786		status = send_stored_km(hdcp, event_ctx, input);
    787		break;
    788	case H2_A1_VALIDATE_H_PRIME:
    789		status = validate_h_prime(hdcp, event_ctx, input);
    790		break;
    791	case H2_A2_LOCALITY_CHECK:
    792		status = locality_check(hdcp, event_ctx, input);
    793		break;
    794	case H2_A3_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
    795		status = exchange_ks_and_test_for_repeater(hdcp, event_ctx, input);
    796		break;
    797	case H2_ENABLE_ENCRYPTION:
    798		status = enable_encryption(hdcp, event_ctx, input);
    799		break;
    800	case H2_A5_AUTHENTICATED:
    801		status = authenticated(hdcp, event_ctx, input);
    802		break;
    803	case H2_A6_WAIT_FOR_RX_ID_LIST:
    804		status = wait_for_rx_id_list(hdcp, event_ctx, input);
    805		break;
    806	case H2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
    807		status = verify_rx_id_list_and_send_ack(hdcp, event_ctx, input);
    808		break;
    809	case H2_A9_SEND_STREAM_MANAGEMENT:
    810		status = send_stream_management(hdcp, event_ctx, input);
    811		break;
    812	case H2_A9_VALIDATE_STREAM_READY:
    813		status = validate_stream_ready(hdcp, event_ctx, input);
    814		break;
    815	default:
    816		status = MOD_HDCP_STATUS_INVALID_STATE;
    817		break;
    818	}
    819
    820	return status;
    821}
    822
    823enum mod_hdcp_status mod_hdcp_hdcp2_dp_execution(struct mod_hdcp *hdcp,
    824	struct mod_hdcp_event_context *event_ctx,
    825	struct mod_hdcp_transition_input_hdcp2 *input)
    826{
    827	enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS;
    828
    829	switch (current_state(hdcp)) {
    830	case D2_A0_DETERMINE_RX_HDCP_CAPABLE:
    831		status = determine_rx_hdcp_capable_dp(hdcp, event_ctx, input);
    832		break;
    833	case D2_A1_SEND_AKE_INIT:
    834		status = send_ake_init(hdcp, event_ctx, input);
    835		break;
    836	case D2_A1_VALIDATE_AKE_CERT:
    837		status = validate_ake_cert(hdcp, event_ctx, input);
    838		break;
    839	case D2_A1_SEND_NO_STORED_KM:
    840		status = send_no_stored_km(hdcp, event_ctx, input);
    841		break;
    842	case D2_A1_READ_H_PRIME:
    843		status = read_h_prime(hdcp, event_ctx, input);
    844		break;
    845	case D2_A1_READ_PAIRING_INFO_AND_VALIDATE_H_PRIME:
    846		status = read_pairing_info_and_validate_h_prime(hdcp,
    847				event_ctx, input);
    848		break;
    849	case D2_A1_SEND_STORED_KM:
    850		status = send_stored_km(hdcp, event_ctx, input);
    851		break;
    852	case D2_A1_VALIDATE_H_PRIME:
    853		status = validate_h_prime(hdcp, event_ctx, input);
    854		break;
    855	case D2_A2_LOCALITY_CHECK:
    856		status = locality_check(hdcp, event_ctx, input);
    857		break;
    858	case D2_A34_EXCHANGE_KS_AND_TEST_FOR_REPEATER:
    859		status = exchange_ks_and_test_for_repeater(hdcp,
    860				event_ctx, input);
    861		break;
    862	case D2_SEND_CONTENT_STREAM_TYPE:
    863		status = send_content_stream_type_dp(hdcp, event_ctx, input);
    864		break;
    865	case D2_ENABLE_ENCRYPTION:
    866		status = enable_encryption(hdcp, event_ctx, input);
    867		break;
    868	case D2_A5_AUTHENTICATED:
    869		status = authenticated(hdcp, event_ctx, input);
    870		break;
    871	case D2_A6_WAIT_FOR_RX_ID_LIST:
    872		status = wait_for_rx_id_list(hdcp, event_ctx, input);
    873		break;
    874	case D2_A78_VERIFY_RX_ID_LIST_AND_SEND_ACK:
    875		status = verify_rx_id_list_and_send_ack(hdcp, event_ctx, input);
    876		break;
    877	case D2_A9_SEND_STREAM_MANAGEMENT:
    878		status = send_stream_management(hdcp, event_ctx, input);
    879		break;
    880	case D2_A9_VALIDATE_STREAM_READY:
    881		status = validate_stream_ready(hdcp, event_ctx, input);
    882		break;
    883	default:
    884		status = MOD_HDCP_STATUS_INVALID_STATE;
    885		break;
    886	}
    887
    888	return status;
    889}