1*b22e6898SYi Chou /* 2*b22e6898SYi Chou * Copyright (c) 2024, The ChromiumOS Authors. All rights reserved. 3*b22e6898SYi Chou * 4*b22e6898SYi Chou * SPDX-License-Identifier: BSD-3-Clause 5*b22e6898SYi Chou */ 6*b22e6898SYi Chou 7*b22e6898SYi Chou #include <assert.h> 8*b22e6898SYi Chou #include <stdint.h> 9*b22e6898SYi Chou #include <string.h> 10*b22e6898SYi Chou 11*b22e6898SYi Chou #include <common/debug.h> 12*b22e6898SYi Chou #include <common/runtime_svc.h> 13*b22e6898SYi Chou #include <lib/psci/psci.h> 14*b22e6898SYi Chou #include <lib/xlat_tables/xlat_tables_v2.h> 15*b22e6898SYi Chou #include <services/oem/chromeos/widevine_smc_handlers.h> 16*b22e6898SYi Chou #include <tools_share/uuid.h> 17*b22e6898SYi Chou 18*b22e6898SYi Chou #define CROS_OEM_TPM_AUTH_PK_MAX_LEN 128 19*b22e6898SYi Chou #define CROS_OEM_HUK_LEN 32 20*b22e6898SYi Chou #define CROS_OEM_ROT_LEN 32 21*b22e6898SYi Chou 22*b22e6898SYi Chou static uint8_t cros_oem_tpm_auth_pk_buffer[CROS_OEM_TPM_AUTH_PK_MAX_LEN]; 23*b22e6898SYi Chou static uint8_t cros_oem_huk_buffer[CROS_OEM_HUK_LEN]; 24*b22e6898SYi Chou static uint8_t cros_oem_rot_len_buffer[CROS_OEM_ROT_LEN]; 25*b22e6898SYi Chou 26*b22e6898SYi Chou struct cros_oem_data cros_oem_tpm_auth_pk = { 27*b22e6898SYi Chou .buffer = cros_oem_tpm_auth_pk_buffer, 28*b22e6898SYi Chou .max_length = sizeof(cros_oem_tpm_auth_pk_buffer), 29*b22e6898SYi Chou }; 30*b22e6898SYi Chou 31*b22e6898SYi Chou struct cros_oem_data cros_oem_huk = { 32*b22e6898SYi Chou .buffer = cros_oem_huk_buffer, 33*b22e6898SYi Chou .max_length = sizeof(cros_oem_huk_buffer), 34*b22e6898SYi Chou }; 35*b22e6898SYi Chou 36*b22e6898SYi Chou struct cros_oem_data cros_oem_rot = { 37*b22e6898SYi Chou .buffer = cros_oem_rot_len_buffer, 38*b22e6898SYi Chou .max_length = sizeof(cros_oem_rot_len_buffer), 39*b22e6898SYi Chou }; 40*b22e6898SYi Chou 41*b22e6898SYi Chou static uintptr_t cros_write_data(struct cros_oem_data *data, 42*b22e6898SYi Chou u_register_t length, u_register_t address, 43*b22e6898SYi Chou void *handle) 44*b22e6898SYi Chou { 45*b22e6898SYi Chou uintptr_t aligned_address; 46*b22e6898SYi Chou uintptr_t aligned_size; 47*b22e6898SYi Chou int32_t rc; 48*b22e6898SYi Chou 49*b22e6898SYi Chou if (data->length) { 50*b22e6898SYi Chou SMC_RET1(handle, PSCI_E_ALREADY_ON); 51*b22e6898SYi Chou } 52*b22e6898SYi Chou 53*b22e6898SYi Chou if (length > data->max_length) { 54*b22e6898SYi Chou SMC_RET1(handle, PSCI_E_INVALID_PARAMS); 55*b22e6898SYi Chou } 56*b22e6898SYi Chou 57*b22e6898SYi Chou aligned_address = page_align(address, DOWN); 58*b22e6898SYi Chou aligned_size = page_align(length + (address - aligned_address), UP); 59*b22e6898SYi Chou 60*b22e6898SYi Chou /* 61*b22e6898SYi Chou * We do not validate the passed in address because we are trusting the 62*b22e6898SYi Chou * non-secure world at this point still. 63*b22e6898SYi Chou */ 64*b22e6898SYi Chou rc = mmap_add_dynamic_region(aligned_address, aligned_address, 65*b22e6898SYi Chou aligned_size, MT_MEMORY | MT_RO | MT_NS); 66*b22e6898SYi Chou if (rc != 0) { 67*b22e6898SYi Chou SMC_RET1(handle, PSCI_E_INVALID_ADDRESS); 68*b22e6898SYi Chou } 69*b22e6898SYi Chou 70*b22e6898SYi Chou memcpy(data->buffer, (void *)address, length); 71*b22e6898SYi Chou data->length = length; 72*b22e6898SYi Chou 73*b22e6898SYi Chou mmap_remove_dynamic_region(aligned_address, aligned_size); 74*b22e6898SYi Chou SMC_RET1(handle, SMC_OK); 75*b22e6898SYi Chou } 76*b22e6898SYi Chou 77*b22e6898SYi Chou /* Handler for servicing specific SMC calls. */ 78*b22e6898SYi Chou static uintptr_t cros_oem_svc_smc_handler(uint32_t smc_fid, u_register_t x1, 79*b22e6898SYi Chou u_register_t x2, u_register_t x3, 80*b22e6898SYi Chou u_register_t x4, void *cookie, 81*b22e6898SYi Chou void *handle, u_register_t flags) 82*b22e6898SYi Chou { 83*b22e6898SYi Chou switch (smc_fid) { 84*b22e6898SYi Chou case CROS_OEM_SMC_DRM_SET_TPM_AUTH_PUB_FUNC_ID: 85*b22e6898SYi Chou return cros_write_data(&cros_oem_tpm_auth_pk, x1, x2, handle); 86*b22e6898SYi Chou case CROS_OEM_SMC_DRM_SET_HARDWARE_UNIQUE_KEY_FUNC_ID: 87*b22e6898SYi Chou return cros_write_data(&cros_oem_huk, x1, x2, handle); 88*b22e6898SYi Chou case CROS_OEM_SMC_DRM_SET_ROOT_OF_TRUST_FUNC_ID: 89*b22e6898SYi Chou return cros_write_data(&cros_oem_rot, x1, x2, handle); 90*b22e6898SYi Chou default: 91*b22e6898SYi Chou WARN("Unimplemented OEM Call: 0x%x\n", smc_fid); 92*b22e6898SYi Chou SMC_RET1(handle, SMC_UNK); 93*b22e6898SYi Chou } 94*b22e6898SYi Chou } 95*b22e6898SYi Chou 96*b22e6898SYi Chou /* Register OEM Service Calls as runtime service */ 97*b22e6898SYi Chou DECLARE_RT_SVC(cros_oem_svc_smc_handler, OEN_OEM_START, OEN_OEM_END, 98*b22e6898SYi Chou SMC_TYPE_FAST, NULL, cros_oem_svc_smc_handler); 99