c05564c4d8
Android 13
160 lines
3.3 KiB
C
Executable file
160 lines
3.3 KiB
C
Executable file
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2015-2019, MICROTRUST Incorporated
|
|
* All Rights Reserved.
|
|
*
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/semaphore.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/cpu.h>
|
|
#include <fdrv.h>
|
|
#include "teei_id.h"
|
|
#include "sched_status.h"
|
|
#include "nt_smc_call.h"
|
|
#include "teei_log.h"
|
|
#include "teei_common.h"
|
|
#include "switch_queue.h"
|
|
#include "teei_client_main.h"
|
|
#include "backward_driver.h"
|
|
#include "utdriver_macro.h"
|
|
|
|
#include <teei_secure_api.h>
|
|
|
|
#define IMSG_TAG "[tz_driver]"
|
|
#include <imsg_log.h>
|
|
|
|
static LIST_HEAD(fdrv_list);
|
|
|
|
int create_fdrv(struct teei_fdrv *fdrv)
|
|
{
|
|
unsigned long temp_addr = 0;
|
|
long retVal = 0;
|
|
|
|
if (fdrv->buff_size > VDRV_MAX_SIZE) {
|
|
IMSG_ERROR("[%s][%d]: FDrv buffer size is too large.\n",
|
|
__FILE__, __LINE__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
#ifdef UT_DMA_ZONE
|
|
temp_addr = (unsigned long) __get_free_pages(GFP_KERNEL | GFP_DMA,
|
|
get_order(ROUND_UP(fdrv->buff_size, SZ_4K)));
|
|
#else
|
|
temp_addr = (unsigned long) __get_free_pages(GFP_KERNEL,
|
|
get_order(ROUND_UP(fdrv->buff_size, SZ_4K)));
|
|
#endif
|
|
if ((unsigned char *)temp_addr == NULL) {
|
|
IMSG_ERROR("[%s][%d]: Faile to alloc fdrv buffer failed.\n",
|
|
__FILE__, __LINE__);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0);
|
|
if (retVal != 0) {
|
|
IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__);
|
|
goto free_memory;
|
|
}
|
|
|
|
retVal = add_nq_entry(TEEI_CREAT_FDRV, fdrv->call_type,
|
|
(unsigned long long)(&boot_sema),
|
|
virt_to_phys((void *)temp_addr),
|
|
fdrv->buff_size, 0);
|
|
if (retVal != 0) {
|
|
IMSG_ERROR("TEEI: Failed to add one nq to n_t_buffer\n");
|
|
goto free_memory;
|
|
}
|
|
|
|
teei_notify_switch_fn();
|
|
|
|
down(&boot_sema);
|
|
|
|
fdrv->buf = (void *)temp_addr;
|
|
|
|
return 0;
|
|
|
|
free_memory:
|
|
free_pages((unsigned long)temp_addr,
|
|
get_order(ROUND_UP(fdrv->buff_size, SZ_4K)));
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void register_fdrv(struct teei_fdrv *fdrv)
|
|
{
|
|
list_add_tail(&fdrv->list, &fdrv_list);
|
|
}
|
|
EXPORT_SYMBOL(register_fdrv);
|
|
|
|
int fdrv_notify(struct teei_fdrv *fdrv)
|
|
{
|
|
struct completion *wait_completion = NULL;
|
|
int retVal = 0;
|
|
|
|
wait_completion = kmalloc(sizeof(struct completion), GFP_KERNEL);
|
|
|
|
init_completion(wait_completion);
|
|
|
|
teei_cpus_read_lock();
|
|
|
|
retVal = add_work_entry(SMC_CALL_TYPE, N_INVOKE_T_NQ, 0, 0, 0);
|
|
if (retVal != 0) {
|
|
IMSG_ERROR("TEEI: Failed to add_work_entry[%s]\n", __func__);
|
|
teei_cpus_read_unlock();
|
|
kfree(wait_completion);
|
|
return retVal;
|
|
}
|
|
|
|
retVal = add_nq_entry(TEEI_FDRV_CALL, fdrv->call_type,
|
|
(unsigned long long)(wait_completion),
|
|
fdrv->buff_size, 0, 0);
|
|
|
|
if (retVal != 0) {
|
|
IMSG_ERROR("TEEI: Failed to add one nq to n_t_buffer\n");
|
|
teei_cpus_read_unlock();
|
|
kfree(wait_completion);
|
|
return retVal;
|
|
}
|
|
|
|
teei_notify_switch_fn();
|
|
|
|
wait_for_completion(wait_completion);
|
|
|
|
teei_cpus_read_unlock();
|
|
|
|
kfree(wait_completion);
|
|
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL(fdrv_notify);
|
|
|
|
void teei_handle_fdrv_call(struct NQ_entry *entry)
|
|
{
|
|
struct completion *bp = NULL;
|
|
|
|
bp = (struct completion *)(entry->block_p);
|
|
if (bp == NULL) {
|
|
IMSG_ERROR("The block_p of entry is NULL!\n");
|
|
return;
|
|
}
|
|
|
|
complete(bp);
|
|
}
|
|
|
|
int create_all_fdrv(void)
|
|
{
|
|
struct teei_fdrv *fdrv;
|
|
int retVal = 0;
|
|
|
|
list_for_each_entry(fdrv, &fdrv_list, list) {
|
|
retVal = create_fdrv(fdrv);
|
|
|
|
if (retVal != 0)
|
|
return retVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|