From: Mike Waychison <mikew@google.com>
To: Greg KH <greg@kroah.com>, Matt Domsch <Matt_Domsch@dell.com>,
Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Duncan Laurie <dlaurie@google.com>,
Aaron Durbin <adurbin@google.com>,
x86@kernel.org, linux-kernel@vger.kernel.org,
Tim Hockin <thockin@google.com>, San Mehat <san@google.com>
Subject: [PATCH v2 12/12] driver: Google Memory Console
Date: Fri, 11 Mar 2011 17:43:58 -0800 [thread overview]
Message-ID: <20110312014358.6133.34911.stgit@mike.mtv.corp.google.com> (raw)
In-Reply-To: <20110312014254.6133.43079.stgit@mike.mtv.corp.google.com>
This patch introduces the 'memconsole' driver.
Our firmware gives us access to an in-memory log of the firmware's
output. This gives us visibility in a data-center of headless machines
as to what the firmware is doing.
The memory console is found by the driver by finding a header block in
the EBDA. The buffer is then copied out, and is exported to userland in
the file /sys/firmware/log.
Signed-off-by: San Mehat <san@google.com>
Signed-off-by: Mike Waychison <mikew@google.com>
---
Changelog:
v2:
- Removed bits that had this driver muck with the kernel's ring
dmesg buffer (log_buf).
- Introduced the log as /sys/firmware/log, a binary file that isn't
interpreted by the kernel.
- Don't use C99 fixed width types; use kernel fixed width types.
- Added file to Documentation/ABI for /sys/firmware/log
---
Documentation/ABI/testing/sysfs-firmware-log | 7 +
drivers/firmware/google/Kconfig | 8 +
drivers/firmware/google/Makefile | 1
drivers/firmware/google/memconsole.c | 151 ++++++++++++++++++++++++++
4 files changed, 167 insertions(+), 0 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-firmware-log
create mode 100644 drivers/firmware/google/memconsole.c
diff --git a/Documentation/ABI/testing/sysfs-firmware-log b/Documentation/ABI/testing/sysfs-firmware-log
new file mode 100644
index 0000000..9b58e7c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-log
@@ -0,0 +1,7 @@
+What: /sys/firmware/log
+Date: February 2011
+Contact: Mike Waychison <mikew@google.com>
+Description:
+ The /sys/firmware/log is a binary file that represents a
+ read-only copy of the firmware's log if one is
+ available.
diff --git a/drivers/firmware/google/Kconfig b/drivers/firmware/google/Kconfig
index dfc3edc..5c3fc2e 100644
--- a/drivers/firmware/google/Kconfig
+++ b/drivers/firmware/google/Kconfig
@@ -22,4 +22,12 @@ config GOOGLE_SMI
clearing the EFI event log and reading and writing NVRAM
variables.
+config GOOGLE_MEMCONSOLE
+ tristate "Firmware Memory Console"
+ default y
+ help
+ This option enables the kernel to search for a firmware log in
+ the EBDA. If found, this log is prepended to the kernel's
+ dmesg logs so they are visible to the user.
+
endmenu
diff --git a/drivers/firmware/google/Makefile b/drivers/firmware/google/Makefile
index fb127d7..54a294e 100644
--- a/drivers/firmware/google/Makefile
+++ b/drivers/firmware/google/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_GOOGLE_SMI) += gsmi.o
+obj-$(CONFIG_GOOGLE_MEMCONSOLE) += memconsole.o
diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c
new file mode 100644
index 0000000..bef93dc
--- /dev/null
+++ b/drivers/firmware/google/memconsole.c
@@ -0,0 +1,151 @@
+/*
+ * memconsole.c
+ *
+ * Infrastructure for importing the BIOS memory based console
+ * into the kernel log ringbuffer.
+ *
+ * Copyright 2010 Google Inc. All rights reserved.
+ */
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <asm/bios_ebda.h>
+
+#define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE
+#define BIOS_MEMCONSOLE_V2_MAGIC (('M')|('C'<<8)|('O'<<16)|('N'<<24))
+
+struct biosmemcon_ebda {
+ u32 signature;
+ union {
+ struct {
+ u8 enabled;
+ u32 buffer_addr;
+ u16 start;
+ u16 end;
+ u16 num_chars;
+ u8 wrapped;
+ } __packed v1;
+ struct {
+ u32 buffer_addr;
+ /* Misdocumented as number of pages! */
+ u16 num_bytes;
+ u16 start;
+ u16 end;
+ } __packed v2;
+ };
+} __packed;
+
+static char *memconsole_baseaddr;
+static size_t memconsole_length;
+
+static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
+ struct bin_attribute *bin_attr, char *buf,
+ loff_t pos, size_t count)
+{
+ return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
+ memconsole_length);
+}
+
+static struct bin_attribute memconsole_bin_attr = {
+ .attr = {.name = "log", .mode = 0444},
+ .read = memconsole_read,
+};
+
+
+static void found_v1_header(struct biosmemcon_ebda *hdr)
+{
+ printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr);
+ printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
+ "start = %d, end = %d, num = %d\n",
+ hdr->v1.buffer_addr, hdr->v1.start,
+ hdr->v1.end, hdr->v1.num_chars);
+
+ memconsole_length = hdr->v1.num_chars;
+ memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
+}
+
+static void found_v2_header(struct biosmemcon_ebda *hdr)
+{
+ printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr);
+ printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
+ "start = %d, end = %d, num_bytes = %d\n",
+ hdr->v2.buffer_addr, hdr->v2.start,
+ hdr->v2.end, hdr->v2.num_bytes);
+
+ memconsole_length = hdr->v2.end - hdr->v2.start;
+ memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr
+ + hdr->v2.start);
+}
+
+/*
+ * Search through the EBDA for the BIOS Memory Console, and
+ * set the global variables to point to it. Return true if found.
+ */
+static bool found_memconsole(void)
+{
+ unsigned int address;
+ size_t length, cur;
+
+ address = get_bios_ebda();
+ if (!address) {
+ printk(KERN_INFO "BIOS EBDA non-existent.\n");
+ return false;
+ }
+
+ /* EBDA length is byte 0 of EBDA (in KB) */
+ length = *(u8 *)phys_to_virt(address);
+ length <<= 10; /* convert to bytes */
+
+ /*
+ * Search through EBDA for BIOS memory console structure
+ * note: signature is not necessarily dword-aligned
+ */
+ for (cur = 0; cur < length; cur++) {
+ struct biosmemcon_ebda *hdr = phys_to_virt(address + cur);
+
+ /* memconsole v1 */
+ if (hdr->signature == BIOS_MEMCONSOLE_V1_MAGIC) {
+ found_v1_header(hdr);
+ return true;
+ }
+
+ /* memconsole v2 */
+ if (hdr->signature == BIOS_MEMCONSOLE_V2_MAGIC) {
+ found_v2_header(hdr);
+ return true;
+ }
+ }
+
+ printk(KERN_INFO "BIOS console EBDA structure not found!\n");
+ return false;
+}
+
+static int __init memconsole_init(void)
+{
+ int ret;
+
+ if (!found_memconsole())
+ return -ENODEV;
+
+ memconsole_bin_attr.size = memconsole_length;
+
+ ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
+
+ return ret;
+}
+
+static void __exit memconsole_exit(void)
+{
+ sysfs_remove_bin_file(firmware_kobj, &memconsole_bin_attr);
+}
+
+module_init(memconsole_init);
+module_exit(memconsole_exit);
+
+MODULE_AUTHOR("Google, Inc.");
+MODULE_LICENSE("GPL");
next prev parent reply other threads:[~2011-03-12 1:44 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-12 1:42 [PATCH v2 00/12] google firmware support Mike Waychison
2011-03-12 1:43 ` [PATCH v2 01/12] efivars: move efivars globals into struct efivars Mike Waychison
2011-03-12 1:43 ` [PATCH v2 02/12] efivars: Make efivars bin_attributes dynamic Mike Waychison
2011-03-12 1:43 ` [PATCH v2 03/12] efivars: parameterize efivars Mike Waychison
2011-03-12 1:43 ` [PATCH v2 04/12] efivars: Split out variable registration Mike Waychison
2011-03-12 1:43 ` [PATCH v2 05/12] efivars: Parameterize operations Mike Waychison
2011-03-12 1:43 ` [PATCH v2 06/12] efivars: Expose efivars functionality to external drivers Mike Waychison
2011-03-12 1:43 ` [PATCH v2 07/12] efivars: Add Documentation Mike Waychison
2011-03-12 1:43 ` [PATCH v2 08/12] x86: get_bios_ebda_length() Mike Waychison
2011-03-14 15:43 ` Greg KH
2011-03-12 1:43 ` [PATCH v2 09/12] x86: Better comments for get_bios_ebda() Mike Waychison
2011-03-14 15:43 ` Greg KH
2011-03-12 1:43 ` [PATCH v2 10/12] Introduce CONFIG_GOOGLE_FIRMWARE Mike Waychison
2011-03-14 15:45 ` Greg KH
2011-03-14 19:49 ` Mike Waychison
2011-03-14 19:59 ` Greg KH
2011-03-14 20:06 ` Mike Waychison
2011-03-12 1:43 ` [PATCH v2 11/12] driver: Google EFI SMI Mike Waychison
2011-03-14 15:47 ` Greg KH
2011-03-14 20:01 ` Mike Waychison
2011-03-14 20:13 ` Greg KH
2011-03-14 21:09 ` Mike Waychison
2011-03-14 23:05 ` Alan Cox
2011-03-12 1:43 ` Mike Waychison [this message]
2011-03-14 4:54 ` [PATCH v2 12/12] driver: Google Memory Console H. Peter Anvin
2011-03-14 4:58 ` Tim Hockin
2011-03-14 5:02 ` H. Peter Anvin
2011-03-14 9:22 ` Ingo Molnar
2011-03-14 14:01 ` Tim Hockin
2011-03-14 14:23 ` Ingo Molnar
2011-03-14 15:47 ` Greg KH
2011-03-14 20:03 ` Mike Waychison
2011-03-14 22:46 ` H. Peter Anvin
2011-03-12 3:54 ` [PATCH v2 00/12] google firmware support Matt Domsch
2011-03-14 15:42 ` Greg KH
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110312014358.6133.34911.stgit@mike.mtv.corp.google.com \
--to=mikew@google.com \
--cc=Matt_Domsch@dell.com \
--cc=adurbin@google.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=dlaurie@google.com \
--cc=greg@kroah.com \
--cc=linux-kernel@vger.kernel.org \
--cc=san@google.com \
--cc=thockin@google.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome