kernel-brax3-ubuntu-touch/drivers/misc/mediatek/ccci_util/ccci_util_boot_args.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

258 lines
6.7 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 MediaTek Inc.
*/
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/skbuff.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include "mt-plat/mtk_ccci_common.h"
#include "ccci_util_log.h"
#include "ccci_util_lib_main.h"
#define ARGS_KEY_VAL_KEY_SIZE 36
#define ARGS_KEY_VAL_BUF_NUM 8
#define ARGS_KEY_VAL_BUF_SIZE 4096
#define ARGS_KEY_VAL_MAX_KEY_NUM 73
struct args_key_val {
char key[ARGS_KEY_VAL_KEY_SIZE];
unsigned int key_size;
unsigned int val_size;
unsigned int source;
unsigned char *pdata;
};
static unsigned char *s_buf[ARGS_KEY_VAL_BUF_NUM];
static unsigned char *s_curr_ptr;
static unsigned int s_curr_buf_idx;
static unsigned int s_curr_buf_free;
static unsigned int s_args_num;
static unsigned int s_init_done;
static struct args_key_val s_args_tbl[ARGS_KEY_VAL_MAX_KEY_NUM];
static int is_key_exist(const char key[], unsigned int size)
{
unsigned int i;
for (i = 0; i < s_args_num; i++) {
if (s_args_tbl[i].key_size != size)
continue;
if (strncmp(s_args_tbl[i].key, key, size) == 0)
return i;
}
return -1;
}
int mtk_ccci_find_args_val(const char key[], unsigned char o_val[], unsigned int val_buf_size)
{
int idx;
unsigned int key_size;
if (!s_init_done) {
pr_info("ccci: %s(line:%d): Not init done\n", __func__, __LINE__);
return -1;
}
if (!key) {
pr_info("ccci: %s(line:%d): Key is NULL\n", __func__, __LINE__);
return -1;
}
key_size = strlen(key) + 1;
if (key_size > ARGS_KEY_VAL_KEY_SIZE) {
pr_info("ccci: %s(line:%d): Key[%s] size is too big\n", __func__, __LINE__, key);
return -1;
}
idx = is_key_exist(key, key_size);
if (idx < 0) {
pr_info("ccci: %s(line:%d): Key[%s] not exist\n", __func__, __LINE__, key);
return -1;
}
if (!o_val)
return (int)s_args_tbl[idx].val_size;
if (val_buf_size < s_args_tbl[idx].val_size) {
pr_info("ccci: %s(line:%d): Val buf size is not enough(%u:%u) for key[%s]\n",
__func__, __LINE__, s_args_tbl[idx].val_size, val_buf_size, key);
return -1;
}
if (s_args_tbl[idx].source == FROM_LK_TAG)
memcpy_fromio(o_val, s_args_tbl[idx].pdata, s_args_tbl[idx].val_size);
else
memcpy(o_val, s_args_tbl[idx].pdata, s_args_tbl[idx].val_size);
return (int)s_args_tbl[idx].val_size;
}
EXPORT_SYMBOL(mtk_ccci_find_args_val);
int mtk_ccci_add_new_args(const char key[], unsigned char val[],
unsigned int val_size, enum args_src source)
{
unsigned int align_sz;
unsigned int key_size;
if (!s_init_done) {
pr_info("ccci: %s(line:%d): Not init done\n", __func__, __LINE__);
return -1;
}
if (!key) {
pr_info("ccci: %s(line:%d): Key is NULL\n", __func__, __LINE__);
return -1;
}
key_size = strlen(key) + 1;
if (key_size > ARGS_KEY_VAL_KEY_SIZE) {
pr_info("ccci: %s(line:%d): Key size is too big\n", __func__, __LINE__);
return -1;
}
if (!val) {
pr_info("ccci: %s(line:%d): Val is NULL\n", __func__, __LINE__);
return -1;
}
if (is_key_exist(key, key_size) >= 0) {
pr_info("ccci: %s(line:%d): Get duplicate key: %s\n",
__func__, __LINE__, key);
return -1;
}
if (source == FROM_LK_TAG) {
memcpy(s_args_tbl[s_args_num].key, key, key_size);
s_args_tbl[s_args_num].key_size = key_size;
s_args_tbl[s_args_num].val_size = val_size;
s_args_tbl[s_args_num].pdata = val;
s_args_tbl[s_args_num].source = source;
s_args_num++;
return (int)val_size;
}
if (val_size > ARGS_KEY_VAL_BUF_SIZE) {
pr_info("ccci: %s(line:%d): Val size is too big\n", __func__, __LINE__);
return -1;
}
if (val_size > s_curr_buf_free) {
s_curr_buf_idx++;
if (s_curr_buf_idx >= ARGS_KEY_VAL_BUF_NUM) {
pr_info("ccci: %s(line:%d): buff number is %d\n",
__func__, __LINE__, ARGS_KEY_VAL_BUF_NUM);
return -1;
}
s_buf[s_curr_buf_idx] = kmalloc(ARGS_KEY_VAL_BUF_SIZE, GFP_KERNEL);
if (!s_buf[s_curr_buf_idx])
return -1;
s_curr_buf_free = ARGS_KEY_VAL_BUF_SIZE;
s_curr_ptr = s_buf[s_curr_buf_idx];
}
memcpy(s_args_tbl[s_args_num].key, key, key_size);
memcpy(s_curr_ptr, val, val_size);
s_args_tbl[s_args_num].key_size = key_size;
s_args_tbl[s_args_num].val_size = val_size;
s_args_tbl[s_args_num].pdata = s_curr_ptr;
s_args_tbl[s_args_num].source = source;
s_args_num++;
align_sz = (val_size + 8) & (~7);
s_curr_ptr += val_size + align_sz;
if (s_curr_buf_free > (val_size + align_sz))
s_curr_buf_free = s_curr_buf_free - val_size - align_sz;
else
s_curr_buf_free = 0;
return (int)val_size;
}
EXPORT_SYMBOL(mtk_ccci_add_new_args);
int mtk_ccci_args_key_val_init(void)
{
struct device_node *node = NULL;
int ret = 0;
unsigned int dt_value = 0;
s_curr_buf_idx = 0;
s_buf[s_curr_buf_idx] = kmalloc(ARGS_KEY_VAL_BUF_SIZE, GFP_KERNEL);
if (!s_buf[s_curr_buf_idx])
return -1;
s_curr_ptr = s_buf[s_curr_buf_idx];
s_curr_buf_free = ARGS_KEY_VAL_BUF_SIZE;
s_args_num = 0;
s_init_done = 1;
/* Add md relate dts info to args table */
node = of_find_compatible_node(NULL, NULL, "mediatek,mddriver");
if (!node) {
CCCI_UTIL_INF_MSG("Legacy chip: mediatek,mddriver node not support\n");
return -1;
}
// From dts: AP Platform
ret = of_property_read_u32(node, "mediatek,ap-plat-info", &dt_value);
if (ret < 0)
CCCI_UTIL_INF_MSG("Attr: [mediatek,ap-plat-info] not support\n");
else
mtk_ccci_add_new_args("ap_platform", (unsigned char *)&dt_value,
(unsigned int)sizeof(unsigned int), FROM_KERNEL);
// From dts: MD Generation
dt_value = 0;
ret = of_property_read_u32(node, "mediatek,md-generation", &dt_value);
if (ret < 0)
CCCI_UTIL_INF_MSG("Attr: [mediatek,md-generation] not support\n");
else
mtk_ccci_add_new_args("md_generation", (unsigned char *)&dt_value,
(unsigned int)sizeof(unsigned int), FROM_KERNEL);
return 0;
}
void mtk_ccci_dump_args_info(void)
{
unsigned int i;
unsigned int *ptr = NULL;
unsigned char *ch;
CCCI_UTIL_INF_MSG("------ Dump args: [key]:[val] --------\n");
for (i = 0; i < s_args_num; i++) {
if (strncmp(s_args_tbl[i].key, "err_trace", 9) == 0) {
s_args_tbl[i].pdata[s_args_tbl[i].val_size] = 0;
CCCI_UTIL_INF_MSG("<key>[err_trace(%u)]:[%s]\n", s_args_tbl[i].val_size,
s_args_tbl[i].pdata);
} else {
if (s_args_tbl[i].val_size >= 8) {
ptr = (unsigned int *)s_args_tbl[i].pdata;
CCCI_UTIL_INF_MSG("<key>[%s(%u)]:[%x:%x]\n", s_args_tbl[i].key,
s_args_tbl[i].val_size, ptr[0], ptr[1]);
} else if (s_args_tbl[i].val_size >= 4) {
ptr = (unsigned int *)s_args_tbl[i].pdata;
CCCI_UTIL_INF_MSG("<key>[%s(%u)]:[%x]\n", s_args_tbl[i].key,
s_args_tbl[i].val_size, ptr[0]);
} else {
ch = (unsigned char *)s_args_tbl[i].pdata;
CCCI_UTIL_INF_MSG("<key>[%s(%u)]:[%x]\n", s_args_tbl[i].key,
s_args_tbl[i].val_size, (unsigned int)(*ch));
}
}
}
}