| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * Firmware layer for XilSecure APIs. | |
| * | |
| * Copyright (C) 2014-2022 Xilinx, Inc. | |
| * Copyright (C) 2022-2025 Advanced Micro Devices, Inc. | |
| */ | |
| #include <linux/firmware/xlnx-zynqmp.h> | |
| #include <linux/module.h> | |
| /** | |
| * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using | |
| * AES-GCM core. | |
| * @address: Address of the AesParams structure. | |
| * @out: Returned output value | |
| * | |
| * Return: Returns status, either success or error code. | |
| */ | |
| int zynqmp_pm_aes_engine(const u64 address, u32 *out) | |
| { | |
| u32 ret_payload[PAYLOAD_ARG_CNT]; | |
| int ret; | |
| if (!out) | |
| return -EINVAL; | |
| ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, ret_payload, 2, upper_32_bits(address), | |
| lower_32_bits(address)); | |
| *out = ret_payload[1]; | |
| return ret; | |
| } | |
| EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine); | |
| /** | |
| * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash | |
| * @address: Address of the data/ Address of output buffer where | |
| * hash should be stored. | |
| * @size: Size of the data. | |
| * @flags: | |
| * BIT(0) - for initializing csudma driver and SHA3(Here address | |
| * and size inputs can be NULL). | |
| * BIT(1) - to call Sha3_Update API which can be called multiple | |
| * times when data is not contiguous. | |
| * BIT(2) - to get final hash of the whole updated data. | |
| * Hash will be overwritten at provided address with | |
| * 48 bytes. | |
| * | |
| * Return: Returns status, either success or error code. | |
| */ | |
| int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags) | |
| { | |
| u32 lower_addr = lower_32_bits(address); | |
| u32 upper_addr = upper_32_bits(address); | |
| return zynqmp_pm_invoke_fn(PM_SECURE_SHA, NULL, 4, upper_addr, lower_addr, size, flags); | |
| } | |
| EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash); | |
| /** | |
| * xlnx_get_crypto_dev_data() - Get crypto dev data of platform | |
| * @feature_map: List of available feature map of all platform | |
| * | |
| * Return: Returns crypto dev data, either address crypto dev or ERR PTR | |
| */ | |
| void *xlnx_get_crypto_dev_data(struct xlnx_feature *feature_map) | |
| { | |
| struct xlnx_feature *feature; | |
| u32 pm_family_code; | |
| int ret; | |
| /* Get the Family code and sub family code of platform */ | |
| ret = zynqmp_pm_get_family_info(&pm_family_code); | |
| if (ret < 0) | |
| return ERR_PTR(ret); | |
| feature = feature_map; | |
| for (; feature->family; feature++) { | |
| if (feature->family == pm_family_code) { | |
| ret = zynqmp_pm_feature(feature->feature_id); | |
| if (ret < 0) | |
| return ERR_PTR(ret); | |
| return feature->data; | |
| } | |
| } | |
| return ERR_PTR(-ENODEV); | |
| } | |
| EXPORT_SYMBOL_GPL(xlnx_get_crypto_dev_data); | |
| /** | |
| * versal_pm_aes_key_write - Write AES key registers | |
| * @keylen: Size of the input key to be written | |
| * @keysrc: Key Source to be selected to which provided | |
| * key should be updated | |
| * @keyaddr: Address of a buffer which should contain the key | |
| * to be written | |
| * | |
| * This function provides support to write AES volatile user keys. | |
| * | |
| * Return: Returns status, either success or error+reason | |
| */ | |
| int versal_pm_aes_key_write(const u32 keylen, | |
| const u32 keysrc, const u64 keyaddr) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_WRITE_KEY, NULL, 4, | |
| keylen, keysrc, | |
| lower_32_bits(keyaddr), | |
| upper_32_bits(keyaddr)); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_key_write); | |
| /** | |
| * versal_pm_aes_key_zero - Zeroise AES User key registers | |
| * @keysrc: Key Source to be selected to which provided | |
| * key should be updated | |
| * | |
| * This function provides support to zeroise AES volatile user keys. | |
| * | |
| * Return: Returns status, either success or error+reason | |
| */ | |
| int versal_pm_aes_key_zero(const u32 keysrc) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_KEY_ZERO, NULL, 1, keysrc); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_key_zero); | |
| /** | |
| * versal_pm_aes_op_init - Init AES operation | |
| * @hw_req: AES op init structure address | |
| * | |
| * This function provides support to init AES operation. | |
| * | |
| * Return: Returns status, either success or error+reason | |
| */ | |
| int versal_pm_aes_op_init(const u64 hw_req) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_OP_INIT, NULL, 2, | |
| lower_32_bits(hw_req), | |
| upper_32_bits(hw_req)); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_op_init); | |
| /** | |
| * versal_pm_aes_update_aad - AES update aad | |
| * @aad_addr: AES aad address | |
| * @aad_len: AES aad data length | |
| * | |
| * This function provides support to update AAD data. | |
| * | |
| * Return: Returns status, either success or error+reason | |
| */ | |
| int versal_pm_aes_update_aad(const u64 aad_addr, const u32 aad_len) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_UPDATE_AAD, NULL, 3, | |
| lower_32_bits(aad_addr), | |
| upper_32_bits(aad_addr), | |
| aad_len); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_update_aad); | |
| /** | |
| * versal_pm_aes_enc_update - Access AES hardware to encrypt the data using | |
| * AES-GCM core. | |
| * @in_params: Address of the AesParams structure | |
| * @in_addr: Address of input buffer | |
| * | |
| * Return: Returns status, either success or error code. | |
| */ | |
| int versal_pm_aes_enc_update(const u64 in_params, const u64 in_addr) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_ENCRYPT_UPDATE, NULL, 4, | |
| lower_32_bits(in_params), | |
| upper_32_bits(in_params), | |
| lower_32_bits(in_addr), | |
| upper_32_bits(in_addr)); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_enc_update); | |
| /** | |
| * versal_pm_aes_enc_final - Access AES hardware to store the GCM tag | |
| * @gcm_addr: Address of the gcm tag | |
| * | |
| * Return: Returns status, either success or error code. | |
| */ | |
| int versal_pm_aes_enc_final(const u64 gcm_addr) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_ENCRYPT_FINAL, NULL, 2, | |
| lower_32_bits(gcm_addr), | |
| upper_32_bits(gcm_addr)); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_enc_final); | |
| /** | |
| * versal_pm_aes_dec_update - Access AES hardware to decrypt the data using | |
| * AES-GCM core. | |
| * @in_params: Address of the AesParams structure | |
| * @in_addr: Address of input buffer | |
| * | |
| * Return: Returns status, either success or error code. | |
| */ | |
| int versal_pm_aes_dec_update(const u64 in_params, const u64 in_addr) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_DECRYPT_UPDATE, NULL, 4, | |
| lower_32_bits(in_params), | |
| upper_32_bits(in_params), | |
| lower_32_bits(in_addr), | |
| upper_32_bits(in_addr)); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_dec_update); | |
| /** | |
| * versal_pm_aes_dec_final - Access AES hardware to get the GCM tag | |
| * @gcm_addr: Address of the gcm tag | |
| * | |
| * Return: Returns status, either success or error code. | |
| */ | |
| int versal_pm_aes_dec_final(const u64 gcm_addr) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_DECRYPT_FINAL, NULL, 2, | |
| lower_32_bits(gcm_addr), | |
| upper_32_bits(gcm_addr)); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_dec_final); | |
| /** | |
| * versal_pm_aes_init - Init AES block | |
| * | |
| * This function initialise AES block. | |
| * | |
| * Return: Returns status, either success or error+reason | |
| */ | |
| int versal_pm_aes_init(void) | |
| { | |
| return zynqmp_pm_invoke_fn(XSECURE_API_AES_INIT, NULL, 0); | |
| } | |
| EXPORT_SYMBOL_GPL(versal_pm_aes_init); |