Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * CMOS/NV-RAM driver for Linux
0004  *
0005  * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
0006  * idea by and with help from Richard Jelinek <rj@suse.de>
0007  * Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com)
0008  *
0009  * This driver allows you to access the contents of the non-volatile memory in
0010  * the mc146818rtc.h real-time clock. This chip is built into all PCs and into
0011  * many Atari machines. In the former it's called "CMOS-RAM", in the latter
0012  * "NVRAM" (NV stands for non-volatile).
0013  *
0014  * The data are supplied as a (seekable) character device, /dev/nvram. The
0015  * size of this file is dependent on the controller.  The usual size is 114,
0016  * the number of freely available bytes in the memory (i.e., not used by the
0017  * RTC itself).
0018  *
0019  * Checksums over the NVRAM contents are managed by this driver. In case of a
0020  * bad checksum, reads and writes return -EIO. The checksum can be initialized
0021  * to a sane state either by ioctl(NVRAM_INIT) (clear whole NVRAM) or
0022  * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid
0023  * again; use with care!)
0024  *
0025  *  1.1 Cesar Barros: SMP locking fixes
0026  *      added changelog
0027  *  1.2 Erik Gilling: Cobalt Networks support
0028  *      Tim Hockin: general cleanup, Cobalt support
0029  *  1.3 Wim Van Sebroeck: convert PRINT_PROC to seq_file
0030  */
0031 
0032 #define NVRAM_VERSION   "1.3"
0033 
0034 #include <linux/module.h>
0035 #include <linux/nvram.h>
0036 #include <linux/types.h>
0037 #include <linux/errno.h>
0038 #include <linux/miscdevice.h>
0039 #include <linux/ioport.h>
0040 #include <linux/fcntl.h>
0041 #include <linux/mc146818rtc.h>
0042 #include <linux/init.h>
0043 #include <linux/proc_fs.h>
0044 #include <linux/seq_file.h>
0045 #include <linux/slab.h>
0046 #include <linux/spinlock.h>
0047 #include <linux/io.h>
0048 #include <linux/uaccess.h>
0049 #include <linux/mutex.h>
0050 #include <linux/pagemap.h>
0051 
0052 #ifdef CONFIG_PPC
0053 #include <asm/nvram.h>
0054 #endif
0055 
0056 static DEFINE_MUTEX(nvram_mutex);
0057 static DEFINE_SPINLOCK(nvram_state_lock);
0058 static int nvram_open_cnt;  /* #times opened */
0059 static int nvram_open_mode; /* special open modes */
0060 static ssize_t nvram_size;
0061 #define NVRAM_WRITE     1 /* opened for writing (exclusive) */
0062 #define NVRAM_EXCL      2 /* opened with O_EXCL */
0063 
0064 #ifdef CONFIG_X86
0065 /*
0066  * These functions are provided to be called internally or by other parts of
0067  * the kernel. It's up to the caller to ensure correct checksum before reading
0068  * or after writing (needs to be done only once).
0069  *
0070  * It is worth noting that these functions all access bytes of general
0071  * purpose memory in the NVRAM - that is to say, they all add the
0072  * NVRAM_FIRST_BYTE offset.  Pass them offsets into NVRAM as if you did not
0073  * know about the RTC cruft.
0074  */
0075 
0076 #define NVRAM_BYTES     (128 - NVRAM_FIRST_BYTE)
0077 
0078 /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
0079  * rtc_lock held. Due to the index-port/data-port design of the RTC, we
0080  * don't want two different things trying to get to it at once. (e.g. the
0081  * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
0082  */
0083 
0084 static unsigned char __nvram_read_byte(int i)
0085 {
0086     return CMOS_READ(NVRAM_FIRST_BYTE + i);
0087 }
0088 
0089 static unsigned char pc_nvram_read_byte(int i)
0090 {
0091     unsigned long flags;
0092     unsigned char c;
0093 
0094     spin_lock_irqsave(&rtc_lock, flags);
0095     c = __nvram_read_byte(i);
0096     spin_unlock_irqrestore(&rtc_lock, flags);
0097     return c;
0098 }
0099 
0100 /* This races nicely with trying to read with checksum checking (nvram_read) */
0101 static void __nvram_write_byte(unsigned char c, int i)
0102 {
0103     CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
0104 }
0105 
0106 static void pc_nvram_write_byte(unsigned char c, int i)
0107 {
0108     unsigned long flags;
0109 
0110     spin_lock_irqsave(&rtc_lock, flags);
0111     __nvram_write_byte(c, i);
0112     spin_unlock_irqrestore(&rtc_lock, flags);
0113 }
0114 
0115 /* On PCs, the checksum is built only over bytes 2..31 */
0116 #define PC_CKS_RANGE_START  2
0117 #define PC_CKS_RANGE_END    31
0118 #define PC_CKS_LOC      32
0119 
0120 static int __nvram_check_checksum(void)
0121 {
0122     int i;
0123     unsigned short sum = 0;
0124     unsigned short expect;
0125 
0126     for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
0127         sum += __nvram_read_byte(i);
0128     expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
0129         __nvram_read_byte(PC_CKS_LOC+1);
0130     return (sum & 0xffff) == expect;
0131 }
0132 
0133 static void __nvram_set_checksum(void)
0134 {
0135     int i;
0136     unsigned short sum = 0;
0137 
0138     for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
0139         sum += __nvram_read_byte(i);
0140     __nvram_write_byte(sum >> 8, PC_CKS_LOC);
0141     __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
0142 }
0143 
0144 static long pc_nvram_set_checksum(void)
0145 {
0146     spin_lock_irq(&rtc_lock);
0147     __nvram_set_checksum();
0148     spin_unlock_irq(&rtc_lock);
0149     return 0;
0150 }
0151 
0152 static long pc_nvram_initialize(void)
0153 {
0154     ssize_t i;
0155 
0156     spin_lock_irq(&rtc_lock);
0157     for (i = 0; i < NVRAM_BYTES; ++i)
0158         __nvram_write_byte(0, i);
0159     __nvram_set_checksum();
0160     spin_unlock_irq(&rtc_lock);
0161     return 0;
0162 }
0163 
0164 static ssize_t pc_nvram_get_size(void)
0165 {
0166     return NVRAM_BYTES;
0167 }
0168 
0169 static ssize_t pc_nvram_read(char *buf, size_t count, loff_t *ppos)
0170 {
0171     char *p = buf;
0172     loff_t i;
0173 
0174     spin_lock_irq(&rtc_lock);
0175     if (!__nvram_check_checksum()) {
0176         spin_unlock_irq(&rtc_lock);
0177         return -EIO;
0178     }
0179     for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
0180         *p = __nvram_read_byte(i);
0181     spin_unlock_irq(&rtc_lock);
0182 
0183     *ppos = i;
0184     return p - buf;
0185 }
0186 
0187 static ssize_t pc_nvram_write(char *buf, size_t count, loff_t *ppos)
0188 {
0189     char *p = buf;
0190     loff_t i;
0191 
0192     spin_lock_irq(&rtc_lock);
0193     if (!__nvram_check_checksum()) {
0194         spin_unlock_irq(&rtc_lock);
0195         return -EIO;
0196     }
0197     for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
0198         __nvram_write_byte(*p, i);
0199     __nvram_set_checksum();
0200     spin_unlock_irq(&rtc_lock);
0201 
0202     *ppos = i;
0203     return p - buf;
0204 }
0205 
0206 const struct nvram_ops arch_nvram_ops = {
0207     .read           = pc_nvram_read,
0208     .write          = pc_nvram_write,
0209     .read_byte      = pc_nvram_read_byte,
0210     .write_byte     = pc_nvram_write_byte,
0211     .get_size       = pc_nvram_get_size,
0212     .set_checksum   = pc_nvram_set_checksum,
0213     .initialize     = pc_nvram_initialize,
0214 };
0215 EXPORT_SYMBOL(arch_nvram_ops);
0216 #endif /* CONFIG_X86 */
0217 
0218 /*
0219  * The are the file operation function for user access to /dev/nvram
0220  */
0221 
0222 static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin)
0223 {
0224     return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
0225                     nvram_size);
0226 }
0227 
0228 static ssize_t nvram_misc_read(struct file *file, char __user *buf,
0229                    size_t count, loff_t *ppos)
0230 {
0231     char *tmp;
0232     ssize_t ret;
0233 
0234 
0235     if (*ppos >= nvram_size)
0236         return 0;
0237 
0238     count = min_t(size_t, count, nvram_size - *ppos);
0239     count = min_t(size_t, count, PAGE_SIZE);
0240 
0241     tmp = kmalloc(count, GFP_KERNEL);
0242     if (!tmp)
0243         return -ENOMEM;
0244 
0245     ret = nvram_read(tmp, count, ppos);
0246     if (ret <= 0)
0247         goto out;
0248 
0249     if (copy_to_user(buf, tmp, ret)) {
0250         *ppos -= ret;
0251         ret = -EFAULT;
0252     }
0253 
0254 out:
0255     kfree(tmp);
0256     return ret;
0257 }
0258 
0259 static ssize_t nvram_misc_write(struct file *file, const char __user *buf,
0260                 size_t count, loff_t *ppos)
0261 {
0262     char *tmp;
0263     ssize_t ret;
0264 
0265     if (*ppos >= nvram_size)
0266         return 0;
0267 
0268     count = min_t(size_t, count, nvram_size - *ppos);
0269     count = min_t(size_t, count, PAGE_SIZE);
0270 
0271     tmp = memdup_user(buf, count);
0272     if (IS_ERR(tmp))
0273         return PTR_ERR(tmp);
0274 
0275     ret = nvram_write(tmp, count, ppos);
0276     kfree(tmp);
0277     return ret;
0278 }
0279 
0280 static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
0281                  unsigned long arg)
0282 {
0283     long ret = -ENOTTY;
0284 
0285     switch (cmd) {
0286 #ifdef CONFIG_PPC
0287     case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
0288         pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
0289         fallthrough;
0290     case IOC_NVRAM_GET_OFFSET:
0291         ret = -EINVAL;
0292 #ifdef CONFIG_PPC_PMAC
0293         if (machine_is(powermac)) {
0294             int part, offset;
0295 
0296             if (copy_from_user(&part, (void __user *)arg,
0297                        sizeof(part)) != 0)
0298                 return -EFAULT;
0299             if (part < pmac_nvram_OF || part > pmac_nvram_NR)
0300                 return -EINVAL;
0301             offset = pmac_get_partition(part);
0302             if (offset < 0)
0303                 return -EINVAL;
0304             if (copy_to_user((void __user *)arg,
0305                      &offset, sizeof(offset)) != 0)
0306                 return -EFAULT;
0307             ret = 0;
0308         }
0309 #endif
0310         break;
0311 #ifdef CONFIG_PPC32
0312     case IOC_NVRAM_SYNC:
0313         if (ppc_md.nvram_sync != NULL) {
0314             mutex_lock(&nvram_mutex);
0315             ppc_md.nvram_sync();
0316             mutex_unlock(&nvram_mutex);
0317         }
0318         ret = 0;
0319         break;
0320 #endif
0321 #elif defined(CONFIG_X86) || defined(CONFIG_M68K)
0322     case NVRAM_INIT:
0323         /* initialize NVRAM contents and checksum */
0324         if (!capable(CAP_SYS_ADMIN))
0325             return -EACCES;
0326 
0327         if (arch_nvram_ops.initialize != NULL) {
0328             mutex_lock(&nvram_mutex);
0329             ret = arch_nvram_ops.initialize();
0330             mutex_unlock(&nvram_mutex);
0331         }
0332         break;
0333     case NVRAM_SETCKS:
0334         /* just set checksum, contents unchanged (maybe useful after
0335          * checksum garbaged somehow...) */
0336         if (!capable(CAP_SYS_ADMIN))
0337             return -EACCES;
0338 
0339         if (arch_nvram_ops.set_checksum != NULL) {
0340             mutex_lock(&nvram_mutex);
0341             ret = arch_nvram_ops.set_checksum();
0342             mutex_unlock(&nvram_mutex);
0343         }
0344         break;
0345 #endif /* CONFIG_X86 || CONFIG_M68K */
0346     }
0347     return ret;
0348 }
0349 
0350 static int nvram_misc_open(struct inode *inode, struct file *file)
0351 {
0352     spin_lock(&nvram_state_lock);
0353 
0354     /* Prevent multiple readers/writers if desired. */
0355     if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
0356         (nvram_open_mode & NVRAM_EXCL)) {
0357         spin_unlock(&nvram_state_lock);
0358         return -EBUSY;
0359     }
0360 
0361 #if defined(CONFIG_X86) || defined(CONFIG_M68K)
0362     /* Prevent multiple writers if the set_checksum ioctl is implemented. */
0363     if ((arch_nvram_ops.set_checksum != NULL) &&
0364         (file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE)) {
0365         spin_unlock(&nvram_state_lock);
0366         return -EBUSY;
0367     }
0368 #endif
0369 
0370     if (file->f_flags & O_EXCL)
0371         nvram_open_mode |= NVRAM_EXCL;
0372     if (file->f_mode & FMODE_WRITE)
0373         nvram_open_mode |= NVRAM_WRITE;
0374     nvram_open_cnt++;
0375 
0376     spin_unlock(&nvram_state_lock);
0377 
0378     return 0;
0379 }
0380 
0381 static int nvram_misc_release(struct inode *inode, struct file *file)
0382 {
0383     spin_lock(&nvram_state_lock);
0384 
0385     nvram_open_cnt--;
0386 
0387     /* if only one instance is open, clear the EXCL bit */
0388     if (nvram_open_mode & NVRAM_EXCL)
0389         nvram_open_mode &= ~NVRAM_EXCL;
0390     if (file->f_mode & FMODE_WRITE)
0391         nvram_open_mode &= ~NVRAM_WRITE;
0392 
0393     spin_unlock(&nvram_state_lock);
0394 
0395     return 0;
0396 }
0397 
0398 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
0399 static const char * const floppy_types[] = {
0400     "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M",
0401     "3.5'' 2.88M", "3.5'' 2.88M"
0402 };
0403 
0404 static const char * const gfx_types[] = {
0405     "EGA, VGA, ... (with BIOS)",
0406     "CGA (40 cols)",
0407     "CGA (80 cols)",
0408     "monochrome",
0409 };
0410 
0411 static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,
0412                    void *offset)
0413 {
0414     int checksum;
0415     int type;
0416 
0417     spin_lock_irq(&rtc_lock);
0418     checksum = __nvram_check_checksum();
0419     spin_unlock_irq(&rtc_lock);
0420 
0421     seq_printf(seq, "Checksum status: %svalid\n", checksum ? "" : "not ");
0422 
0423     seq_printf(seq, "# floppies     : %d\n",
0424         (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
0425     seq_printf(seq, "Floppy 0 type  : ");
0426     type = nvram[2] >> 4;
0427     if (type < ARRAY_SIZE(floppy_types))
0428         seq_printf(seq, "%s\n", floppy_types[type]);
0429     else
0430         seq_printf(seq, "%d (unknown)\n", type);
0431     seq_printf(seq, "Floppy 1 type  : ");
0432     type = nvram[2] & 0x0f;
0433     if (type < ARRAY_SIZE(floppy_types))
0434         seq_printf(seq, "%s\n", floppy_types[type]);
0435     else
0436         seq_printf(seq, "%d (unknown)\n", type);
0437 
0438     seq_printf(seq, "HD 0 type      : ");
0439     type = nvram[4] >> 4;
0440     if (type)
0441         seq_printf(seq, "%02x\n", type == 0x0f ? nvram[11] : type);
0442     else
0443         seq_printf(seq, "none\n");
0444 
0445     seq_printf(seq, "HD 1 type      : ");
0446     type = nvram[4] & 0x0f;
0447     if (type)
0448         seq_printf(seq, "%02x\n", type == 0x0f ? nvram[12] : type);
0449     else
0450         seq_printf(seq, "none\n");
0451 
0452     seq_printf(seq, "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
0453         nvram[18] | (nvram[19] << 8),
0454         nvram[20], nvram[25],
0455         nvram[21] | (nvram[22] << 8), nvram[23] | (nvram[24] << 8));
0456     seq_printf(seq, "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
0457         nvram[39] | (nvram[40] << 8),
0458         nvram[41], nvram[46],
0459         nvram[42] | (nvram[43] << 8), nvram[44] | (nvram[45] << 8));
0460 
0461     seq_printf(seq, "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8));
0462     seq_printf(seq, "Extended memory: %d kB (configured), %d kB (tested)\n",
0463         nvram[9] | (nvram[10] << 8), nvram[34] | (nvram[35] << 8));
0464 
0465     seq_printf(seq, "Gfx adapter    : %s\n",
0466         gfx_types[(nvram[6] >> 4) & 3]);
0467 
0468     seq_printf(seq, "FPU            : %sinstalled\n",
0469         (nvram[6] & 2) ? "" : "not ");
0470 
0471     return;
0472 }
0473 
0474 static int nvram_proc_read(struct seq_file *seq, void *offset)
0475 {
0476     unsigned char contents[NVRAM_BYTES];
0477     int i = 0;
0478 
0479     spin_lock_irq(&rtc_lock);
0480     for (i = 0; i < NVRAM_BYTES; ++i)
0481         contents[i] = __nvram_read_byte(i);
0482     spin_unlock_irq(&rtc_lock);
0483 
0484     pc_nvram_proc_read(contents, seq, offset);
0485 
0486     return 0;
0487 }
0488 #endif /* CONFIG_X86 && CONFIG_PROC_FS */
0489 
0490 static const struct file_operations nvram_misc_fops = {
0491     .owner      = THIS_MODULE,
0492     .llseek     = nvram_misc_llseek,
0493     .read       = nvram_misc_read,
0494     .write      = nvram_misc_write,
0495     .unlocked_ioctl = nvram_misc_ioctl,
0496     .open       = nvram_misc_open,
0497     .release    = nvram_misc_release,
0498 };
0499 
0500 static struct miscdevice nvram_misc = {
0501     NVRAM_MINOR,
0502     "nvram",
0503     &nvram_misc_fops,
0504 };
0505 
0506 static int __init nvram_module_init(void)
0507 {
0508     int ret;
0509 
0510     nvram_size = nvram_get_size();
0511     if (nvram_size < 0)
0512         return nvram_size;
0513 
0514     ret = misc_register(&nvram_misc);
0515     if (ret) {
0516         pr_err("nvram: can't misc_register on minor=%d\n", NVRAM_MINOR);
0517         return ret;
0518     }
0519 
0520 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
0521     if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) {
0522         pr_err("nvram: can't create /proc/driver/nvram\n");
0523         misc_deregister(&nvram_misc);
0524         return -ENOMEM;
0525     }
0526 #endif
0527 
0528     pr_info("Non-volatile memory driver v" NVRAM_VERSION "\n");
0529     return 0;
0530 }
0531 
0532 static void __exit nvram_module_exit(void)
0533 {
0534 #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
0535     remove_proc_entry("driver/nvram", NULL);
0536 #endif
0537     misc_deregister(&nvram_misc);
0538 }
0539 
0540 module_init(nvram_module_init);
0541 module_exit(nvram_module_exit);
0542 
0543 MODULE_LICENSE("GPL");
0544 MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
0545 MODULE_ALIAS("devname:nvram");