diff mbox

[RFC,v2,2/8] platform/chrome: ChromeOS firmware interface driver

Message ID 1508167900-27415-3-git-send-email-ulrich.hecht+renesas@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ulrich Hecht Oct. 16, 2017, 3:31 p.m. UTC
Ported from chromeos-3.18 kernel.

Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/platform/chrome/Kconfig        |  18 +++
 drivers/platform/chrome/Makefile       |   2 +
 drivers/platform/chrome/chromeos.c     | 120 +++++++++++++++
 drivers/platform/chrome/chromeos.h     |  61 ++++++++
 drivers/platform/chrome/chromeos_arm.c | 264 +++++++++++++++++++++++++++++++++
 drivers/platform/chrome/elog.h         | 186 +++++++++++++++++++++++
 include/linux/chromeos_platform.h      |  27 ++++
 7 files changed, 678 insertions(+)
 create mode 100644 drivers/platform/chrome/chromeos.c
 create mode 100644 drivers/platform/chrome/chromeos.h
 create mode 100644 drivers/platform/chrome/chromeos_arm.c
 create mode 100644 drivers/platform/chrome/elog.h
 create mode 100644 include/linux/chromeos_platform.h
diff mbox

Patch

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 0ad6e29..f8b1876 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -14,6 +14,24 @@  menuconfig CHROME_PLATFORMS
 
 if CHROME_PLATFORMS
 
+config CHROMEOS
+	bool
+	depends on CHROMEOS_OF_FIRMWARE || (NVRAM && ACPI_CHROMEOS)
+
+	---help---
+	  Provides abstracted interfaces to the firmware features provided on
+	  ChromeOS devices. It depends on a lowlevel driver to implement the
+	  firmware interface on the platform.
+
+config CHROMEOS_OF_FIRMWARE
+	bool "ChromeOS firmware interface driver"
+	depends on OF
+	select CHROMEOS
+	---help---
+	  This driver provides an interface to ChromeOS firmware.
+
+	  Say Y here if you are building for a ChromeOS device.
+
 config CHROMEOS_LAPTOP
 	tristate "Chrome OS Laptop"
 	depends on I2C && DMI && X86
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 66c345c..f10a7b6 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -1,4 +1,6 @@ 
 
+obj-$(CONFIG_CHROMEOS)		+= chromeos.o
+obj-$(CONFIG_CHROMEOS_OF_FIRMWARE) += chromeos_arm.o
 obj-$(CONFIG_CHROMEOS_LAPTOP)		+= chromeos_laptop.o
 obj-$(CONFIG_CHROMEOS_PSTORE)		+= chromeos_pstore.o
 cros_ec_devs-objs			:= cros_ec_dev.o cros_ec_sysfs.o \
