linux/drivers/firmware/google/gsmi.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2010 Google Inc. All Rights Reserved.
 * Author: [email protected] (Duncan Laurie)
 *
 * Re-worked to expose sysfs APIs by [email protected] (Mike Waychison)
 *
 * EFI SMI interface for Google platforms
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/panic_notifier.h>
#include <linux/ioctl.h>
#include <linux/acpi.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/dmi.h>
#include <linux/kdebug.h>
#include <linux/reboot.h>
#include <linux/efi.h>
#include <linux/module.h>
#include <linux/ucs2_string.h>
#include <linux/suspend.h>

#define GSMI_SHUTDOWN_CLEAN
/* TODO([email protected]): Tie in HARDLOCKUP_DETECTOR with NMIWDT */
#define GSMI_SHUTDOWN_NMIWDT
#define GSMI_SHUTDOWN_PANIC
#define GSMI_SHUTDOWN_OOPS
#define GSMI_SHUTDOWN_DIE
#define GSMI_SHUTDOWN_MCE
#define GSMI_SHUTDOWN_SOFTWDT
#define GSMI_SHUTDOWN_MBE
#define GSMI_SHUTDOWN_TRIPLE

#define DRIVER_VERSION
#define GSMI_GUID_SIZE
#define GSMI_BUF_SIZE
#define GSMI_BUF_ALIGN
#define GSMI_CALLBACK

/* SMI return codes */
#define GSMI_SUCCESS
#define GSMI_UNSUPPORTED2
#define GSMI_LOG_FULL
#define GSMI_VAR_NOT_FOUND
#define GSMI_HANDSHAKE_SPIN
#define GSMI_HANDSHAKE_CF
#define GSMI_HANDSHAKE_NONE
#define GSMI_INVALID_PARAMETER
#define GSMI_UNSUPPORTED
#define GSMI_BUFFER_TOO_SMALL
#define GSMI_NOT_READY
#define GSMI_DEVICE_ERROR
#define GSMI_NOT_FOUND

#define QUIRKY_BOARD_HASH

/* Internally used commands passed to the firmware */
#define GSMI_CMD_GET_NVRAM_VAR
#define GSMI_CMD_GET_NEXT_VAR
#define GSMI_CMD_SET_NVRAM_VAR
#define GSMI_CMD_SET_EVENT_LOG
#define GSMI_CMD_CLEAR_EVENT_LOG
#define GSMI_CMD_LOG_S0IX_SUSPEND
#define GSMI_CMD_LOG_S0IX_RESUME
#define GSMI_CMD_CLEAR_CONFIG
#define GSMI_CMD_HANDSHAKE_TYPE
#define GSMI_CMD_RESERVED

/* Magic entry type for kernel events */
#define GSMI_LOG_ENTRY_TYPE_KERNEL

/* SMI buffers must be in 32bit physical address space */
struct gsmi_buf {};

static struct gsmi_device {} gsmi_dev;

/* Packed structures for communicating with the firmware */
struct gsmi_nvram_var_param {} __packed;

struct gsmi_get_next_var_param {} __packed;

struct gsmi_set_eventlog_param {} __packed;

/* Event log formats */
struct gsmi_log_entry_type_1 {} __packed;

/*
 * Some platforms don't have explicit SMI handshake
 * and need to wait for SMI to complete.
 */
#define GSMI_DEFAULT_SPINCOUNT
static unsigned int spincount =;
module_param(spincount, uint, 0600);
MODULE_PARM_DESC();

/*
 * Some older platforms with Apollo Lake chipsets do not support S0ix logging
 * in their GSMI handlers, and behaved poorly when resuming via power button
 * press if the logging was attempted. Updated firmware with proper behavior
 * has long since shipped, removing the need for this opt-in parameter. It
 * now exists as an opt-out parameter for folks defiantly running old
 * firmware, or unforeseen circumstances. After the change from opt-in to
 * opt-out has baked sufficiently, this parameter should probably be removed
 * entirely.
 */
