1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright 2010 Google Inc. All Rights Reserved. |
4 | * Author: dlaurie@google.com (Duncan Laurie) |
5 | * |
6 | * Re-worked to expose sysfs APIs by mikew@google.com (Mike Waychison) |
7 | * |
8 | * EFI SMI interface for Google platforms |
9 | */ |
10 | |
11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> |
13 | #include <linux/types.h> |
14 | #include <linux/device.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/errno.h> |
17 | #include <linux/string.h> |
18 | #include <linux/spinlock.h> |
19 | #include <linux/dma-mapping.h> |
20 | #include <linux/fs.h> |
21 | #include <linux/slab.h> |
22 | #include <linux/panic_notifier.h> |
23 | #include <linux/ioctl.h> |
24 | #include <linux/acpi.h> |
25 | #include <linux/io.h> |
26 | #include <linux/uaccess.h> |
27 | #include <linux/dmi.h> |
28 | #include <linux/kdebug.h> |
29 | #include <linux/reboot.h> |
30 | #include <linux/efi.h> |
31 | #include <linux/module.h> |
32 | #include <linux/ucs2_string.h> |
33 | #include <linux/suspend.h> |
34 | |
35 | #define GSMI_SHUTDOWN_CLEAN 0 /* Clean Shutdown */ |
36 | /* TODO(mikew@google.com): Tie in HARDLOCKUP_DETECTOR with NMIWDT */ |
37 | #define GSMI_SHUTDOWN_NMIWDT 1 /* NMI Watchdog */ |
38 | #define GSMI_SHUTDOWN_PANIC 2 /* Panic */ |
39 | #define GSMI_SHUTDOWN_OOPS 3 /* Oops */ |
40 | #define GSMI_SHUTDOWN_DIE 4 /* Die -- No longer meaningful */ |
41 | #define GSMI_SHUTDOWN_MCE 5 /* Machine Check */ |
42 | #define GSMI_SHUTDOWN_SOFTWDT 6 /* Software Watchdog */ |
43 | #define GSMI_SHUTDOWN_MBE 7 /* Uncorrected ECC */ |
44 | #define GSMI_SHUTDOWN_TRIPLE 8 /* Triple Fault */ |
45 | |
46 | #define DRIVER_VERSION "1.0" |
47 | #define GSMI_GUID_SIZE 16 |
48 | #define GSMI_BUF_SIZE 1024 |
49 | #define GSMI_BUF_ALIGN sizeof(u64) |
50 | #define GSMI_CALLBACK 0xef |
51 | |
52 | /* SMI return codes */ |
53 | #define GSMI_SUCCESS 0x00 |
54 | #define GSMI_UNSUPPORTED2 0x03 |
55 | #define GSMI_LOG_FULL 0x0b |
56 | #define GSMI_VAR_NOT_FOUND 0x0e |
57 | #define GSMI_HANDSHAKE_SPIN 0x7d |
58 | #define GSMI_HANDSHAKE_CF 0x7e |
59 | #define GSMI_HANDSHAKE_NONE 0x7f |
60 | #define GSMI_INVALID_PARAMETER 0x82 |
61 | #define GSMI_UNSUPPORTED 0x83 |
62 | #define GSMI_BUFFER_TOO_SMALL 0x85 |
63 | #define GSMI_NOT_READY 0x86 |
64 | #define GSMI_DEVICE_ERROR 0x87 |
65 | #define GSMI_NOT_FOUND 0x8e |
66 | |
67 | #define QUIRKY_BOARD_HASH 0x78a30a50 |
68 | |
69 | /* Internally used commands passed to the firmware */ |
70 | #define GSMI_CMD_GET_NVRAM_VAR 0x01 |
71 | #define GSMI_CMD_GET_NEXT_VAR 0x02 |
72 | #define GSMI_CMD_SET_NVRAM_VAR 0x03 |
73 | #define GSMI_CMD_SET_EVENT_LOG 0x08 |
74 | #define GSMI_CMD_CLEAR_EVENT_LOG 0x09 |
75 | #define GSMI_CMD_LOG_S0IX_SUSPEND 0x0a |
76 | #define GSMI_CMD_LOG_S0IX_RESUME 0x0b |
77 | #define GSMI_CMD_CLEAR_CONFIG 0x20 |
78 | #define GSMI_CMD_HANDSHAKE_TYPE 0xC1 |
79 | #define GSMI_CMD_RESERVED 0xff |
80 | |
81 | /* Magic entry type for kernel events */ |
82 | #define GSMI_LOG_ENTRY_TYPE_KERNEL 0xDEAD |
83 | |
84 | /* SMI buffers must be in 32bit physical address space */ |
85 | struct gsmi_buf { |
86 | u8 *start; /* start of buffer */ |
87 | size_t length; /* length of buffer */ |
88 | u32 address; /* physical address of buffer */ |
89 | }; |
90 | |
91 | static struct gsmi_device { |
92 | struct platform_device *pdev; /* platform device */ |
93 | struct gsmi_buf *name_buf; /* variable name buffer */ |
94 | struct gsmi_buf *data_buf; /* generic data buffer */ |
95 | struct gsmi_buf *param_buf; /* parameter buffer */ |
96 | spinlock_t lock; /* serialize access to SMIs */ |
97 | u16 smi_cmd; /* SMI command port */ |
98 | int handshake_type; /* firmware handler interlock type */ |
99 | struct kmem_cache *mem_pool; /* kmem cache for gsmi_buf allocations */ |
100 | } gsmi_dev; |
101 | |
102 | /* Packed structures for communicating with the firmware */ |
103 | struct gsmi_nvram_var_param { |
104 | efi_guid_t guid; |
105 | u32 name_ptr; |
106 | u32 attributes; |
107 | u32 data_len; |
108 | u32 data_ptr; |
109 | } __packed; |
110 | |
111 | struct gsmi_get_next_var_param { |
112 | u8 guid[GSMI_GUID_SIZE]; |
113 | u32 name_ptr; |
114 | u32 name_len; |
115 | } __packed; |
116 | |
117 | struct gsmi_set_eventlog_param { |
118 | u32 data_ptr; |
119 | u32 data_len; |
120 | u32 type; |
121 | } __packed; |
122 | |
123 | /* Event log formats */ |
124 | struct gsmi_log_entry_type_1 { |
125 | u16 type; |
126 | u32 instance; |
127 | } __packed; |
128 | |
129 | /* |
130 | * Some platforms don't have explicit SMI handshake |
131 | * and need to wait for SMI to complete. |
132 | */ |
133 | #define GSMI_DEFAULT_SPINCOUNT 0x10000 |
134 | static unsigned int spincount = GSMI_DEFAULT_SPINCOUNT; |
135 | module_param(spincount, uint, 0600); |
136 | MODULE_PARM_DESC(spincount, |
137 | "The number of loop iterations to use when using the spin handshake." ); |
138 | |
139 | /* |
140 | * Some older platforms with Apollo Lake chipsets do not support S0ix logging |
141 | * in their GSMI handlers, and behaved poorly when resuming via power button |
142 | * press if the logging was attempted. Updated firmware with proper behavior |
143 | * has long since shipped, removing the need for this opt-in parameter. It |
144 | * now exists as an opt-out parameter for folks defiantly running old |
145 | * firmware, or unforeseen circumstances. After the change from opt-in to |
146 | * opt-out has baked sufficiently, this parameter should probably be removed |
147 | * entirely. |
148 | */ |
149 | static bool s0ix_logging_enable = true; |
150 | module_param(s0ix_logging_enable, bool, 0600); |
151 | |
152 | static struct gsmi_buf *gsmi_buf_alloc(void) |
153 | { |
154 | struct gsmi_buf *smibuf; |
155 | |
156 | smibuf = kzalloc(size: sizeof(*smibuf), GFP_KERNEL); |
157 | if (!smibuf) { |
158 | printk(KERN_ERR "gsmi: out of memory\n" ); |
159 | return NULL; |
160 | } |
161 | |
162 | /* allocate buffer in 32bit address space */ |
163 | smibuf->start = kmem_cache_alloc(cachep: gsmi_dev.mem_pool, GFP_KERNEL); |
164 | if (!smibuf->start) { |
165 | printk(KERN_ERR "gsmi: failed to allocate name buffer\n" ); |
166 | kfree(objp: smibuf); |
167 | return NULL; |
168 | } |
169 | |
170 | /* fill in the buffer handle */ |
171 | smibuf->length = GSMI_BUF_SIZE; |
172 | smibuf->address = (u32)virt_to_phys(address: smibuf->start); |
173 | |
174 | return smibuf; |
175 | } |
176 | |
177 | static void gsmi_buf_free(struct gsmi_buf *smibuf) |
178 | { |
179 | if (smibuf) { |
180 | if (smibuf->start) |
181 | kmem_cache_free(s: gsmi_dev.mem_pool, objp: smibuf->start); |
182 | kfree(objp: smibuf); |
183 | } |
184 | } |
185 | |
186 | /* |
187 | * Make a call to gsmi func(sub). GSMI error codes are translated to |
188 | * in-kernel errnos (0 on success, -ERRNO on error). |
189 | */ |
190 | static int gsmi_exec(u8 func, u8 sub) |
191 | { |
192 | u16 cmd = (sub << 8) | func; |
193 | u16 result = 0; |
194 | int rc = 0; |
195 | |
196 | /* |
197 | * AH : Subfunction number |
198 | * AL : Function number |
199 | * EBX : Parameter block address |
200 | * DX : SMI command port |
201 | * |
202 | * Three protocols here. See also the comment in gsmi_init(). |
203 | */ |
204 | if (gsmi_dev.handshake_type == GSMI_HANDSHAKE_CF) { |
205 | /* |
206 | * If handshake_type == HANDSHAKE_CF then set CF on the |
207 | * way in and wait for the handler to clear it; this avoids |
208 | * corrupting register state on those chipsets which have |
209 | * a delay between writing the SMI trigger register and |
210 | * entering SMM. |
211 | */ |
212 | asm volatile ( |
213 | "stc\n" |
214 | "outb %%al, %%dx\n" |
215 | "1: jc 1b\n" |
216 | : "=a" (result) |
217 | : "0" (cmd), |
218 | "d" (gsmi_dev.smi_cmd), |
219 | "b" (gsmi_dev.param_buf->address) |
220 | : "memory" , "cc" |
221 | ); |
222 | } else if (gsmi_dev.handshake_type == GSMI_HANDSHAKE_SPIN) { |
223 | /* |
224 | * If handshake_type == HANDSHAKE_SPIN we spin a |
225 | * hundred-ish usecs to ensure the SMI has triggered. |
226 | */ |
227 | asm volatile ( |
228 | "outb %%al, %%dx\n" |
229 | "1: loop 1b\n" |
230 | : "=a" (result) |
231 | : "0" (cmd), |
232 | "d" (gsmi_dev.smi_cmd), |
233 | "b" (gsmi_dev.param_buf->address), |
234 | "c" (spincount) |
235 | : "memory" , "cc" |
236 | ); |
237 | } else { |
238 | /* |
239 | * If handshake_type == HANDSHAKE_NONE we do nothing; |
240 | * either we don't need to or it's legacy firmware that |
241 | * doesn't understand the CF protocol. |
242 | */ |
243 | asm volatile ( |
244 | "outb %%al, %%dx\n\t" |
245 | : "=a" (result) |
246 | : "0" (cmd), |
247 | "d" (gsmi_dev.smi_cmd), |
248 | "b" (gsmi_dev.param_buf->address) |
249 | : "memory" , "cc" |
250 | ); |
251 | } |
252 | |
253 | /* check return code from SMI handler */ |
254 | switch (result) { |
255 | case GSMI_SUCCESS: |
256 | break; |
257 | case GSMI_VAR_NOT_FOUND: |
258 | /* not really an error, but let the caller know */ |
259 | rc = 1; |
260 | break; |
261 | case GSMI_INVALID_PARAMETER: |
262 | printk(KERN_ERR "gsmi: exec 0x%04x: Invalid parameter\n" , cmd); |
263 | rc = -EINVAL; |
264 | break; |
265 | case GSMI_BUFFER_TOO_SMALL: |
266 | printk(KERN_ERR "gsmi: exec 0x%04x: Buffer too small\n" , cmd); |
267 | rc = -ENOMEM; |
268 | break; |
269 | case GSMI_UNSUPPORTED: |
270 | case GSMI_UNSUPPORTED2: |
271 | if (sub != GSMI_CMD_HANDSHAKE_TYPE) |
272 | printk(KERN_ERR "gsmi: exec 0x%04x: Not supported\n" , |
273 | cmd); |
274 | rc = -ENOSYS; |
275 | break; |
276 | case GSMI_NOT_READY: |
277 | printk(KERN_ERR "gsmi: exec 0x%04x: Not ready\n" , cmd); |
278 | rc = -EBUSY; |
279 | break; |
280 | case GSMI_DEVICE_ERROR: |
281 | printk(KERN_ERR "gsmi: exec 0x%04x: Device error\n" , cmd); |
282 | rc = -EFAULT; |
283 | break; |
284 | case GSMI_NOT_FOUND: |
285 | printk(KERN_ERR "gsmi: exec 0x%04x: Data not found\n" , cmd); |
286 | rc = -ENOENT; |
287 | break; |
288 | case GSMI_LOG_FULL: |
289 | printk(KERN_ERR "gsmi: exec 0x%04x: Log full\n" , cmd); |
290 | rc = -ENOSPC; |
291 | break; |
292 | case GSMI_HANDSHAKE_CF: |
293 | case GSMI_HANDSHAKE_SPIN: |
294 | case GSMI_HANDSHAKE_NONE: |
295 | rc = result; |
296 | break; |
297 | default: |
298 | printk(KERN_ERR "gsmi: exec 0x%04x: Unknown error 0x%04x\n" , |
299 | cmd, result); |
300 | rc = -ENXIO; |
301 | } |
302 | |
303 | return rc; |
304 | } |
305 | |
306 | #ifdef CONFIG_EFI |
307 | |
308 | static struct efivars efivars; |
309 | |
310 | static efi_status_t gsmi_get_variable(efi_char16_t *name, |
311 | efi_guid_t *vendor, u32 *attr, |
312 | unsigned long *data_size, |
313 | void *data) |
314 | { |
315 | struct gsmi_nvram_var_param param = { |
316 | .name_ptr = gsmi_dev.name_buf->address, |
317 | .data_ptr = gsmi_dev.data_buf->address, |
318 | .data_len = (u32)*data_size, |
319 | }; |
320 | efi_status_t ret = EFI_SUCCESS; |
321 | unsigned long flags; |
322 | size_t name_len = ucs2_strnlen(s: name, GSMI_BUF_SIZE / 2); |
323 | int rc; |
324 | |
325 | if (name_len >= GSMI_BUF_SIZE / 2) |
326 | return EFI_BAD_BUFFER_SIZE; |
327 | |
328 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
329 | |
330 | /* Vendor guid */ |
331 | memcpy(¶m.guid, vendor, sizeof(param.guid)); |
332 | |
333 | /* variable name, already in UTF-16 */ |
334 | memset(gsmi_dev.name_buf->start, 0, gsmi_dev.name_buf->length); |
335 | memcpy(gsmi_dev.name_buf->start, name, name_len * 2); |
336 | |
337 | /* data pointer */ |
338 | memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); |
339 | |
340 | /* parameter buffer */ |
341 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
342 | memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); |
343 | |
344 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_GET_NVRAM_VAR); |
345 | if (rc < 0) { |
346 | printk(KERN_ERR "gsmi: Get Variable failed\n" ); |
347 | ret = EFI_LOAD_ERROR; |
348 | } else if (rc == 1) { |
349 | /* variable was not found */ |
350 | ret = EFI_NOT_FOUND; |
351 | } else { |
352 | /* Get the arguments back */ |
353 | memcpy(¶m, gsmi_dev.param_buf->start, sizeof(param)); |
354 | |
355 | /* The size reported is the min of all of our buffers */ |
356 | *data_size = min_t(unsigned long, *data_size, |
357 | gsmi_dev.data_buf->length); |
358 | *data_size = min_t(unsigned long, *data_size, param.data_len); |
359 | |
360 | /* Copy data back to return buffer. */ |
361 | memcpy(data, gsmi_dev.data_buf->start, *data_size); |
362 | |
363 | /* All variables are have the following attributes */ |
364 | if (attr) |
365 | *attr = EFI_VARIABLE_NON_VOLATILE | |
366 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
367 | EFI_VARIABLE_RUNTIME_ACCESS; |
368 | } |
369 | |
370 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
371 | |
372 | return ret; |
373 | } |
374 | |
375 | static efi_status_t gsmi_get_next_variable(unsigned long *name_size, |
376 | efi_char16_t *name, |
377 | efi_guid_t *vendor) |
378 | { |
379 | struct gsmi_get_next_var_param param = { |
380 | .name_ptr = gsmi_dev.name_buf->address, |
381 | .name_len = gsmi_dev.name_buf->length, |
382 | }; |
383 | efi_status_t ret = EFI_SUCCESS; |
384 | int rc; |
385 | unsigned long flags; |
386 | |
387 | /* For the moment, only support buffers that exactly match in size */ |
388 | if (*name_size != GSMI_BUF_SIZE) |
389 | return EFI_BAD_BUFFER_SIZE; |
390 | |
391 | /* Let's make sure the thing is at least null-terminated */ |
392 | if (ucs2_strnlen(s: name, GSMI_BUF_SIZE / 2) == GSMI_BUF_SIZE / 2) |
393 | return EFI_INVALID_PARAMETER; |
394 | |
395 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
396 | |
397 | /* guid */ |
398 | memcpy(¶m.guid, vendor, sizeof(param.guid)); |
399 | |
400 | /* variable name, already in UTF-16 */ |
401 | memcpy(gsmi_dev.name_buf->start, name, *name_size); |
402 | |
403 | /* parameter buffer */ |
404 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
405 | memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); |
406 | |
407 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_GET_NEXT_VAR); |
408 | if (rc < 0) { |
409 | printk(KERN_ERR "gsmi: Get Next Variable Name failed\n" ); |
410 | ret = EFI_LOAD_ERROR; |
411 | } else if (rc == 1) { |
412 | /* variable not found -- end of list */ |
413 | ret = EFI_NOT_FOUND; |
414 | } else { |
415 | /* copy variable data back to return buffer */ |
416 | memcpy(¶m, gsmi_dev.param_buf->start, sizeof(param)); |
417 | |
418 | /* Copy the name back */ |
419 | memcpy(name, gsmi_dev.name_buf->start, GSMI_BUF_SIZE); |
420 | *name_size = ucs2_strnlen(s: name, GSMI_BUF_SIZE / 2) * 2; |
421 | |
422 | /* copy guid to return buffer */ |
423 | memcpy(vendor, ¶m.guid, sizeof(param.guid)); |
424 | ret = EFI_SUCCESS; |
425 | } |
426 | |
427 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
428 | |
429 | return ret; |
430 | } |
431 | |
432 | static efi_status_t gsmi_set_variable(efi_char16_t *name, |
433 | efi_guid_t *vendor, |
434 | u32 attr, |
435 | unsigned long data_size, |
436 | void *data) |
437 | { |
438 | struct gsmi_nvram_var_param param = { |
439 | .name_ptr = gsmi_dev.name_buf->address, |
440 | .data_ptr = gsmi_dev.data_buf->address, |
441 | .data_len = (u32)data_size, |
442 | .attributes = EFI_VARIABLE_NON_VOLATILE | |
443 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
444 | EFI_VARIABLE_RUNTIME_ACCESS, |
445 | }; |
446 | size_t name_len = ucs2_strnlen(s: name, GSMI_BUF_SIZE / 2); |
447 | efi_status_t ret = EFI_SUCCESS; |
448 | int rc; |
449 | unsigned long flags; |
450 | |
451 | if (name_len >= GSMI_BUF_SIZE / 2) |
452 | return EFI_BAD_BUFFER_SIZE; |
453 | |
454 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
455 | |
456 | /* guid */ |
457 | memcpy(¶m.guid, vendor, sizeof(param.guid)); |
458 | |
459 | /* variable name, already in UTF-16 */ |
460 | memset(gsmi_dev.name_buf->start, 0, gsmi_dev.name_buf->length); |
461 | memcpy(gsmi_dev.name_buf->start, name, name_len * 2); |
462 | |
463 | /* data pointer */ |
464 | memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); |
465 | memcpy(gsmi_dev.data_buf->start, data, data_size); |
466 | |
467 | /* parameter buffer */ |
468 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
469 | memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); |
470 | |
471 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_SET_NVRAM_VAR); |
472 | if (rc < 0) { |
473 | printk(KERN_ERR "gsmi: Set Variable failed\n" ); |
474 | ret = EFI_INVALID_PARAMETER; |
475 | } |
476 | |
477 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
478 | |
479 | return ret; |
480 | } |
481 | |
482 | static const struct efivar_operations efivar_ops = { |
483 | .get_variable = gsmi_get_variable, |
484 | .set_variable = gsmi_set_variable, |
485 | .get_next_variable = gsmi_get_next_variable, |
486 | }; |
487 | |
488 | #endif /* CONFIG_EFI */ |
489 | |
490 | static ssize_t eventlog_write(struct file *filp, struct kobject *kobj, |
491 | struct bin_attribute *bin_attr, |
492 | char *buf, loff_t pos, size_t count) |
493 | { |
494 | struct gsmi_set_eventlog_param param = { |
495 | .data_ptr = gsmi_dev.data_buf->address, |
496 | }; |
497 | int rc = 0; |
498 | unsigned long flags; |
499 | |
500 | /* Pull the type out */ |
501 | if (count < sizeof(u32)) |
502 | return -EINVAL; |
503 | param.type = *(u32 *)buf; |
504 | buf += sizeof(u32); |
505 | |
506 | /* The remaining buffer is the data payload */ |
507 | if ((count - sizeof(u32)) > gsmi_dev.data_buf->length) |
508 | return -EINVAL; |
509 | param.data_len = count - sizeof(u32); |
510 | |
511 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
512 | |
513 | /* data pointer */ |
514 | memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); |
515 | memcpy(gsmi_dev.data_buf->start, buf, param.data_len); |
516 | |
517 | /* parameter buffer */ |
518 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
519 | memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); |
520 | |
521 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_SET_EVENT_LOG); |
522 | if (rc < 0) |
523 | printk(KERN_ERR "gsmi: Set Event Log failed\n" ); |
524 | |
525 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
526 | |
527 | return (rc == 0) ? count : rc; |
528 | |
529 | } |
530 | |
531 | static struct bin_attribute eventlog_bin_attr = { |
532 | .attr = {.name = "append_to_eventlog" , .mode = 0200}, |
533 | .write = eventlog_write, |
534 | }; |
535 | |
536 | static ssize_t gsmi_clear_eventlog_store(struct kobject *kobj, |
537 | struct kobj_attribute *attr, |
538 | const char *buf, size_t count) |
539 | { |
540 | int rc; |
541 | unsigned long flags; |
542 | unsigned long val; |
543 | struct { |
544 | u32 percentage; |
545 | u32 data_type; |
546 | } param; |
547 | |
548 | rc = kstrtoul(s: buf, base: 0, res: &val); |
549 | if (rc) |
550 | return rc; |
551 | |
552 | /* |
553 | * Value entered is a percentage, 0 through 100, anything else |
554 | * is invalid. |
555 | */ |
556 | if (val > 100) |
557 | return -EINVAL; |
558 | |
559 | /* data_type here selects the smbios event log. */ |
560 | param.percentage = val; |
561 | param.data_type = 0; |
562 | |
563 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
564 | |
565 | /* parameter buffer */ |
566 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
567 | memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); |
568 | |
569 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_CLEAR_EVENT_LOG); |
570 | |
571 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
572 | |
573 | if (rc) |
574 | return rc; |
575 | return count; |
576 | } |
577 | |
578 | static struct kobj_attribute gsmi_clear_eventlog_attr = { |
579 | .attr = {.name = "clear_eventlog" , .mode = 0200}, |
580 | .store = gsmi_clear_eventlog_store, |
581 | }; |
582 | |
583 | static ssize_t gsmi_clear_config_store(struct kobject *kobj, |
584 | struct kobj_attribute *attr, |
585 | const char *buf, size_t count) |
586 | { |
587 | int rc; |
588 | unsigned long flags; |
589 | |
590 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
591 | |
592 | /* clear parameter buffer */ |
593 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
594 | |
595 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_CLEAR_CONFIG); |
596 | |
597 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
598 | |
599 | if (rc) |
600 | return rc; |
601 | return count; |
602 | } |
603 | |
604 | static struct kobj_attribute gsmi_clear_config_attr = { |
605 | .attr = {.name = "clear_config" , .mode = 0200}, |
606 | .store = gsmi_clear_config_store, |
607 | }; |
608 | |
609 | static const struct attribute *gsmi_attrs[] = { |
610 | &gsmi_clear_config_attr.attr, |
611 | &gsmi_clear_eventlog_attr.attr, |
612 | NULL, |
613 | }; |
614 | |
615 | static int gsmi_shutdown_reason(int reason) |
616 | { |
617 | struct gsmi_log_entry_type_1 entry = { |
618 | .type = GSMI_LOG_ENTRY_TYPE_KERNEL, |
619 | .instance = reason, |
620 | }; |
621 | struct gsmi_set_eventlog_param param = { |
622 | .data_len = sizeof(entry), |
623 | .type = 1, |
624 | }; |
625 | static int saved_reason; |
626 | int rc = 0; |
627 | unsigned long flags; |
628 | |
629 | /* avoid duplicate entries in the log */ |
630 | if (saved_reason & (1 << reason)) |
631 | return 0; |
632 | |
633 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
634 | |
635 | saved_reason |= (1 << reason); |
636 | |
637 | /* data pointer */ |
638 | memset(gsmi_dev.data_buf->start, 0, gsmi_dev.data_buf->length); |
639 | memcpy(gsmi_dev.data_buf->start, &entry, sizeof(entry)); |
640 | |
641 | /* parameter buffer */ |
642 | param.data_ptr = gsmi_dev.data_buf->address; |
643 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
644 | memcpy(gsmi_dev.param_buf->start, ¶m, sizeof(param)); |
645 | |
646 | rc = gsmi_exec(GSMI_CALLBACK, GSMI_CMD_SET_EVENT_LOG); |
647 | |
648 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
649 | |
650 | if (rc < 0) |
651 | printk(KERN_ERR "gsmi: Log Shutdown Reason failed\n" ); |
652 | else |
653 | printk(KERN_EMERG "gsmi: Log Shutdown Reason 0x%02x\n" , |
654 | reason); |
655 | |
656 | return rc; |
657 | } |
658 | |
659 | static int gsmi_reboot_callback(struct notifier_block *nb, |
660 | unsigned long reason, void *arg) |
661 | { |
662 | gsmi_shutdown_reason(GSMI_SHUTDOWN_CLEAN); |
663 | return NOTIFY_DONE; |
664 | } |
665 | |
666 | static struct notifier_block gsmi_reboot_notifier = { |
667 | .notifier_call = gsmi_reboot_callback |
668 | }; |
669 | |
670 | static int gsmi_die_callback(struct notifier_block *nb, |
671 | unsigned long reason, void *arg) |
672 | { |
673 | if (reason == DIE_OOPS) |
674 | gsmi_shutdown_reason(GSMI_SHUTDOWN_OOPS); |
675 | return NOTIFY_DONE; |
676 | } |
677 | |
678 | static struct notifier_block gsmi_die_notifier = { |
679 | .notifier_call = gsmi_die_callback |
680 | }; |
681 | |
682 | static int gsmi_panic_callback(struct notifier_block *nb, |
683 | unsigned long reason, void *arg) |
684 | { |
685 | |
686 | /* |
687 | * Panic callbacks are executed with all other CPUs stopped, |
688 | * so we must not attempt to spin waiting for gsmi_dev.lock |
689 | * to be released. |
690 | */ |
691 | if (spin_is_locked(lock: &gsmi_dev.lock)) |
692 | return NOTIFY_DONE; |
693 | |
694 | gsmi_shutdown_reason(GSMI_SHUTDOWN_PANIC); |
695 | return NOTIFY_DONE; |
696 | } |
697 | |
698 | static struct notifier_block gsmi_panic_notifier = { |
699 | .notifier_call = gsmi_panic_callback, |
700 | }; |
701 | |
702 | /* |
703 | * This hash function was blatantly copied from include/linux/hash.h. |
704 | * It is used by this driver to obfuscate a board name that requires a |
705 | * quirk within this driver. |
706 | * |
707 | * Please do not remove this copy of the function as any changes to the |
708 | * global utility hash_64() function would break this driver's ability |
709 | * to identify a board and provide the appropriate quirk -- mikew@google.com |
710 | */ |
711 | static u64 __init local_hash_64(u64 val, unsigned bits) |
712 | { |
713 | u64 hash = val; |
714 | |
715 | /* Sigh, gcc can't optimise this alone like it does for 32 bits. */ |
716 | u64 n = hash; |
717 | n <<= 18; |
718 | hash -= n; |
719 | n <<= 33; |
720 | hash -= n; |
721 | n <<= 3; |
722 | hash += n; |
723 | n <<= 3; |
724 | hash -= n; |
725 | n <<= 4; |
726 | hash += n; |
727 | n <<= 2; |
728 | hash += n; |
729 | |
730 | /* High bits are more random, so use them. */ |
731 | return hash >> (64 - bits); |
732 | } |
733 | |
734 | static u32 __init hash_oem_table_id(char s[8]) |
735 | { |
736 | u64 input; |
737 | memcpy(&input, s, 8); |
738 | return local_hash_64(val: input, bits: 32); |
739 | } |
740 | |
741 | static const struct dmi_system_id gsmi_dmi_table[] __initconst = { |
742 | { |
743 | .ident = "Google Board" , |
744 | .matches = { |
745 | DMI_MATCH(DMI_BOARD_VENDOR, "Google, Inc." ), |
746 | }, |
747 | }, |
748 | { |
749 | .ident = "Coreboot Firmware" , |
750 | .matches = { |
751 | DMI_MATCH(DMI_BIOS_VENDOR, "coreboot" ), |
752 | }, |
753 | }, |
754 | {} |
755 | }; |
756 | MODULE_DEVICE_TABLE(dmi, gsmi_dmi_table); |
757 | |
758 | static __init int gsmi_system_valid(void) |
759 | { |
760 | u32 hash; |
761 | u16 cmd, result; |
762 | |
763 | if (!dmi_check_system(list: gsmi_dmi_table)) |
764 | return -ENODEV; |
765 | |
766 | /* |
767 | * Only newer firmware supports the gsmi interface. All older |
768 | * firmware that didn't support this interface used to plug the |
769 | * table name in the first four bytes of the oem_table_id field. |
770 | * Newer firmware doesn't do that though, so use that as the |
771 | * discriminant factor. We have to do this in order to |
772 | * whitewash our board names out of the public driver. |
773 | */ |
774 | if (!strncmp(acpi_gbl_FADT.header.oem_table_id, "FACP" , 4)) { |
775 | printk(KERN_INFO "gsmi: Board is too old\n" ); |
776 | return -ENODEV; |
777 | } |
778 | |
779 | /* Disable on board with 1.0 BIOS due to Google bug 2602657 */ |
780 | hash = hash_oem_table_id(s: acpi_gbl_FADT.header.oem_table_id); |
781 | if (hash == QUIRKY_BOARD_HASH) { |
782 | const char *bios_ver = dmi_get_system_info(field: DMI_BIOS_VERSION); |
783 | if (strncmp(bios_ver, "1.0" , 3) == 0) { |
784 | pr_info("gsmi: disabled on this board's BIOS %s\n" , |
785 | bios_ver); |
786 | return -ENODEV; |
787 | } |
788 | } |
789 | |
790 | /* check for valid SMI command port in ACPI FADT */ |
791 | if (acpi_gbl_FADT.smi_command == 0) { |
792 | pr_info("gsmi: missing smi_command\n" ); |
793 | return -ENODEV; |
794 | } |
795 | |
796 | /* Test the smihandler with a bogus command. If it leaves the |
797 | * calling argument in %ax untouched, there is no handler for |
798 | * GSMI commands. |
799 | */ |
800 | cmd = GSMI_CALLBACK | GSMI_CMD_RESERVED << 8; |
801 | asm volatile ( |
802 | "outb %%al, %%dx\n\t" |
803 | : "=a" (result) |
804 | : "0" (cmd), |
805 | "d" (acpi_gbl_FADT.smi_command) |
806 | : "memory" , "cc" |
807 | ); |
808 | if (cmd == result) { |
809 | pr_info("gsmi: no gsmi handler in firmware\n" ); |
810 | return -ENODEV; |
811 | } |
812 | |
813 | /* Found */ |
814 | return 0; |
815 | } |
816 | |
817 | static struct kobject *gsmi_kobj; |
818 | |
819 | static const struct platform_device_info gsmi_dev_info = { |
820 | .name = "gsmi" , |
821 | .id = -1, |
822 | /* SMI callbacks require 32bit addresses */ |
823 | .dma_mask = DMA_BIT_MASK(32), |
824 | }; |
825 | |
826 | #ifdef CONFIG_PM |
827 | static void gsmi_log_s0ix_info(u8 cmd) |
828 | { |
829 | unsigned long flags; |
830 | |
831 | /* |
832 | * If platform has not enabled S0ix logging, then no action is |
833 | * necessary. |
834 | */ |
835 | if (!s0ix_logging_enable) |
836 | return; |
837 | |
838 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
839 | |
840 | memset(gsmi_dev.param_buf->start, 0, gsmi_dev.param_buf->length); |
841 | |
842 | gsmi_exec(GSMI_CALLBACK, sub: cmd); |
843 | |
844 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
845 | } |
846 | |
847 | static int gsmi_log_s0ix_suspend(struct device *dev) |
848 | { |
849 | /* |
850 | * If system is not suspending via firmware using the standard ACPI Sx |
851 | * types, then make a GSMI call to log the suspend info. |
852 | */ |
853 | if (!pm_suspend_via_firmware()) |
854 | gsmi_log_s0ix_info(GSMI_CMD_LOG_S0IX_SUSPEND); |
855 | |
856 | /* |
857 | * Always return success, since we do not want suspend |
858 | * to fail just because of logging failure. |
859 | */ |
860 | return 0; |
861 | } |
862 | |
863 | static int gsmi_log_s0ix_resume(struct device *dev) |
864 | { |
865 | /* |
866 | * If system did not resume via firmware, then make a GSMI call to log |
867 | * the resume info and wake source. |
868 | */ |
869 | if (!pm_resume_via_firmware()) |
870 | gsmi_log_s0ix_info(GSMI_CMD_LOG_S0IX_RESUME); |
871 | |
872 | /* |
873 | * Always return success, since we do not want resume |
874 | * to fail just because of logging failure. |
875 | */ |
876 | return 0; |
877 | } |
878 | |
879 | static const struct dev_pm_ops gsmi_pm_ops = { |
880 | .suspend_noirq = gsmi_log_s0ix_suspend, |
881 | .resume_noirq = gsmi_log_s0ix_resume, |
882 | }; |
883 | |
884 | static int gsmi_platform_driver_probe(struct platform_device *dev) |
885 | { |
886 | return 0; |
887 | } |
888 | |
889 | static struct platform_driver gsmi_driver_info = { |
890 | .driver = { |
891 | .name = "gsmi" , |
892 | .pm = &gsmi_pm_ops, |
893 | }, |
894 | .probe = gsmi_platform_driver_probe, |
895 | }; |
896 | #endif |
897 | |
898 | static __init int gsmi_init(void) |
899 | { |
900 | unsigned long flags; |
901 | int ret; |
902 | |
903 | ret = gsmi_system_valid(); |
904 | if (ret) |
905 | return ret; |
906 | |
907 | gsmi_dev.smi_cmd = acpi_gbl_FADT.smi_command; |
908 | |
909 | #ifdef CONFIG_PM |
910 | ret = platform_driver_register(&gsmi_driver_info); |
911 | if (unlikely(ret)) { |
912 | printk(KERN_ERR "gsmi: unable to register platform driver\n" ); |
913 | return ret; |
914 | } |
915 | #endif |
916 | |
917 | /* register device */ |
918 | gsmi_dev.pdev = platform_device_register_full(pdevinfo: &gsmi_dev_info); |
919 | if (IS_ERR(ptr: gsmi_dev.pdev)) { |
920 | printk(KERN_ERR "gsmi: unable to register platform device\n" ); |
921 | return PTR_ERR(ptr: gsmi_dev.pdev); |
922 | } |
923 | |
924 | /* SMI access needs to be serialized */ |
925 | spin_lock_init(&gsmi_dev.lock); |
926 | |
927 | ret = -ENOMEM; |
928 | |
929 | /* |
930 | * SLAB cache is created using SLAB_CACHE_DMA32 to ensure that the |
931 | * allocations for gsmi_buf come from the DMA32 memory zone. These |
932 | * buffers have nothing to do with DMA. They are required for |
933 | * communication with firmware executing in SMI mode which can only |
934 | * access the bottom 4GiB of physical memory. Since DMA32 memory zone |
935 | * guarantees allocation under the 4GiB boundary, this driver creates |
936 | * a SLAB cache with SLAB_CACHE_DMA32 flag. |
937 | */ |
938 | gsmi_dev.mem_pool = kmem_cache_create(name: "gsmi" , GSMI_BUF_SIZE, |
939 | GSMI_BUF_ALIGN, |
940 | SLAB_CACHE_DMA32, NULL); |
941 | if (!gsmi_dev.mem_pool) |
942 | goto out_err; |
943 | |
944 | /* |
945 | * pre-allocate buffers because sometimes we are called when |
946 | * this is not feasible: oops, panic, die, mce, etc |
947 | */ |
948 | gsmi_dev.name_buf = gsmi_buf_alloc(); |
949 | if (!gsmi_dev.name_buf) { |
950 | printk(KERN_ERR "gsmi: failed to allocate name buffer\n" ); |
951 | goto out_err; |
952 | } |
953 | |
954 | gsmi_dev.data_buf = gsmi_buf_alloc(); |
955 | if (!gsmi_dev.data_buf) { |
956 | printk(KERN_ERR "gsmi: failed to allocate data buffer\n" ); |
957 | goto out_err; |
958 | } |
959 | |
960 | gsmi_dev.param_buf = gsmi_buf_alloc(); |
961 | if (!gsmi_dev.param_buf) { |
962 | printk(KERN_ERR "gsmi: failed to allocate param buffer\n" ); |
963 | goto out_err; |
964 | } |
965 | |
966 | /* |
967 | * Determine type of handshake used to serialize the SMI |
968 | * entry. See also gsmi_exec(). |
969 | * |
970 | * There's a "behavior" present on some chipsets where writing the |
971 | * SMI trigger register in the southbridge doesn't result in an |
972 | * immediate SMI. Rather, the processor can execute "a few" more |
973 | * instructions before the SMI takes effect. To ensure synchronous |
974 | * behavior, implement a handshake between the kernel driver and the |
975 | * firmware handler to spin until released. This ioctl determines |
976 | * the type of handshake. |
977 | * |
978 | * NONE: The firmware handler does not implement any |
979 | * handshake. Either it doesn't need to, or it's legacy firmware |
980 | * that doesn't know it needs to and never will. |
981 | * |
982 | * CF: The firmware handler will clear the CF in the saved |
983 | * state before returning. The driver may set the CF and test for |
984 | * it to clear before proceeding. |
985 | * |
986 | * SPIN: The firmware handler does not implement any handshake |
987 | * but the driver should spin for a hundred or so microseconds |
988 | * to ensure the SMI has triggered. |
989 | * |
990 | * Finally, the handler will return -ENOSYS if |
991 | * GSMI_CMD_HANDSHAKE_TYPE is unimplemented, which implies |
992 | * HANDSHAKE_NONE. |
993 | */ |
994 | spin_lock_irqsave(&gsmi_dev.lock, flags); |
995 | gsmi_dev.handshake_type = GSMI_HANDSHAKE_SPIN; |
996 | gsmi_dev.handshake_type = |
997 | gsmi_exec(GSMI_CALLBACK, GSMI_CMD_HANDSHAKE_TYPE); |
998 | if (gsmi_dev.handshake_type == -ENOSYS) |
999 | gsmi_dev.handshake_type = GSMI_HANDSHAKE_NONE; |
1000 | spin_unlock_irqrestore(lock: &gsmi_dev.lock, flags); |
1001 | |
1002 | /* Remove and clean up gsmi if the handshake could not complete. */ |
1003 | if (gsmi_dev.handshake_type == -ENXIO) { |
1004 | printk(KERN_INFO "gsmi version " DRIVER_VERSION |
1005 | " failed to load\n" ); |
1006 | ret = -ENODEV; |
1007 | goto out_err; |
1008 | } |
1009 | |
1010 | /* Register in the firmware directory */ |
1011 | ret = -ENOMEM; |
1012 | gsmi_kobj = kobject_create_and_add(name: "gsmi" , parent: firmware_kobj); |
1013 | if (!gsmi_kobj) { |
1014 | printk(KERN_INFO "gsmi: Failed to create firmware kobj\n" ); |
1015 | goto out_err; |
1016 | } |
1017 | |
1018 | /* Setup eventlog access */ |
1019 | ret = sysfs_create_bin_file(kobj: gsmi_kobj, attr: &eventlog_bin_attr); |
1020 | if (ret) { |
1021 | printk(KERN_INFO "gsmi: Failed to setup eventlog" ); |
1022 | goto out_err; |
1023 | } |
1024 | |
1025 | /* Other attributes */ |
1026 | ret = sysfs_create_files(kobj: gsmi_kobj, attr: gsmi_attrs); |
1027 | if (ret) { |
1028 | printk(KERN_INFO "gsmi: Failed to add attrs" ); |
1029 | goto out_remove_bin_file; |
1030 | } |
1031 | |
1032 | #ifdef CONFIG_EFI |
1033 | ret = efivars_register(efivars: &efivars, ops: &efivar_ops); |
1034 | if (ret) { |
1035 | printk(KERN_INFO "gsmi: Failed to register efivars\n" ); |
1036 | sysfs_remove_files(kobj: gsmi_kobj, attr: gsmi_attrs); |
1037 | goto out_remove_bin_file; |
1038 | } |
1039 | #endif |
1040 | |
1041 | register_reboot_notifier(&gsmi_reboot_notifier); |
1042 | register_die_notifier(nb: &gsmi_die_notifier); |
1043 | atomic_notifier_chain_register(nh: &panic_notifier_list, |
1044 | nb: &gsmi_panic_notifier); |
1045 | |
1046 | printk(KERN_INFO "gsmi version " DRIVER_VERSION " loaded\n" ); |
1047 | |
1048 | return 0; |
1049 | |
1050 | out_remove_bin_file: |
1051 | sysfs_remove_bin_file(kobj: gsmi_kobj, attr: &eventlog_bin_attr); |
1052 | out_err: |
1053 | kobject_put(kobj: gsmi_kobj); |
1054 | gsmi_buf_free(smibuf: gsmi_dev.param_buf); |
1055 | gsmi_buf_free(smibuf: gsmi_dev.data_buf); |
1056 | gsmi_buf_free(smibuf: gsmi_dev.name_buf); |
1057 | kmem_cache_destroy(s: gsmi_dev.mem_pool); |
1058 | platform_device_unregister(gsmi_dev.pdev); |
1059 | pr_info("gsmi: failed to load: %d\n" , ret); |
1060 | #ifdef CONFIG_PM |
1061 | platform_driver_unregister(&gsmi_driver_info); |
1062 | #endif |
1063 | return ret; |
1064 | } |
1065 | |
1066 | static void __exit gsmi_exit(void) |
1067 | { |
1068 | unregister_reboot_notifier(&gsmi_reboot_notifier); |
1069 | unregister_die_notifier(nb: &gsmi_die_notifier); |
1070 | atomic_notifier_chain_unregister(nh: &panic_notifier_list, |
1071 | nb: &gsmi_panic_notifier); |
1072 | #ifdef CONFIG_EFI |
1073 | efivars_unregister(efivars: &efivars); |
1074 | #endif |
1075 | |
1076 | sysfs_remove_files(kobj: gsmi_kobj, attr: gsmi_attrs); |
1077 | sysfs_remove_bin_file(kobj: gsmi_kobj, attr: &eventlog_bin_attr); |
1078 | kobject_put(kobj: gsmi_kobj); |
1079 | gsmi_buf_free(smibuf: gsmi_dev.param_buf); |
1080 | gsmi_buf_free(smibuf: gsmi_dev.data_buf); |
1081 | gsmi_buf_free(smibuf: gsmi_dev.name_buf); |
1082 | kmem_cache_destroy(s: gsmi_dev.mem_pool); |
1083 | platform_device_unregister(gsmi_dev.pdev); |
1084 | #ifdef CONFIG_PM |
1085 | platform_driver_unregister(&gsmi_driver_info); |
1086 | #endif |
1087 | } |
1088 | |
1089 | module_init(gsmi_init); |
1090 | module_exit(gsmi_exit); |
1091 | |
1092 | MODULE_AUTHOR("Google, Inc." ); |
1093 | MODULE_LICENSE("GPL" ); |
1094 | |