📄 uboot_flash_dev.c
字号:
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm-generic/errno-base.h>
#include <linux/stddef.h>
#include <linux/delay.h>
#include "uboot_common.h"
#define FLASH_MAJOR 206
static loff_t flash_env_dev_llseek(struct file * file, loff_t offset, int orig)
{
/*
* orig 0: position from begning of flash
* orig 1: relative from current position
* orig 2: position from last flash address
*/
switch (orig)
{
case 0:
file->f_pos = offset;
break;
case 1:
file->f_pos += offset;
break;
case 2:
file->f_pos = CFG_FLASH_SIZE- offset; // FLASH SIZE = 0x1000000 = 16M bytes
break;
default:
return -EINVAL;
}
/* truncate position */
if (file->f_pos < 0)
{
file->f_pos = 0;
return(-EOVERFLOW);
}
if (file->f_pos >= CFG_FLASH_SIZE)
{
file->f_pos = CFG_FLASH_SIZE - 1;
return(-EOVERFLOW);
}
return ( file->f_pos );
}
extern void * memcpy(void * to, const void * from, size_t n);
static ssize_t flash_env_dev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
{
unsigned long temp_size;
unsigned long p;
p = file->f_pos;
while(count)
{
temp_size = count > CFG_MAIN_SECT_SIZE ? CFG_MAIN_SECT_SIZE : count;
memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+p), temp_size);
copy_to_user(buf, uboot_env_ptr, temp_size);
count -= temp_size;
p += temp_size;
buf += temp_size;
}
return 0;
}
static ssize_t flash_env_dev_write (struct file *file, const char __user *buf, size_t count,
loff_t *offset)
{
uboot_flash_info_t *info;
unsigned long p;
unsigned long temp_size;
unsigned long flash_sector_offset;
unsigned long flash_sector_offset_len;
unsigned long sector_addr;
unsigned long len;
unsigned long range, flashsize;
p = file->f_pos;
info=&uboot_flash_info[0];
flashsize = info->size;
while(count)
{
if ( p<0x10000 ) //in boot flash range
{
if (info->size == 0x400000)
{
flash_sector_offset = p & (CFG_BOOT_SECT_SIZE -1); // flash secotor size = 0x2000; get the offset in one flash sector
sector_addr = p & (CFG_FLASH_SIZE - CFG_BOOT_SECT_SIZE); //sector_addr =p & 0X3FE000
// printk("sector_addr = 0x%x!\n",sector_addr);
flash_sector_offset_len = CFG_BOOT_SECT_SIZE - flash_sector_offset;
temp_size = count > CFG_BOOT_SECT_SIZE ? CFG_BOOT_SECT_SIZE : count;
len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), CFG_BOOT_SECT_SIZE);
}
else if (info->size == 0x200000)//xusha add for 2M flash
{
if (p<0x4000)
{
range = CFG_BOOT_SECT_SIZE*2;
flash_sector_offset = p & (range -1);
sector_addr = p & (flashsize - range);
flash_sector_offset_len = range - flash_sector_offset;
temp_size = count > range ? range : count;
len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), range);
}
else if (p>=0x4000&&p<0x8000)
{
range = CFG_BOOT_SECT_SIZE;
flash_sector_offset = p & (range -1);
sector_addr = p & (flashsize - range);
flash_sector_offset_len = range - flash_sector_offset;
temp_size = count > range ? range : count;
len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), range);
}
else
{
range = CFG_BOOT_SECT_SIZE*4;
flash_sector_offset = p & (range -1);
sector_addr = p & (flashsize - range);
flash_sector_offset_len = range - flash_sector_offset;
temp_size = count > range ? range : count;
len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), range);
}
}
}
else if ( ( p>=0x10000 ) && ( p<CFG_FLASH_SIZE ) ) //in main flash range
{
flash_sector_offset = p & (CFG_MAIN_SECT_SIZE -1); // flash main secotor size = 0x10000; get the offset in one flash sector
sector_addr = p & (CFG_FLASH_SIZE - CFG_MAIN_SECT_SIZE); //sector_addr =p & 0X3F0000
// printk("sector_addr = 0x%x!\n",sector_addr);
flash_sector_offset_len = CFG_MAIN_SECT_SIZE - flash_sector_offset;
temp_size = count > CFG_MAIN_SECT_SIZE ? CFG_MAIN_SECT_SIZE : count;
len = temp_size > flash_sector_offset_len ? flash_sector_offset_len : temp_size;
//printk("len = 0x%x!\n",len);
memcpy(uboot_env_ptr, (void*)((unsigned long)uboot_flash_addr+ sector_addr), CFG_MAIN_SECT_SIZE);
}
copy_from_user((uboot_env_ptr+flash_sector_offset), buf, len);
//printk("uboot_env_ptr is :%s\n", uboot_env_ptr);
//printk("uboot_env_ptr+flash_sector_offset is :%s\n", uboot_env_ptr+flash_sector_offset);
uboot_saveenv(sector_addr);
count -= len;
p += len;
buf += len;
}
// printk("write flash done!\n");
return 0;
}
static int flash_env_dev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
return 0;
}
static int flash_env_dev_open(struct inode *inode, struct file *file)
{
uboot_env_ptr = (env_t *)kmalloc(CFG_MAIN_SECT_SIZE,GFP_KERNEL);
if (uboot_env_ptr == NULL)
{
printk("writing flash but kmalloc failue,return!\n");
return (-ENOMEM);
}
uboot_flash_init();
//printk("start flash_env device success\n");
return 0;
}
static int flash_env_dev_release(struct inode *inode, struct file *file)
{
kfree(uboot_env_ptr);
return 0;
}
static struct file_operations flash_env_dev_fops = {
.owner = THIS_MODULE,
.llseek = flash_env_dev_llseek,
.read = flash_env_dev_read,
.write = flash_env_dev_write,
.ioctl = flash_env_dev_ioctl,
.open = flash_env_dev_open,
.release = flash_env_dev_release,
};
static int __init flash_env_dev_init(void)
{
int res;
//printk("flash_env /dev entries driver\n");
res = register_chrdev(FLASH_MAJOR, "flash_env", &flash_env_dev_fops);
if(res)
goto flash_env_out;
init_pf7_interrupt();
devfs_mk_dir("flash_env");
return 0;
flash_env_out_unreg_chrdev:
unregister_chrdev(FLASH_MAJOR, "flash_env");
flash_env_out:
printk(KERN_ERR "%s: Driver Initialisation failed", __FILE__);
return res;
}
static void __exit flash_env_dev_exit(void)
{
devfs_remove("flash_env");
unregister_chrdev(FLASH_MAJOR,"flash_env");
}
MODULE_AUTHOR("Suntek-Polytek Inc.");
MODULE_DESCRIPTION("flash_env /dev entries driver");
MODULE_LICENSE("Copyright (c) Suntek-Polytek Inc.");
module_init(flash_env_dev_init);
module_exit(flash_env_dev_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -