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