techpack: audio: aw882xxacf: Load calibration file through firmware class

Direct access to filesystem is insane and hits a neverallow, load it
through the firmware class instead.

Co-authored-by: Michael Bestas <mkbestas@lineageos.org>
Change-Id: Ic522644c73d63a36430526736257d635deb08f6a
This commit is contained in:
dianlujitao 2022-02-02 23:37:08 +08:00 • committed by Michael Bestas
commit 63b35288f8
No known key found for this signature in database
3 changed files with 33 additions and 55 deletions

View file

@ -20,6 +20,7 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <sound/core.h>
@ -47,20 +48,12 @@ static unsigned int g_cali_status = false;
static struct miscdevice *g_misc_dev = NULL;
static DEFINE_MUTEX(g_cali_lock);
#ifdef AW_CALI_STORE_EXAMPLE
/*write cali to persist file example*/
#define AWINIC_CALI_FILE "/mnt/vendor/persist/factory/audio/aw_cali.bin"
#define AWINIC_CALI_FILE "aw_cali.bin"
#define AW_INT_DEC_DIGIT 10
static void aw_fs_read(struct file *file, char *buf, size_t count, loff_t *pos)
{
#ifdef AW_KERNEL_VER_OVER_5_4_0
kernel_read(file, buf, count, pos);
#else
vfs_read(file, buf, count, pos);
#endif
}
#ifdef AW_CALI_STORE_EXAMPLE
/*write cali to persist file example*/
#define AWINIC_CALI_PERSIST_FILE "/mnt/vendor/persist/factory/audio/aw_cali.bin"
static void aw_fs_write(struct file *file, char *buf, size_t count, loff_t *pos)
{
#ifdef AW_KERNEL_VER_OVER_5_4_0
@ -77,7 +70,7 @@ static int aw_cali_write_cali_re_to_file(int32_t cali_re, int channel)
loff_t pos = 0;
mm_segment_t fs;
fp = filp_open(AWINIC_CALI_FILE, O_RDWR | O_CREAT, 0644);
fp = filp_open(AWINIC_CALI_PERSIST_FILE, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
pr_err("%s:channel:%d open %s failed!\n",
__func__, channel, AWINIC_CALI_FILE);
@ -101,60 +94,49 @@ static int aw_cali_write_cali_re_to_file(int32_t cali_re, int channel)
filp_close(fp, NULL);
return 0;
}
#endif
static int aw_cali_get_read_cali_re(int32_t *cali_re, int channel)
static int aw_cali_get_read_cali_re(struct aw_device *aw_dev, int32_t *cali_re, int channel)
{
struct file *fp = NULL;
/*struct inode *node;*/
int f_size;
char *buf = NULL;
int rc = -EINVAL;
int32_t int_cali_re = 0;
loff_t pos = 0;
mm_segment_t fs;
const struct firmware *fw = NULL;
fp = filp_open(AWINIC_CALI_FILE, O_RDONLY, 0);
if (IS_ERR(fp)) {
/* open cali file */
if (request_firmware(&fw, AWINIC_CALI_FILE, aw_dev->dev)) {
pr_err("%s:channel:%d open %s failed!\n",
__func__, channel, AWINIC_CALI_FILE);
return -EINVAL;
return rc;
}
if (!fw || !fw->data || !fw->size) {
pr_err("%s: invalid firmware", __func__);
goto error;
}
if (fw->size < AW_INT_DEC_DIGIT || fw->size > AW_INT_DEC_DIGIT * 2) {
pr_err("%s: invalid firmware size\n", __func__);
goto error;
}
pos = AW_INT_DEC_DIGIT * channel;
/*node = fp->f_dentry->d_inode;*/
/*f_size = node->i_size;*/
f_size = AW_INT_DEC_DIGIT;
buf = kzalloc(f_size + 1, GFP_ATOMIC);
if (!buf) {
pr_err("%s: channel:%d malloc mem %d failed!\n",
__func__, channel, f_size);
filp_close(fp, NULL);
return -EINVAL;
}
fs = get_fs();
set_fs(KERNEL_DS);
aw_fs_read(fp, buf, f_size, &pos);
set_fs(fs);
if (sscanf(buf, "%d", &int_cali_re) == 1)
if (sscanf(fw->data + pos, "%d", &int_cali_re) == 1)
*cali_re = int_cali_re;
else
*cali_re = AW_ERRO_CALI_VALUE;
pr_info("%s: channel:%d buf:%s int_cali_re: %d\n",
__func__, channel, buf, int_cali_re);
pr_info("%s: channel:%d int_cali_re: %d\n",
__func__, channel, int_cali_re);
kfree(buf);
buf = NULL;
filp_close(fp, NULL);
rc = 0;
return 0;
error:
/* close file */
release_firmware(fw);
return rc;
}
#endif
/*custom need add to set/get cali_re form/to nv*/
int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
@ -170,18 +152,14 @@ int aw_cali_write_re_to_nvram(int32_t cali_re, int32_t channel)
#endif
}
int aw_cali_read_re_from_nvram(int32_t *cali_re, int32_t channel)
int aw_cali_read_re_from_nvram(struct aw_device *aw_dev, int32_t *cali_re, int32_t channel)
{
/*custom add, if success return value is 0 , else -1*/
#ifdef AW_CALI_STORE_EXAMPLE
if (channel >= AW_DEV_CH_MAX) {
pr_err("%s: unsupported channel [%d] \n", __func__, channel);
return -EINVAL;
}
return aw_cali_get_read_cali_re(cali_re, channel);
#else
return 0;
#endif
return aw_cali_get_read_cali_re(aw_dev, cali_re, channel);
}
int aw_cali_store_cali_re(struct aw_device *aw_dev, int32_t re)

View file

@ -136,7 +136,7 @@ struct aw_cali_desc {
int aw_cali_init(struct aw_cali_desc *cali_desc);
void aw_cali_deinit(struct aw_cali_desc *cali_desc);
int aw_cali_svc_get_cali_status(void);
int aw_cali_read_re_from_nvram(int32_t *cali_re, int32_t ch_index);
int aw_cali_read_re_from_nvram(struct aw_device *aw_dev, int32_t *cali_re, int32_t ch_index);
#endif

View file

@ -1509,7 +1509,7 @@ int aw_dev_init_cali_re(struct aw_device *aw_dev)
if (aw_dev->cali_desc.mode) {
if (aw_dev->cali_desc.cali_re == AW_ERRO_CALI_VALUE) {
ret = aw_cali_read_re_from_nvram(&aw_dev->cali_desc.cali_re, aw_dev->channel);
ret = aw_cali_read_re_from_nvram(aw_dev, &aw_dev->cali_desc.cali_re, aw_dev->channel);
if (ret) {
aw_dev_info(aw_dev->dev, "read nvram cali failed, use default Re");
aw_dev->cali_desc.cali_re = AW_ERRO_CALI_VALUE;