static bool s0ix_logging_enable =;
module_param(s0ix_logging_enable, bool, 0600);

static struct gsmi_buf *gsmi_buf_alloc(void)
{}

static void gsmi_buf_free(struct gsmi_buf *smibuf)
{}

/*
 * Make a call to gsmi func(sub).  GSMI error codes are translated to
 * in-kernel errnos (0 on success, -ERRNO on error).
 */
static int gsmi_exec(u8 func, u8 sub)
{}

#ifdef CONFIG_EFI

static struct efivars efivars;

static efi_status_t gsmi_get_variable(efi_char16_t *name,
				      efi_guid_t *vendor, u32 *attr,
				      unsigned long *data_size,
				      void *data)
{}

static efi_status_t gsmi_get_next_variable(unsigned long *name_size,
					   efi_char16_t *name,
					   efi_guid_t *vendor)
{}

static efi_status_t gsmi_set_variable(efi_char16_t *name,
				      efi_guid_t *vendor,
				      u32 attr,
				      unsigned long data_size,
				      void *data)
{}

static const struct efivar_operations efivar_ops =;

#endif /* CONFIG_EFI */

static ssize_t eventlog_write(struct file *filp, struct kobject *kobj,
			       struct bin_attribute *bin_attr,
			       char *buf, loff_t pos, size_t count)
{}

static struct bin_attribute eventlog_bin_attr =;

static ssize_t gsmi_clear_eventlog_store(struct kobject *kobj,
					 struct kobj_attribute *attr,
					 const char *buf, size_t count)
{}

static struct kobj_attribute gsmi_clear_eventlog_attr =;

static ssize_t gsmi_clear_config_store(struct kobject *kobj,
				       struct kobj_attribute *attr,
				       const char *buf, size_t count)
{}

static struct kobj_attribute gsmi_clear_config_attr =;

static const struct attribute *gsmi_attrs[] =;

static int gsmi_shutdown_reason(int reason)
{}

static int gsmi_reboot_callback(struct notifier_block *nb,
				unsigned long reason, void *arg)
{}

static struct notifier_block gsmi_reboot_notifier =;

static int gsmi_die_callback(struct notifier_block *nb,
			     unsigned long reason, void *arg)
{}

static struct notifier_block gsmi_die_notifier =;

static int gsmi_panic_callback(struct notifier_block *nb,
			       unsigned long reason, void *arg)
{}

static struct notifier_block gsmi_panic_notifier =;

/*
 * This hash function was blatantly copied from include/linux/hash.h.
 * It is used by this driver to obfuscate a board name that requires a
 * quirk within this driver.
 *
 * Please do not remove this copy of the function as any changes to the
 * global utility hash_64() function would break this driver's ability
 * to identify a board and provide the appropriate quirk -- [email protected]
 */
static u64 __init local_hash_64(u64 val, unsigned bits)
{}

static u32 __init hash_oem_table_id(char s[8])
{}

static const struct dmi_system_id gsmi_dmi_table[] __initconst =;
MODULE_DEVICE_TABLE(dmi, gsmi_dmi_table);

static __init int gsmi_system_valid(void)
{}

static struct kobject *gsmi_kobj;

static const struct platform_device_info gsmi_dev_info =;

#ifdef CONFIG_PM
static void gsmi_log_s0ix_info(u8 cmd)
{}

static int gsmi_log_s0ix_suspend(struct device *dev)
{}

static int gsmi_log_s0ix_resume(struct device *dev)
{}

static const struct dev_pm_ops gsmi_pm_ops =;

static int gsmi_platform_driver_probe(struct platform_device *dev)
{}

static struct platform_driver gsmi_driver_info =;
#endif

static __init int gsmi_init(void)
{}

static void __exit gsmi_exit(void)
{}

module_init();
module_exit(gsmi_exit);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();