diff --git a/drivers/platform/chrome/chromeos.c b/drivers/platform/chrome/chromeos.c
new file mode 100644
index 0000000..8b01630
--- /dev/null
+++ b/drivers/platform/chrome/chromeos.c
@@ -0,0 +1,120 @@ 
+/*
+ *  ChromeOS platform support code. Glue layer between higher level functions
+ *  and per-platform firmware interfaces.
+ *
+ *  Copyright (C) 2010 The Chromium OS Authors
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/chromeos_platform.h>
+#include <linux/module.h>
+#include "chromeos.h"
+
+static struct chromeos_vbc *chromeos_vbc_ptr;
+
+static int vbc_read(u8 *buf, int buf_size);
+static int vbc_write_byte(unsigned offset, u8 value);
+
+/* the following defines are copied from
+ * vboot_reference:firmware/lib/vboot_nvstorage.c.
+ */
+#define RECOVERY_OFFSET              2
+#define VBNV_RECOVERY_RW_INVALID_OS  0x43
+
+int chromeos_set_need_recovery(void)
+{
+	if (!chromeos_legacy_set_need_recovery())
+		return 0;
+
+	return vbc_write_byte(RECOVERY_OFFSET, VBNV_RECOVERY_RW_INVALID_OS);
+}
+EXPORT_SYMBOL(chromeos_set_need_recovery);
+
+/*
+ * Lifted from vboot_reference:firmware/lib/vboot_nvstorage.c and formatted.
+ *
+ * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based
+ * algorithm would be faster, but for only 15 bytes isn't worth the code size.
+ */
+static u8 crc8(const u8 *data, int len)
+{
+	unsigned crc = 0;
+	int i, j;
+
+	for (j = len; j; j--, data++) {
+		crc ^= (*data << 8);
+		for (i = 8; i; i--) {
+			if (crc & 0x8000)
+				crc ^= (0x1070 << 3);
+			crc <<= 1;
+		}
+	}
+	return (u8)(crc >> 8);
+}
+
+static int vbc_write_byte(unsigned offset, u8 value)
+{
+	u8 buf[MAX_VBOOT_CONTEXT_BUFFER_SIZE];
+	ssize_t size;
+
+	if (!chromeos_vbc_ptr)
+		return -ENOSYS;
+
+	size = vbc_read(buf, sizeof(buf));
+	if (size <= 0)
+		return -EINVAL;
+
+	if (offset >= (size - 1))
+		return -EINVAL;
+
+	if (buf[offset] == value)
+		return 0;
+
+	buf[offset] = value;
+	buf[size - 1] = crc8(buf, size - 1);
+
+	return chromeos_vbc_ptr->write(buf, size);
+}
+
+/*
+ * Read vboot context and verify it.  If everything checks out, return number
+ * of bytes in the vboot context buffer, -1 on any error (uninitialized
+ * subsystem, corrupted crc8 value, not enough room in the buffer, etc.).
+ */
+static int vbc_read(u8 *buf, int buf_size)
+{
+	ssize_t size;
+
+	if (!chromeos_vbc_ptr)
+		return -ENOSYS;
+
+	size = chromeos_vbc_ptr->read(buf, buf_size);
+	if (size <= 0)
+		return -1;
+
+	if (buf[size - 1] != crc8(buf, size - 1)) {
+		pr_err("%s: vboot context contents corrupted\n", __func__);
+		return -1;
+	}
+	return size;
+}
+
+int chromeos_vbc_register(struct chromeos_vbc *chromeos_vbc)
+{
+	chromeos_vbc_ptr = chromeos_vbc;
+	return 0;
+}
diff --git a/drivers/platform/chrome/chromeos.h b/drivers/platform/chrome/chromeos.h
new file mode 100644
index 0000000..8f4384a
--- /dev/null
+++ b/drivers/platform/chrome/chromeos.h
@@ -0,0 +1,61 @@ 
+/*
+ *  Copyright (C) 2011 The Chromium OS Authors
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef _DRIVERS_PLATFORM_CHROMEOS_H
+#define _DRIVERS_PLATFORM_CHROMEOS_H
+
+#define MAX_VBOOT_CONTEXT_BUFFER_SIZE 64  /* Should be enough for anything. */
+
+#ifdef CONFIG_ACPI_CHROMEOS
+extern int chromeos_legacy_set_need_recovery(void);
+#else
+static inline int chromeos_legacy_set_need_recovery(void) { return -ENODEV; }
+#endif
+
+struct chromeos_vbc {
+	/**
+	 * Read vboot context to buffer
+	 *
+	 * @param buf		Pointer to buffer for storing vboot context
+	 * @param count		Size of buffer
+	 * @return	on success, the number of bytes read is returned and
+	 *		on error, -err is returned.
+	 */
+	ssize_t (*read)(void *buf, size_t count);
+
+	/**
+	 * Write vboot context from buffer
+	 *
+	 * @param buf		Pointer to buffer of new vboot context content
+	 * @param count		Size of buffer
+	 * @return	on success, the number of bytes written is returned and
+	 *		on error, -err is returned.
+	 */
+	ssize_t (*write)(const void *buf, size_t count);
+
+	const char *name;
+};
+
+/**
+ * Register chromeos_vbc callbacks.
+ *
+ * @param chromeos_vbc	Pointer to struct holding callbacks
+ * @return	on success, return 0, on error, -err is returned.
+ */
+int chromeos_vbc_register(struct chromeos_vbc *chromeos_vbc);
+
+#endif /* _DRIVERS_PLATFORM_CHROMEOS_H */
diff --git a/drivers/platform/chrome/chromeos_arm.c b/drivers/platform/chrome/chromeos_arm.c
new file mode 100644
index 0000000..337e24d
--- /dev/null
+++ b/drivers/platform/chrome/chromeos_arm.c
@@ -0,0 +1,264 @@ 
+/*
+ *  Copyright (C) 2011 The Chromium OS Authors
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt) "chromeos_arm: " fmt
+
+#include <linux/bcd.h>
+#include <linux/gpio.h>
+#include <linux/notifier.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "chromeos.h"
+#include "elog.h"
+
+struct chromeos_arm_elog_panic_buffer {
+	uint32_t start;
+	uint32_t size;
+	void __iomem *virt_addr;
+	struct notifier_block nb;
+};
+
+/*
+ * Update the checksum at the last byte
+ */
+static void elog_update_checksum(struct event_header *event, u8 checksum)
+{
+	u8 *event_data = (u8 *)event;
+	event_data[event->length - 1] = checksum;
+}
+
+/*
+ * Simple byte checksum for events
+ */
+static u8 elog_checksum_event(struct event_header *event)
+{
+	u8 index, checksum = 0;
+	u8 *data = (u8 *)event;
+
+	for (index = 0; index < event->length; index++)
+		checksum += data[index];
+	return checksum;
+}
+
+/*
+ * Populate timestamp in event header with current time
+ */
+static void elog_fill_timestamp(struct event_header *event)
+{
+	struct timeval timeval;
+	struct tm time;
+
+	do_gettimeofday(&timeval);
+	time_to_tm(timeval.tv_sec, 0, &time);
+
+	event->second = bin2bcd(time.tm_sec);
+	event->minute = bin2bcd(time.tm_min);
+	event->hour   = bin2bcd(time.tm_hour);
+	event->day    = bin2bcd(time.tm_mday);
+	event->month  = bin2bcd(time.tm_mon + 1);
+	event->year   = bin2bcd(time.tm_year % 100);
+}
+
+/*
+ * Fill out an event structure with space for the data and checksum.
+ */
+void elog_prepare_event(struct event_header *event, u8 event_type, void *data,
+			u8 data_size)
+{
+	event->type = event_type;
+	event->length = sizeof(*event) + data_size + 1;
+	elog_fill_timestamp(event);
+
+	if (data_size)
+		memcpy(&event[1], data, data_size);
+
+	/* Zero the checksum byte and then compute checksum */
+	elog_update_checksum(event, 0);
+	elog_update_checksum(event, -(elog_checksum_event(event)));
+}
+
+static int chromeos_arm_elog_panic(struct notifier_block *this,
+				   unsigned long p_event, void *ptr)
+{
+	struct chromeos_arm_elog_panic_buffer *buf;
+	uint32_t reason = ELOG_SHUTDOWN_PANIC;
+	const u8 data_size = sizeof(reason);
+	union {
+		struct event_header hdr;
+		u8 bytes[sizeof(struct event_header) + data_size + 1];
+	} event;
+
+	buf = container_of(this, struct chromeos_arm_elog_panic_buffer, nb);
+	elog_prepare_event(&event.hdr, ELOG_TYPE_OS_EVENT, &reason, data_size);
+	memcpy_toio(buf->virt_addr, event.bytes, sizeof(event.bytes));
+
+	return NOTIFY_DONE;
+}
+
+static int chromeos_arm_panic_init(struct platform_device *pdev, u32 start,
+				   u32 size)
+{
+	int ret = -EINVAL;
+	struct chromeos_arm_elog_panic_buffer *buf;
+
+	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf) {
+		dev_err(&pdev->dev, "failed to allocate panic notifier.\n");
+		ret = -ENOMEM;
+		goto fail1;
+	}
+
+	buf->start = start;
+	buf->size = size;
+	buf->nb.notifier_call = chromeos_arm_elog_panic;
+
+	if (!request_mem_region(start, size, "elog panic event")) {
+		dev_err(&pdev->dev, "failed to request panic event buffer.\n");
+		goto fail2;
+	}
+
+	buf->virt_addr = ioremap(start, size);
+	if (!buf->virt_addr) {
+		dev_err(&pdev->dev, "failed to map panic event buffer.\n");
+		goto fail3;
+	}
+
+	atomic_notifier_chain_register(&panic_notifier_list, &buf->nb);
+
+	platform_set_drvdata(pdev, buf);
+
+	return 0;
+
+fail3:
+	release_mem_region(start, size);
+fail2:
+	kfree(buf);
+fail1:
+	return ret;
+}
+
+static int dt_gpio_init(struct platform_device *pdev, const char *of_list_name,
+			const char *gpio_desc_name, const char *sysfs_name)
+{
+	int gpio, err, active_low;
+	enum of_gpio_flags flags;
+	struct device_node *np = pdev->dev.of_node;
+
+	gpio = of_get_named_gpio_flags(np, of_list_name, 0, &flags);
+	if (!gpio_is_valid(gpio)) {
+		dev_err(&pdev->dev, "invalid %s descriptor\n", of_list_name);
+		return -EINVAL;
+	}
+
+	err = gpio_request_one(gpio, GPIOF_DIR_IN, gpio_desc_name);
+	if (err)
+		return err;
+
+	active_low = !!(flags & OF_GPIO_ACTIVE_LOW);
+//	err = gpio_sysfs_set_active_low(gpio, active_low);
+//	if (err)
+//		return err;
+
+	gpio_export(gpio, 0);
+	gpio_export_link(&pdev->dev, sysfs_name, gpio);
+	return 0;
+}
+
+static int chromeos_arm_probe(struct platform_device *pdev)
+{
+	int err;
+	u32 elog_panic_event[2];
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!np) {
+		err = -ENODEV;
+		goto err;
+	}
+
+	err = dt_gpio_init(pdev, "write-protect-gpio",
+			   "firmware-write-protect", "write-protect");
+	if (err)
+		goto err;
+	err = dt_gpio_init(pdev, "recovery-switch",
+			   "firmware-recovery-switch", "recovery-switch");
+	err = dt_gpio_init(pdev, "developer-switch",
+			   "firmware-developer-switch", "developer-switch");
+
+	if (!of_property_read_u32_array(np, "elog-panic-event",
+					elog_panic_event,
+					ARRAY_SIZE(elog_panic_event))) {
+		err = chromeos_arm_panic_init(pdev, elog_panic_event[0],
+					      elog_panic_event[1]);
+		if (err)
+			goto err;
+	}
+
+	dev_info(&pdev->dev, "chromeos system detected\n");
+
+	err = 0;
+err:
+	of_node_put(np);
+
+	return err;
+}
+
+static int chromeos_arm_remove(struct platform_device *pdev)
+{
+	struct chromeos_arm_elog_panic_buffer *buf;
+
+	buf = platform_get_drvdata(pdev);
+	platform_set_drvdata(pdev, NULL);
+	if (buf) {
+		atomic_notifier_chain_unregister(&panic_notifier_list,
+						 &buf->nb);
+		release_mem_region(buf->start, buf->size);
+		iounmap(buf->virt_addr);
+		kfree(buf);
+	}
+	return 0;
+}
+
+static struct platform_driver chromeos_arm_driver = {
+	.probe = chromeos_arm_probe,
+	.remove = chromeos_arm_remove,
+	.driver = {
+		.name = "chromeos_arm",
+	},
+};
+
+static int __init chromeos_arm_init(void)
+{
+	struct device_node *fw_dn;
+	struct platform_device *pdev;
+
+	fw_dn = of_find_compatible_node(NULL, NULL, "chromeos-firmware");
+	if (!fw_dn)
+		return -ENODEV;
+
+	pdev = platform_device_register_simple("chromeos_arm", -1, NULL, 0);
+	pdev->dev.of_node = fw_dn;
+
+	platform_driver_register(&chromeos_arm_driver);
+
+	return 0;
+}
+subsys_initcall(chromeos_arm_init);
diff --git a/drivers/platform/chrome/elog.h b/drivers/platform/chrome/elog.h
new file mode 100644
index 0000000..84b005f
--- /dev/null
+++ b/drivers/platform/chrome/elog.h
@@ -0,0 +1,186 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 The ChromiumOS Authors.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#ifndef ELOG_H_
+#define ELOG_H_
+
+/* SMI command code for GSMI event logging */
+#define ELOG_GSMI_APM_CNT                 0xEF
+
+#define MAX_EVENT_SIZE                    0x7F
+
+/* End of log */
+#define ELOG_TYPE_EOL                     0xFF
+
+/*
+ * Standard SMBIOS event log types below 0x80
+ */
+#define ELOG_TYPE_UNDEFINED_EVENT         0x00
+#define ELOG_TYPE_SINGLE_BIT_ECC_MEM_ERR  0x01
+#define ELOG_TYPE_MULTI_BIT_ECC_MEM_ERR   0x02
+#define ELOG_TYPE_MEM_PARITY_ERR          0x03
+#define ELOG_TYPE_BUS_TIMEOUT             0x04
+#define ELOG_TYPE_IO_CHECK                0x05
+#define ELOG_TYPE_SW_NMI                  0x06
+#define ELOG_TYPE_POST_MEM_RESIZE         0x07
+#define ELOG_TYPE_POST_ERR                0x08
+#define ELOG_TYPE_PCI_PERR                0x09
+#define ELOG_TYPE_PCI_SERR                0x0A
+#define ELOG_TYPE_CPU_FAIL                0x0B
+#define ELOG_TYPE_EISA_TIMEOUT            0x0C
+#define ELOG_TYPE_CORRECTABLE_MEMLOG_DIS  0x0D
+#define ELOG_TYPE_LOG_DISABLED            0x0E
+#define ELOG_TYPE_UNDEFINED_EVENT2        0x0F
+#define ELOG_TYPE_SYS_LIMIT_EXCEED        0x10
+#define ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED  0x11
+#define ELOG_TYPE_SYS_CONFIG_INFO         0x12
+#define ELOG_TYPE_HDD_INFO                0x13
+#define ELOG_TYPE_SYS_RECONFIG            0x14
+#define ELOG_TYPE_CPU_ERROR               0x15
+#define ELOG_TYPE_LOG_CLEAR               0x16
+#define ELOG_TYPE_BOOT                    0x17
+
+/*
+ * Extended defined OEM event types start at 0x80
+ */
+
+/* OS/kernel events */
+#define ELOG_TYPE_OS_EVENT                0x81
+#define  ELOG_SHUTDOWN_CLEAN              0    /* Clean Shutdown */
+#define  ELOG_SHUTDOWN_NMIWDT             1    /* NMI Watchdog */
+#define  ELOG_SHUTDOWN_PANIC              2    /* Panic */
+#define  ELOG_SHUTDOWN_OOPS               3    /* Oops */
+#define  ELOG_SHUTDOWN_DIE                4    /* Die - No longer meaningful */
+#define  ELOG_SHUTDOWN_MCE                5    /* Machine Check */
+#define  ELOG_SHUTDOWN_SOFTWDT            6    /* Software Watchdog */
+#define  ELOG_SHUTDOWN_MBE                7    /* Uncorrected ECC */
+#define  ELOG_SHUTDOWN_TRIPLE             8    /* Triple Fault */
+#define  ELOG_SHUTDOWN_THERMAL            9    /* Critical Thermal Threshold */
+
+/* Last event from coreboot */
+#define ELOG_TYPE_OS_BOOT                 0x90
+
+/* Embedded controller event */
+#define ELOG_TYPE_EC_EVENT                0x91
+#define EC_EVENT_LID_CLOSED                0x01
+#define EC_EVENT_LID_OPEN                  0x02
+#define EC_EVENT_POWER_BUTTON              0x03
+#define EC_EVENT_AC_CONNECTED              0x04
+#define EC_EVENT_AC_DISCONNECTED           0x05
+#define EC_EVENT_BATTERY_LOW               0x06
+#define EC_EVENT_BATTERY_CRITICAL          0x07
+#define EC_EVENT_BATTERY                   0x08
+#define EC_EVENT_THERMAL_THRESHOLD         0x09
+#define EC_EVENT_THERMAL_OVERLOAD          0x0a
+#define EC_EVENT_THERMAL                   0x0b
+#define EC_EVENT_USB_CHARGER               0x0c
+#define EC_EVENT_KEY_PRESSED               0x0d
+#define EC_EVENT_INTERFACE_READY           0x0e
+#define EC_EVENT_KEYBOARD_RECOVERY         0x0f
+#define EC_EVENT_THERMAL_SHUTDOWN          0x10
+#define EC_EVENT_BATTERY_SHUTDOWN          0x11
+#define EC_EVENT_FAN_ERROR                 0x12
+
+/* Power */
+#define ELOG_TYPE_POWER_FAIL              0x92
+#define ELOG_TYPE_SUS_POWER_FAIL          0x93
+#define ELOG_TYPE_PWROK_FAIL              0x94
+#define ELOG_TYPE_SYS_PWROK_FAIL          0x95
+#define ELOG_TYPE_POWER_ON                0x96
+#define ELOG_TYPE_POWER_BUTTON            0x97
+#define ELOG_TYPE_POWER_BUTTON_OVERRIDE   0x98
+
+/* Reset */
+#define ELOG_TYPE_RESET_BUTTON            0x99
+#define ELOG_TYPE_SYSTEM_RESET            0x9a
+#define ELOG_TYPE_RTC_RESET               0x9b
+#define ELOG_TYPE_TCO_RESET               0x9c
+
+/* Sleep/Wake */
+#define ELOG_TYPE_ACPI_ENTER              0x9d
+#define ELOG_TYPE_ACPI_WAKE               0x9e
+#define ELOG_TYPE_WAKE_SOURCE             0x9f
+#define  ELOG_WAKE_SOURCE_PCIE             0x00
+#define  ELOG_WAKE_SOURCE_PME              0x01
+#define  ELOG_WAKE_SOURCE_PME_INTERNAL     0x02
+#define  ELOG_WAKE_SOURCE_RTC              0x03
+#define  ELOG_WAKE_SOURCE_GPIO             0x04
+#define  ELOG_WAKE_SOURCE_SMBUS            0x05
+#define  ELOG_WAKE_SOURCE_PWRBTN           0x06
+struct elog_event_data_wake {
+	u8 source;
+	u32 instance;
+} __packed;
+
+/* Chrome OS related events */
+#define ELOG_TYPE_CROS_DEVELOPER_MODE     0xa0
+#define ELOG_TYPE_CROS_RECOVERY_MODE      0xa1
+#define  ELOG_CROS_RECOVERY_MODE_BUTTON    0x02
+
+/* Management Engine Events */
+#define ELOG_TYPE_MANAGEMENT_ENGINE       0xa2
+#define ELOG_TYPE_MANAGEMENT_ENGINE_EXT   0xa4
+struct elog_event_data_me_extended {
+	u8 current_working_state;
+	u8 operation_state;
+	u8 operation_mode;
+	u8 error_code;
+	u8 progress_code;
+	u8 current_pmevent;
+	u8 current_state;
+} __packed;
+
+/* Last post code from previous boot */
+#define ELOG_TYPE_LAST_POST_CODE          0xa3
+
+/* EC Shutdown Reason */
+#define ELOG_TYPE_EC_SHUTDOWN             0xa5
+
+/* ARM/generic versions of sleep/wake */
+#define ELOG_TYPE_SLEEP                   0xa7
+#define ELOG_TYPE_WAKE                    0xa8
+
+/* ELOG header */
+struct elog_header {
+	u32 magic;
+	u8 version;
+	u8 header_size;
+	u8 reserved[2];
+} __packed;
+
+/* ELOG related constants */
+#define ELOG_SIGNATURE			0x474f4c45  /* 'ELOG' */
+#define ELOG_VERSION			1
+
+/* SMBIOS event log header */
+struct event_header {
+	u8 type;
+	u8 length;
+	u8 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 minute;
+	u8 second;
+} __packed;
+
+extern void elog_prepare_event(struct event_header *event, u8 event_type,
+			       void *data, u8 data_size);
+
+#endif /* ELOG_H_ */
diff --git a/include/linux/chromeos_platform.h b/include/linux/chromeos_platform.h
new file mode 100644
index 0000000..32c4510
--- /dev/null
+++ b/include/linux/chromeos_platform.h
@@ -0,0 +1,27 @@ 
+#ifndef _LINUX_CHROMEOS_PLATFORM_H
+#define _LINUX_CHROMEOS_PLATFORM_H
+
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_CHROMEOS
+/*
+ * ChromeOS platform support code. Glue layer between higher level functions
+ * and per-platform firmware interfaces.
+ */
+
+/*
+ * Set the taint bit telling firmware that the currently running side needs
+ * recovery (or reinstall).
+ */
+extern int chromeos_set_need_recovery(void);
+
+#else
+
+static inline int chromeos_set_need_recovery(void)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_CHROMEOS */
+
+#endif /* _LINUX_CHROMEOS_PLATFORM_H */