// SPDX-License-Identifier: GPL-2.0-only /* * CMOS/NV-RAM driver for Linux * * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> * idea by and with help from Richard Jelinek <rj@suse.de> * Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com) * * This driver allows you to access the contents of the non-volatile memory in * the mc146818rtc.h real-time clock. This chip is built into all PCs and into * many Atari machines. In the former it's called "CMOS-RAM", in the latter * "NVRAM" (NV stands for non-volatile). * * The data are supplied as a (seekable) character device, /dev/nvram. The * size of this file is dependent on the controller. The usual size is 114, * the number of freely available bytes in the memory (i.e., not used by the * RTC itself). * * Checksums over the NVRAM contents are managed by this driver. In case of a * bad checksum, reads and writes return -EIO. The checksum can be initialized * to a sane state either by ioctl(NVRAM_INIT) (clear whole NVRAM) or * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid * again; use with care!) * * 1.1 Cesar Barros: SMP locking fixes * added changelog * 1.2 Erik Gilling: Cobalt Networks support * Tim Hockin: general cleanup, Cobalt support * 1.3 Wim Van Sebroeck: convert PRINT_PROC to seq_file
*/
static DEFINE_MUTEX(nvram_mutex); static DEFINE_SPINLOCK(nvram_state_lock); staticint nvram_open_cnt; /* #times opened */ staticint nvram_open_mode; /* special open modes */ static ssize_t nvram_size; #define NVRAM_WRITE 1 /* opened for writing (exclusive) */ #define NVRAM_EXCL 2 /* opened with O_EXCL */
#ifdef CONFIG_X86 /* * These functions are provided to be called internally or by other parts of * the kernel. It's up to the caller to ensure correct checksum before reading * or after writing (needs to be done only once). * * It is worth noting that these functions all access bytes of general * purpose memory in the NVRAM - that is to say, they all add the * NVRAM_FIRST_BYTE offset. Pass them offsets into NVRAM as if you did not * know about the RTC cruft.
*/
#define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE)
/* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with * rtc_lock held. Due to the index-port/data-port design of the RTC, we * don't want two different things trying to get to it at once. (e.g. the * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
*/
spin_lock_irqsave(&rtc_lock, flags);
c = __nvram_read_byte(i);
spin_unlock_irqrestore(&rtc_lock, flags); return c;
}
/* This races nicely with trying to read with checksum checking (nvram_read) */ staticvoid __nvram_write_byte(unsignedchar c, int i)
{
CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
}
staticvoid pc_nvram_write_byte(unsignedchar c, int i)
{ unsignedlong flags;
tmp = memdup_user(buf, count); if (IS_ERR(tmp)) return PTR_ERR(tmp);
ret = nvram_write(tmp, count, ppos);
kfree(tmp); return ret;
}
staticlong nvram_misc_ioctl(struct file *file, unsignedint cmd, unsignedlong arg)
{ long ret = -ENOTTY;
switch (cmd) { #ifdef CONFIG_PPC case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
fallthrough; case IOC_NVRAM_GET_OFFSET:
ret = -EINVAL; #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { int part, offset;
if (copy_from_user(&part, (void __user *)arg, sizeof(part)) != 0) return -EFAULT; if (part < pmac_nvram_OF || part > pmac_nvram_NR) return -EINVAL;
offset = pmac_get_partition(part); if (offset < 0) return -EINVAL; if (copy_to_user((void __user *)arg,
&offset, sizeof(offset)) != 0) return -EFAULT;
ret = 0;
} #endif break; #ifdef CONFIG_PPC32 case IOC_NVRAM_SYNC: if (ppc_md.nvram_sync != NULL) {
mutex_lock(&nvram_mutex);
ppc_md.nvram_sync();
mutex_unlock(&nvram_mutex);
}
ret = 0; break; #endif #elifdefined(CONFIG_X86) || defined(CONFIG_M68K) case NVRAM_INIT: /* initialize NVRAM contents and checksum */ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (arch_nvram_ops.initialize != NULL) {
mutex_lock(&nvram_mutex);
ret = arch_nvram_ops.initialize();
mutex_unlock(&nvram_mutex);
} break; case NVRAM_SETCKS: /* just set checksum, contents unchanged (maybe useful after
* checksum garbaged somehow...) */ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
/* if only one instance is open, clear the EXCL bit */ if (nvram_open_mode & NVRAM_EXCL)
nvram_open_mode &= ~NVRAM_EXCL; if (file->f_mode & FMODE_WRITE)
nvram_open_mode &= ~NVRAM_WRITE;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.