1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * c 2001 PPC 64 Team, IBM Corp 4 * 5 * /dev/nvram driver for PPC64 6 */ 7 8 9 #include <linux/types.h> 10 #include <linux/errno.h> 11 #include <linux/init.h> 12 #include <linux/spinlock.h> 13 #include <linux/slab.h> 14 #include <linux/ctype.h> 15 #include <linux/uaccess.h> 16 #include <linux/of.h> 17 #include <asm/nvram.h> 18 #include <asm/rtas.h> 19 #include <asm/machdep.h> 20 21 /* Max bytes to read/write in one go */ 22 #define NVRW_CNT 0x20 23 24 static unsigned int nvram_size; 25 static int nvram_fetch, nvram_store; 26 static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ 27 static DEFINE_SPINLOCK(nvram_lock); 28 29 /* See clobbering_unread_rtas_event() */ 30 #define NVRAM_RTAS_READ_TIMEOUT 5 /* seconds */ 31 static time64_t last_unread_rtas_event; /* timestamp */ 32 33 #ifdef CONFIG_PSTORE 34 time64_t last_rtas_event; 35 #endif 36 37 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) 38 { 39 unsigned int i; 40 unsigned long len; 41 int done; 42 unsigned long flags; 43 char *p = buf; 44 45 46 if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE) 47 return -ENODEV; 48 49 if (*index >= nvram_size) 50 return 0; 51 52 i = *index; 53 if (i + count > nvram_size) 54 count = nvram_size - i; 55 56 spin_lock_irqsave(&nvram_lock, flags); 57 58 for (; count != 0; count -= len) { 59 len = count; 60 if (len > NVRW_CNT) 61 len = NVRW_CNT; 62 63 if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf), 64 len) != 0) || len != done) { 65 spin_unlock_irqrestore(&nvram_lock, flags); 66 return -EIO; 67 } 68 69 memcpy(p, nvram_buf, len); 70 71 p += len; 72 i += len; 73 } 74 75 spin_unlock_irqrestore(&nvram_lock, flags); 76 77 *index = i; 78 return p - buf; 79 } 80 81 static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index) 82 { 83 unsigned int i; 84 unsigned long len; 85 int done; 86 unsigned long flags; 87 const char *p = buf; 88 89 if (nvram_size == 0 || nvram_store == RTAS_UNKNOWN_SERVICE) 90 return -ENODEV; 91 92 if (*index >= nvram_size) 93 return 0; 94 95 i = *index; 96 if (i + count > nvram_size) 97 count = nvram_size - i; 98 99 spin_lock_irqsave(&nvram_lock, flags); 100 101 for (; count != 0; count -= len) { 102 len = count; 103 if (len > NVRW_CNT) 104 len = NVRW_CNT; 105 106 memcpy(nvram_buf, p, len); 107 108 if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf), 109 len) != 0) || len != done) { 110 spin_unlock_irqrestore(&nvram_lock, flags); 111 return -EIO; 112 } 113 114 p += len; 115 i += len; 116 } 117 spin_unlock_irqrestore(&nvram_lock, flags); 118 119 *index = i; 120 return p - buf; 121 } 122 123 static ssize_t pSeries_nvram_get_size(void) 124 { 125 return nvram_size ? nvram_size : -ENODEV; 126 } 127 128 /* nvram_write_error_log 129 * 130 * We need to buffer the error logs into nvram to ensure that we have 131 * the failure information to decode. 132 */ 133 int nvram_write_error_log(char * buff, int length, 134 unsigned int err_type, unsigned int error_log_cnt) 135 { 136 int rc = nvram_write_os_partition(&rtas_log_partition, buff, length, 137 err_type, error_log_cnt); 138 if (!rc) { 139 last_unread_rtas_event = ktime_get_real_seconds(); 140 #ifdef CONFIG_PSTORE 141 last_rtas_event = ktime_get_real_seconds(); 142 #endif 143 } 144 145 return rc; 146 } 147 148 /* nvram_read_error_log 149 * 150 * Reads nvram for error log for at most 'length' 151 */ 152 int nvram_read_error_log(char *buff, int length, 153 unsigned int *err_type, unsigned int *error_log_cnt) 154 { 155 return nvram_read_partition(&rtas_log_partition, buff, length, 156 err_type, error_log_cnt); 157 } 158 159 /* This doesn't actually zero anything, but it sets the event_logged 160 * word to tell that this event is safely in syslog. 161 */ 162 int nvram_clear_error_log(void) 163 { 164 loff_t tmp_index; 165 int clear_word = ERR_FLAG_ALREADY_LOGGED; 166 int rc; 167 168 if (rtas_log_partition.index == -1) 169 return -1; 170 171 tmp_index = rtas_log_partition.index; 172 173 rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); 174 if (rc <= 0) { 175 printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc); 176 return rc; 177 } 178 last_unread_rtas_event = 0; 179 180 return 0; 181 } 182 183 /* 184 * Are we using the ibm,rtas-log for oops/panic reports? And if so, 185 * would logging this oops/panic overwrite an RTAS event that rtas_errd 186 * hasn't had a chance to read and process? Return 1 if so, else 0. 187 * 188 * We assume that if rtas_errd hasn't read the RTAS event in 189 * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to. 190 */ 191 int clobbering_unread_rtas_event(void) 192 { 193 return (oops_log_partition.index == rtas_log_partition.index 194 && last_unread_rtas_event 195 && ktime_get_real_seconds() - last_unread_rtas_event <= 196 NVRAM_RTAS_READ_TIMEOUT); 197 } 198 199 static int __init pseries_nvram_init_log_partitions(void) 200 { 201 int rc; 202 203 /* Scan nvram for partitions */ 204 nvram_scan_partitions(); 205 206 rc = nvram_init_os_partition(&rtas_log_partition); 207 nvram_init_oops_partition(rc == 0); 208 return 0; 209 } 210 machine_arch_initcall(pseries, pseries_nvram_init_log_partitions); 211 212 int __init pSeries_nvram_init(void) 213 { 214 struct device_node *nvram; 215 const __be32 *nbytes_p; 216 unsigned int proplen; 217 218 nvram = of_find_node_by_type(NULL, "nvram"); 219 if (nvram == NULL) 220 return -ENODEV; 221 222 nbytes_p = of_get_property(nvram, "#bytes", &proplen); 223 if (nbytes_p == NULL || proplen != sizeof(unsigned int)) { 224 of_node_put(nvram); 225 return -EIO; 226 } 227 228 nvram_size = be32_to_cpup(nbytes_p); 229 230 nvram_fetch = rtas_function_token(RTAS_FN_NVRAM_FETCH); 231 nvram_store = rtas_function_token(RTAS_FN_NVRAM_STORE); 232 printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size); 233 of_node_put(nvram); 234 235 ppc_md.nvram_read = pSeries_nvram_read; 236 ppc_md.nvram_write = pSeries_nvram_write; 237 ppc_md.nvram_size = pSeries_nvram_get_size; 238 239 return 0; 240 } 241 242
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.