kernel_samsung_a53x/security/samsung/mz/mz_mem.c
2024-06-15 16:02:09 -03:00

151 lines
4.1 KiB
C
Executable file

/*
* Copyright (c) 2021 Samsung Electronics Co., Ltd. All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*/
#include <linux/kconfig.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/random.h>
#include <linux/sched/task.h>
#include "mz_internal.h"
#include "mz_log.h"
#define ADDR_INIT_SIZE 56
#ifdef CONFIG_MZ_USE_TZDEV
static void *list_addr_mz;
#elif IS_ENABLED(CONFIG_MZ_USE_QSEECOM)
static void __iomem *list_addr_mz1;
static void __iomem *list_addr_mz2;
static void __iomem *list_addr_mz3;
#endif
bool addrset;
int mz_addr_init(void)
{
struct device_node *np;
#ifdef CONFIG_MZ_USE_TZDEV
struct resource res;
#endif
addr_list = NULL;
#ifdef CONFIG_MZ_USE_TZDEV
np = of_find_compatible_node(NULL, NULL, "sboot,mz");
if (unlikely(!np)) {
MZ_LOG(err_level_error, "unable to find DT imem sboot,mz node\n");
return -ENODEV;
}
if (of_address_to_resource(np, 0, &res)) {
MZ_LOG(err_level_error, "%s of_address_to_resource fail\n", __func__);
return -ENODEV;
}
list_addr_mz = phys_to_virt(res.start);
#elif IS_ENABLED(CONFIG_MZ_USE_QSEECOM)
np = of_find_compatible_node(NULL, NULL, "samsung,security_mz1");
if (unlikely(!np)) {
MZ_LOG(err_level_error, "unable to find DT imem samsung,security_mz1 node\n");
return -ENODEV;
}
list_addr_mz1 = of_iomap(np, 0);
if (unlikely(!list_addr_mz1)) {
MZ_LOG(err_level_error, "unable to map imem samsung,security_mz1 offset\n");
return -ENODEV;
}
np = of_find_compatible_node(NULL, NULL, "samsung,security_mz2");
if (unlikely(!np)) {
MZ_LOG(err_level_error, "unable to find DT imem samsung,security_mz2 node\n");
return -ENODEV;
}
list_addr_mz2 = of_iomap(np, 0);
if (unlikely(!list_addr_mz2)) {
MZ_LOG(err_level_error, "unable to map imem samsung,security_mz2 offset\n");
return -ENODEV;
}
np = of_find_compatible_node(NULL, NULL, "samsung,security_mz3");
if (unlikely(!np)) {
MZ_LOG(err_level_error, "unable to find DT imem samsung,security_mz3 node\n");
return -ENODEV;
}
list_addr_mz3 = of_iomap(np, 0);
if (unlikely(!list_addr_mz3)) {
MZ_LOG(err_level_error, "unable to map imem samsung,security_mz3 offset\n");
return -ENODEV;
}
MZ_LOG(err_level_debug, "list addr1 : 0x%pK(0x%llx)\n", list_addr_mz1,
(unsigned long long)virt_to_phys(list_addr_mz1));
MZ_LOG(err_level_debug, "list addr2 : 0x%pK(0x%llx)\n", list_addr_mz2,
(unsigned long long)virt_to_phys(list_addr_mz2));
MZ_LOG(err_level_debug, "list addr3 : 0x%pK(0x%llx)\n", list_addr_mz3,
(unsigned long long)virt_to_phys(list_addr_mz3));
#else
MZ_LOG(err_level_error, "%s no tz config\n", __func__);
#endif
addr_list = kmalloc(sizeof(uint64_t) * ADDR_INIT_SIZE, GFP_KERNEL);
addr_list[0] = 0;
get_random_bytes(&(addr_list[1]), sizeof(addr_list[1]) * 2);
addr_list_count_max = ADDR_INIT_SIZE;
MZ_LOG(err_level_debug, "%s iv %llx %llx\n", __func__, addr_list[1], addr_list[2]);
addrset = false;
return MZ_SUCCESS;
}
int set_mz_mem(void)
{
unsigned long long addr_list1, addr_list2;
uint32_t mz_magic = 0x4D5A4D5A;
MZ_LOG(err_level_debug, "set_mz_mem start\n");
if (!addr_list) {
MZ_LOG(err_level_error, "%s list_addr null\n", __func__);
return MZ_GENERAL_ERROR;
}
addr_list1 = (unsigned long long)virt_to_phys(addr_list);
addr_list2 = addr_list1 >> 32;
#ifdef CONFIG_MZ_USE_TZDEV
memcpy(list_addr_mz, &addr_list1, 4);
memcpy(list_addr_mz+4, &addr_list2, 4);
memcpy(list_addr_mz+8, &mz_magic, 4);
#elif IS_ENABLED(CONFIG_MZ_USE_QSEECOM)
if (unlikely(!list_addr_mz1) || unlikely(!list_addr_mz2) || unlikely(!list_addr_mz3)) {
MZ_LOG(err_level_error, "list_addr address unmapped\n");
return MZ_GENERAL_ERROR;
}
__raw_writel(addr_list1, list_addr_mz1);
__raw_writel(addr_list2, list_addr_mz2);
__raw_writel(mz_magic, list_addr_mz3);
#else
MZ_LOG(err_level_error, "%s mz_magic set fail\n", __func__);
#endif
MZ_LOG(err_level_debug, "addr_list addr : (0x%llx) (0x%llx) (0x%llx)\n",
addr_list1, addr_list2, (unsigned long long)virt_to_phys(addr_list));
addrset = true;
return MZ_SUCCESS;
}
bool isaddrset(void)
{
return addrset;
}