nvram.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * CMOS/NV-RAM driver for Linux
  4. *
  5. * Copyright (C) 1997 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
  6. * idea by and with help from Richard Jelinek <rj@suse.de>
  7. * Portions copyright (c) 2001,2002 Sun Microsystems (thockin@sun.com)
  8. *
  9. * This driver allows you to access the contents of the non-volatile memory in
  10. * the mc146818rtc.h real-time clock. This chip is built into all PCs and into
  11. * many Atari machines. In the former it's called "CMOS-RAM", in the latter
  12. * "NVRAM" (NV stands for non-volatile).
  13. *
  14. * The data are supplied as a (seekable) character device, /dev/nvram. The
  15. * size of this file is dependent on the controller. The usual size is 114,
  16. * the number of freely available bytes in the memory (i.e., not used by the
  17. * RTC itself).
  18. *
  19. * Checksums over the NVRAM contents are managed by this driver. In case of a
  20. * bad checksum, reads and writes return -EIO. The checksum can be initialized
  21. * to a sane state either by ioctl(NVRAM_INIT) (clear whole NVRAM) or
  22. * ioctl(NVRAM_SETCKS) (doesn't change contents, just makes checksum valid
  23. * again; use with care!)
  24. *
  25. * 1.1 Cesar Barros: SMP locking fixes
  26. * added changelog
  27. * 1.2 Erik Gilling: Cobalt Networks support
  28. * Tim Hockin: general cleanup, Cobalt support
  29. * 1.3 Wim Van Sebroeck: convert PRINT_PROC to seq_file
  30. */
  31. #define NVRAM_VERSION "1.3"
  32. #include <linux/module.h>
  33. #include <linux/nvram.h>
  34. #include <linux/types.h>
  35. #include <linux/errno.h>
  36. #include <linux/miscdevice.h>
  37. #include <linux/ioport.h>
  38. #include <linux/fcntl.h>
  39. #include <linux/mc146818rtc.h>
  40. #include <linux/init.h>
  41. #include <linux/proc_fs.h>
  42. #include <linux/seq_file.h>
  43. #include <linux/slab.h>
  44. #include <linux/spinlock.h>
  45. #include <linux/io.h>
  46. #include <linux/uaccess.h>
  47. #include <linux/mutex.h>
  48. #include <linux/pagemap.h>
  49. #ifdef CONFIG_PPC
  50. #include <asm/nvram.h>
  51. #endif
  52. static DEFINE_MUTEX(nvram_mutex);
  53. static DEFINE_SPINLOCK(nvram_state_lock);
  54. static int nvram_open_cnt; /* #times opened */
  55. static int nvram_open_mode; /* special open modes */
  56. static ssize_t nvram_size;
  57. #define NVRAM_WRITE 1 /* opened for writing (exclusive) */
  58. #define NVRAM_EXCL 2 /* opened with O_EXCL */
  59. #ifdef CONFIG_X86
  60. /*
  61. * These functions are provided to be called internally or by other parts of
  62. * the kernel. It's up to the caller to ensure correct checksum before reading
  63. * or after writing (needs to be done only once).
  64. *
  65. * It is worth noting that these functions all access bytes of general
  66. * purpose memory in the NVRAM - that is to say, they all add the
  67. * NVRAM_FIRST_BYTE offset. Pass them offsets into NVRAM as if you did not
  68. * know about the RTC cruft.
  69. */
  70. #define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE)
  71. /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
  72. * rtc_lock held. Due to the index-port/data-port design of the RTC, we
  73. * don't want two different things trying to get to it at once. (e.g. the
  74. * periodic 11 min sync from kernel/time/ntp.c vs. this driver.)
  75. */
  76. static unsigned char __nvram_read_byte(int i)
  77. {
  78. return CMOS_READ(NVRAM_FIRST_BYTE + i);
  79. }
  80. static unsigned char pc_nvram_read_byte(int i)
  81. {
  82. unsigned long flags;
  83. unsigned char c;
  84. spin_lock_irqsave(&rtc_lock, flags);
  85. c = __nvram_read_byte(i);
  86. spin_unlock_irqrestore(&rtc_lock, flags);
  87. return c;
  88. }
  89. /* This races nicely with trying to read with checksum checking (nvram_read) */
  90. static void __nvram_write_byte(unsigned char c, int i)
  91. {
  92. CMOS_WRITE(c, NVRAM_FIRST_BYTE + i);
  93. }
  94. static void pc_nvram_write_byte(unsigned char c, int i)
  95. {
  96. unsigned long flags;
  97. spin_lock_irqsave(&rtc_lock, flags);
  98. __nvram_write_byte(c, i);
  99. spin_unlock_irqrestore(&rtc_lock, flags);
  100. }
  101. /* On PCs, the checksum is built only over bytes 2..31 */
  102. #define PC_CKS_RANGE_START 2
  103. #define PC_CKS_RANGE_END 31
  104. #define PC_CKS_LOC 32
  105. static int __nvram_check_checksum(void)
  106. {
  107. int i;
  108. unsigned short sum = 0;
  109. unsigned short expect;
  110. for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
  111. sum += __nvram_read_byte(i);
  112. expect = __nvram_read_byte(PC_CKS_LOC)<<8 |
  113. __nvram_read_byte(PC_CKS_LOC+1);
  114. return (sum & 0xffff) == expect;
  115. }
  116. static void __nvram_set_checksum(void)
  117. {
  118. int i;
  119. unsigned short sum = 0;
  120. for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
  121. sum += __nvram_read_byte(i);
  122. __nvram_write_byte(sum >> 8, PC_CKS_LOC);
  123. __nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
  124. }
  125. static long pc_nvram_set_checksum(void)
  126. {
  127. spin_lock_irq(&rtc_lock);
  128. __nvram_set_checksum();
  129. spin_unlock_irq(&rtc_lock);
  130. return 0;
  131. }
  132. static long pc_nvram_initialize(void)
  133. {
  134. ssize_t i;
  135. spin_lock_irq(&rtc_lock);
  136. for (i = 0; i < NVRAM_BYTES; ++i)
  137. __nvram_write_byte(0, i);
  138. __nvram_set_checksum();
  139. spin_unlock_irq(&rtc_lock);
  140. return 0;
  141. }
  142. static ssize_t pc_nvram_get_size(void)
  143. {
  144. return NVRAM_BYTES;
  145. }
  146. static ssize_t pc_nvram_read(char *buf, size_t count, loff_t *ppos)
  147. {
  148. char *p = buf;
  149. loff_t i;
  150. spin_lock_irq(&rtc_lock);
  151. if (!__nvram_check_checksum()) {
  152. spin_unlock_irq(&rtc_lock);
  153. return -EIO;
  154. }
  155. for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
  156. *p = __nvram_read_byte(i);
  157. spin_unlock_irq(&rtc_lock);
  158. *ppos = i;
  159. return p - buf;
  160. }
  161. static ssize_t pc_nvram_write(char *buf, size_t count, loff_t *ppos)
  162. {
  163. char *p = buf;
  164. loff_t i;
  165. spin_lock_irq(&rtc_lock);
  166. if (!__nvram_check_checksum()) {
  167. spin_unlock_irq(&rtc_lock);
  168. return -EIO;
  169. }
  170. for (i = *ppos; count > 0 && i < NVRAM_BYTES; --count, ++i, ++p)
  171. __nvram_write_byte(*p, i);
  172. __nvram_set_checksum();
  173. spin_unlock_irq(&rtc_lock);
  174. *ppos = i;
  175. return p - buf;
  176. }
  177. const struct nvram_ops arch_nvram_ops = {
  178. .read = pc_nvram_read,
  179. .write = pc_nvram_write,
  180. .read_byte = pc_nvram_read_byte,
  181. .write_byte = pc_nvram_write_byte,
  182. .get_size = pc_nvram_get_size,
  183. .set_checksum = pc_nvram_set_checksum,
  184. .initialize = pc_nvram_initialize,
  185. };
  186. EXPORT_SYMBOL(arch_nvram_ops);
  187. #endif /* CONFIG_X86 */
  188. /*
  189. * The are the file operation function for user access to /dev/nvram
  190. */
  191. static loff_t nvram_misc_llseek(struct file *file, loff_t offset, int origin)
  192. {
  193. return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
  194. nvram_size);
  195. }
  196. static ssize_t nvram_misc_read(struct file *file, char __user *buf,
  197. size_t count, loff_t *ppos)
  198. {
  199. char *tmp;
  200. ssize_t ret;
  201. if (*ppos >= nvram_size)
  202. return 0;
  203. count = min_t(size_t, count, nvram_size - *ppos);
  204. count = min_t(size_t, count, PAGE_SIZE);
  205. tmp = kmalloc(count, GFP_KERNEL);
  206. if (!tmp)
  207. return -ENOMEM;
  208. ret = nvram_read(tmp, count, ppos);
  209. if (ret <= 0)
  210. goto out;
  211. if (copy_to_user(buf, tmp, ret)) {
  212. *ppos -= ret;
  213. ret = -EFAULT;
  214. }
  215. out:
  216. kfree(tmp);
  217. return ret;
  218. }
  219. static ssize_t nvram_misc_write(struct file *file, const char __user *buf,
  220. size_t count, loff_t *ppos)
  221. {
  222. char *tmp;
  223. ssize_t ret;
  224. if (*ppos >= nvram_size)
  225. return 0;
  226. count = min_t(size_t, count, nvram_size - *ppos);
  227. count = min_t(size_t, count, PAGE_SIZE);
  228. tmp = memdup_user(buf, count);
  229. if (IS_ERR(tmp))
  230. return PTR_ERR(tmp);
  231. ret = nvram_write(tmp, count, ppos);
  232. kfree(tmp);
  233. return ret;
  234. }
  235. static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
  236. unsigned long arg)
  237. {
  238. long ret = -ENOTTY;
  239. switch (cmd) {
  240. #ifdef CONFIG_PPC
  241. case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
  242. pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
  243. fallthrough;
  244. case IOC_NVRAM_GET_OFFSET:
  245. ret = -EINVAL;
  246. #ifdef CONFIG_PPC_PMAC
  247. if (machine_is(powermac)) {
  248. int part, offset;
  249. if (copy_from_user(&part, (void __user *)arg,
  250. sizeof(part)) != 0)
  251. return -EFAULT;
  252. if (part < pmac_nvram_OF || part > pmac_nvram_NR)
  253. return -EINVAL;
  254. offset = pmac_get_partition(part);
  255. if (offset < 0)
  256. return -EINVAL;
  257. if (copy_to_user((void __user *)arg,
  258. &offset, sizeof(offset)) != 0)
  259. return -EFAULT;
  260. ret = 0;
  261. }
  262. #endif
  263. break;
  264. #ifdef CONFIG_PPC32
  265. case IOC_NVRAM_SYNC:
  266. if (ppc_md.nvram_sync != NULL) {
  267. mutex_lock(&nvram_mutex);
  268. ppc_md.nvram_sync();
  269. mutex_unlock(&nvram_mutex);
  270. }
  271. ret = 0;
  272. break;
  273. #endif
  274. #elif defined(CONFIG_X86) || defined(CONFIG_M68K)
  275. case NVRAM_INIT:
  276. /* initialize NVRAM contents and checksum */
  277. if (!capable(CAP_SYS_ADMIN))
  278. return -EACCES;
  279. if (arch_nvram_ops.initialize != NULL) {
  280. mutex_lock(&nvram_mutex);
  281. ret = arch_nvram_ops.initialize();
  282. mutex_unlock(&nvram_mutex);
  283. }
  284. break;
  285. case NVRAM_SETCKS:
  286. /* just set checksum, contents unchanged (maybe useful after
  287. * checksum garbaged somehow...) */
  288. if (!capable(CAP_SYS_ADMIN))
  289. return -EACCES;
  290. if (arch_nvram_ops.set_checksum != NULL) {
  291. mutex_lock(&nvram_mutex);
  292. ret = arch_nvram_ops.set_checksum();
  293. mutex_unlock(&nvram_mutex);
  294. }
  295. break;
  296. #endif /* CONFIG_X86 || CONFIG_M68K */
  297. }
  298. return ret;
  299. }
  300. static int nvram_misc_open(struct inode *inode, struct file *file)
  301. {
  302. spin_lock(&nvram_state_lock);
  303. /* Prevent multiple readers/writers if desired. */
  304. if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
  305. (nvram_open_mode & NVRAM_EXCL)) {
  306. spin_unlock(&nvram_state_lock);
  307. return -EBUSY;
  308. }
  309. #if defined(CONFIG_X86) || defined(CONFIG_M68K)
  310. /* Prevent multiple writers if the set_checksum ioctl is implemented. */
  311. if ((arch_nvram_ops.set_checksum != NULL) &&
  312. (file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE)) {
  313. spin_unlock(&nvram_state_lock);
  314. return -EBUSY;
  315. }
  316. #endif
  317. if (file->f_flags & O_EXCL)
  318. nvram_open_mode |= NVRAM_EXCL;
  319. if (file->f_mode & FMODE_WRITE)
  320. nvram_open_mode |= NVRAM_WRITE;
  321. nvram_open_cnt++;
  322. spin_unlock(&nvram_state_lock);
  323. return 0;
  324. }
  325. static int nvram_misc_release(struct inode *inode, struct file *file)
  326. {
  327. spin_lock(&nvram_state_lock);
  328. nvram_open_cnt--;
  329. /* if only one instance is open, clear the EXCL bit */
  330. if (nvram_open_mode & NVRAM_EXCL)
  331. nvram_open_mode &= ~NVRAM_EXCL;
  332. if (file->f_mode & FMODE_WRITE)
  333. nvram_open_mode &= ~NVRAM_WRITE;
  334. spin_unlock(&nvram_state_lock);
  335. return 0;
  336. }
  337. #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
  338. static const char * const floppy_types[] = {
  339. "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M",
  340. "3.5'' 2.88M", "3.5'' 2.88M"
  341. };
  342. static const char * const gfx_types[] = {
  343. "EGA, VGA, ... (with BIOS)",
  344. "CGA (40 cols)",
  345. "CGA (80 cols)",
  346. "monochrome",
  347. };
  348. static void pc_nvram_proc_read(unsigned char *nvram, struct seq_file *seq,
  349. void *offset)
  350. {
  351. int checksum;
  352. int type;
  353. spin_lock_irq(&rtc_lock);
  354. checksum = __nvram_check_checksum();
  355. spin_unlock_irq(&rtc_lock);
  356. seq_printf(seq, "Checksum status: %svalid\n", checksum ? "" : "not ");
  357. seq_printf(seq, "# floppies : %d\n",
  358. (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
  359. seq_printf(seq, "Floppy 0 type : ");
  360. type = nvram[2] >> 4;
  361. if (type < ARRAY_SIZE(floppy_types))
  362. seq_printf(seq, "%s\n", floppy_types[type]);
  363. else
  364. seq_printf(seq, "%d (unknown)\n", type);
  365. seq_printf(seq, "Floppy 1 type : ");
  366. type = nvram[2] & 0x0f;
  367. if (type < ARRAY_SIZE(floppy_types))
  368. seq_printf(seq, "%s\n", floppy_types[type]);
  369. else
  370. seq_printf(seq, "%d (unknown)\n", type);
  371. seq_printf(seq, "HD 0 type : ");
  372. type = nvram[4] >> 4;
  373. if (type)
  374. seq_printf(seq, "%02x\n", type == 0x0f ? nvram[11] : type);
  375. else
  376. seq_printf(seq, "none\n");
  377. seq_printf(seq, "HD 1 type : ");
  378. type = nvram[4] & 0x0f;
  379. if (type)
  380. seq_printf(seq, "%02x\n", type == 0x0f ? nvram[12] : type);
  381. else
  382. seq_printf(seq, "none\n");
  383. seq_printf(seq, "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
  384. nvram[18] | (nvram[19] << 8),
  385. nvram[20], nvram[25],
  386. nvram[21] | (nvram[22] << 8), nvram[23] | (nvram[24] << 8));
  387. seq_printf(seq, "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
  388. nvram[39] | (nvram[40] << 8),
  389. nvram[41], nvram[46],
  390. nvram[42] | (nvram[43] << 8), nvram[44] | (nvram[45] << 8));
  391. seq_printf(seq, "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8));
  392. seq_printf(seq, "Extended memory: %d kB (configured), %d kB (tested)\n",
  393. nvram[9] | (nvram[10] << 8), nvram[34] | (nvram[35] << 8));
  394. seq_printf(seq, "Gfx adapter : %s\n",
  395. gfx_types[(nvram[6] >> 4) & 3]);
  396. seq_printf(seq, "FPU : %sinstalled\n",
  397. (nvram[6] & 2) ? "" : "not ");
  398. return;
  399. }
  400. static int nvram_proc_read(struct seq_file *seq, void *offset)
  401. {
  402. unsigned char contents[NVRAM_BYTES];
  403. int i = 0;
  404. spin_lock_irq(&rtc_lock);
  405. for (i = 0; i < NVRAM_BYTES; ++i)
  406. contents[i] = __nvram_read_byte(i);
  407. spin_unlock_irq(&rtc_lock);
  408. pc_nvram_proc_read(contents, seq, offset);
  409. return 0;
  410. }
  411. #endif /* CONFIG_X86 && CONFIG_PROC_FS */
  412. static const struct file_operations nvram_misc_fops = {
  413. .owner = THIS_MODULE,
  414. .llseek = nvram_misc_llseek,
  415. .read = nvram_misc_read,
  416. .write = nvram_misc_write,
  417. .unlocked_ioctl = nvram_misc_ioctl,
  418. .open = nvram_misc_open,
  419. .release = nvram_misc_release,
  420. };
  421. static struct miscdevice nvram_misc = {
  422. NVRAM_MINOR,
  423. "nvram",
  424. &nvram_misc_fops,
  425. };
  426. static int __init nvram_module_init(void)
  427. {
  428. int ret;
  429. nvram_size = nvram_get_size();
  430. if (nvram_size < 0)
  431. return nvram_size;
  432. ret = misc_register(&nvram_misc);
  433. if (ret) {
  434. pr_err("nvram: can't misc_register on minor=%d\n", NVRAM_MINOR);
  435. return ret;
  436. }
  437. #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
  438. if (!proc_create_single("driver/nvram", 0, NULL, nvram_proc_read)) {
  439. pr_err("nvram: can't create /proc/driver/nvram\n");
  440. misc_deregister(&nvram_misc);
  441. return -ENOMEM;
  442. }
  443. #endif
  444. pr_info("Non-volatile memory driver v" NVRAM_VERSION "\n");
  445. return 0;
  446. }
  447. static void __exit nvram_module_exit(void)
  448. {
  449. #if defined(CONFIG_X86) && defined(CONFIG_PROC_FS)
  450. remove_proc_entry("driver/nvram", NULL);
  451. #endif
  452. misc_deregister(&nvram_misc);
  453. }
  454. module_init(nvram_module_init);
  455. module_exit(nvram_module_exit);
  456. MODULE_LICENSE("GPL");
  457. MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
  458. MODULE_ALIAS("devname:nvram");