You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
kernel_samsung_sm7125/drivers/samsung/sec_sysup.c

188 lines
4.1 KiB

/*
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Samsung TN debugging code
*
* 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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ":%s() " fmt, __func__
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/sec_param.h>
#include <linux/sec_class.h>
#define SEC_EDTBO_FILENAME "/spu/edtbo/edtbo.img"
#define EDTBO_FIEMAP_MAGIC 0x7763
#define EDTBO_FIEMAP_COUNT 128
static unsigned long edtbo_ver = 0;
static int __init init_sysup_edtbo(char *str)
{
edtbo_ver = simple_strtoul(str, NULL, 10);
return 0;
}
early_param("androidboot.edtbo", init_sysup_edtbo);
static int fiemap_chk_ranges(struct super_block *sb,
u64 start, u64 len, u64 *new_len)
{
u64 maxbytes = (u64) sb->s_maxbytes;
*new_len = len;
if (len == 0)
return -EINVAL;
if (start > maxbytes)
return -EFBIG;
/*
* Shrink request scope to what the fs can actually handle.
*/
if (len > maxbytes || (maxbytes - len) < start)
*new_len = maxbytes - start;
return 0;
}
static ssize_t sec_edtbo_update_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
struct fiemap *pfiemap;
struct fiemap_extent_info fieinfo = { 0, };
struct file *fp;
mm_segment_t old_fs;
struct inode *inode;
u64 len;
int update, error;
u32 allocsize = 0;
u32 fiemap_magic = EDTBO_FIEMAP_MAGIC;
error = sscanf(buf, "%d", &update);
if (error < 0 || update != 1)
return -EINVAL;
old_fs = get_fs();
set_fs(KERNEL_DS);
fp = filp_open(SEC_EDTBO_FILENAME, O_RDONLY, S_IRUSR);
if (IS_ERR(fp)) {
pr_err("file open error\n");
error = -ENOENT;
goto fp_err;
}
inode = file_inode(fp);
if (!inode->i_op->fiemap) {
error = -EOPNOTSUPP;
goto open_err;
}
allocsize = EDTBO_FIEMAP_COUNT * sizeof(struct fiemap_extent) + offsetof(struct fiemap, fm_extents);
pfiemap = kmalloc(allocsize, GFP_KERNEL | __GFP_ZERO);
if (!pfiemap) {
error = -ENOMEM;
goto open_err;
}
pfiemap->fm_length = ULONG_MAX;
pfiemap->fm_extent_count = EDTBO_FIEMAP_COUNT;
error = fiemap_chk_ranges(inode->i_sb, pfiemap->fm_start, pfiemap->fm_length, &len);
if (error)
goto alloc_err;
fieinfo.fi_flags = pfiemap->fm_flags;
fieinfo.fi_extents_max = pfiemap->fm_extent_count;
fieinfo.fi_extents_start = pfiemap->fm_extents;
error = inode->i_op->fiemap(inode, &fieinfo, pfiemap->fm_start, len);
if (error)
goto alloc_err;
pfiemap->fm_flags = fieinfo.fi_flags;
pfiemap->fm_mapped_extents = fieinfo.fi_extents_mapped;
if (!pfiemap->fm_mapped_extents) {
error = -EFAULT;
goto alloc_err;
}
sec_set_param(param_index_fiemap_result, pfiemap);
sec_set_param(param_index_fiemap_update, &fiemap_magic);
error = size;
alloc_err:
if (pfiemap)
kfree(pfiemap);
open_err:
filp_close(fp, NULL);
fp_err:
set_fs(old_fs);
return error;
}
static ssize_t sec_edtbo_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%lu\n", edtbo_ver);
}
static struct device_attribute sec_sysup_edtbo_update_attr =
__ATTR(edtbo_update, 0220, NULL, sec_edtbo_update_store);
static struct device_attribute sec_sysup_edtbo_version_attr =
__ATTR(edtbo_version, 0440, sec_edtbo_version_show, NULL);
static struct attribute *sec_sysup_attributes[] = {
&sec_sysup_edtbo_update_attr.attr,
&sec_sysup_edtbo_version_attr.attr,
NULL,
};
static struct attribute_group sec_sysup_attr_group = {
.attrs = sec_sysup_attributes,
};
static int __init sec_sysup_init(void)
{
int ret = 0;
struct device *dev;
pr_info("start\n");
dev = ___sec_device_create(NULL, "sec_sysup");
if(!dev)
pr_err("sec device create failed!\n");
ret = sysfs_create_group(&dev->kobj, &sec_sysup_attr_group);
if (ret)
pr_err("could not create sysfs node\n");
return 0;
}
static void __exit sec_sysup_exit(void)
{
pr_info("exit\n");
}
module_init(sec_sysup_init);
module_exit(sec_sysup_exit);