Commit 7918cfc4 authored by Julius Werner's avatar Julius Werner Committed by Greg Kroah-Hartman

firmware: google: memconsole: Make memconsole interface more flexible

This patch redesigns the interface between the generic memconsole driver
and its implementations to become more flexible than a flat memory
buffer with unchanging bounds. This allows memconsoles like coreboot's
to include lines that were added by runtime firmware after the driver
was initialized. Since the console log size is thus no longer static,
this means that the /sys/firmware/log file has to become unseekable.
Signed-off-by: default avatarJulius Werner <jwerner@chromium.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent acec09e6
...@@ -33,6 +33,14 @@ struct cbmem_cons { ...@@ -33,6 +33,14 @@ struct cbmem_cons {
static struct cbmem_cons __iomem *cbmem_console; static struct cbmem_cons __iomem *cbmem_console;
static ssize_t memconsole_coreboot_read(char *buf, loff_t pos, size_t count)
{
return memory_read_from_buffer(buf, count, &pos,
cbmem_console->buffer_body,
min(cbmem_console->buffer_cursor,
cbmem_console->buffer_size));
}
static int memconsole_coreboot_init(phys_addr_t physaddr) static int memconsole_coreboot_init(phys_addr_t physaddr)
{ {
struct cbmem_cons __iomem *tmp_cbmc; struct cbmem_cons __iomem *tmp_cbmc;
...@@ -50,9 +58,7 @@ static int memconsole_coreboot_init(phys_addr_t physaddr) ...@@ -50,9 +58,7 @@ static int memconsole_coreboot_init(phys_addr_t physaddr)
if (!cbmem_console) if (!cbmem_console)
return -ENOMEM; return -ENOMEM;
memconsole_setup(cbmem_console->buffer_body, memconsole_setup(memconsole_coreboot_read);
min(cbmem_console->buffer_cursor, cbmem_console->buffer_size));
return 0; return 0;
} }
......
...@@ -48,6 +48,15 @@ struct biosmemcon_ebda { ...@@ -48,6 +48,15 @@ struct biosmemcon_ebda {
}; };
} __packed; } __packed;
static char *memconsole_baseaddr;
static size_t memconsole_length;
static ssize_t memconsole_read(char *buf, loff_t pos, size_t count)
{
return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
memconsole_length);
}
static void found_v1_header(struct biosmemcon_ebda *hdr) static void found_v1_header(struct biosmemcon_ebda *hdr)
{ {
pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n", pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
...@@ -56,7 +65,9 @@ static void found_v1_header(struct biosmemcon_ebda *hdr) ...@@ -56,7 +65,9 @@ static void found_v1_header(struct biosmemcon_ebda *hdr)
hdr->v1.buffer_addr, hdr->v1.start, hdr->v1.buffer_addr, hdr->v1.start,
hdr->v1.end, hdr->v1.num_chars); hdr->v1.end, hdr->v1.num_chars);
memconsole_setup(phys_to_virt(hdr->v1.buffer_addr), hdr->v1.num_chars); memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
memconsole_length = hdr->v1.num_chars;
memconsole_setup(memconsole_read);
} }
static void found_v2_header(struct biosmemcon_ebda *hdr) static void found_v2_header(struct biosmemcon_ebda *hdr)
...@@ -67,8 +78,9 @@ static void found_v2_header(struct biosmemcon_ebda *hdr) ...@@ -67,8 +78,9 @@ static void found_v2_header(struct biosmemcon_ebda *hdr)
hdr->v2.buffer_addr, hdr->v2.start, hdr->v2.buffer_addr, hdr->v2.start,
hdr->v2.end, hdr->v2.num_bytes); hdr->v2.end, hdr->v2.num_bytes);
memconsole_setup(phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start), memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr + hdr->v2.start);
hdr->v2.end - hdr->v2.start); memconsole_length = hdr->v2.end - hdr->v2.start;
memconsole_setup(memconsole_read);
} }
/* /*
......
...@@ -22,15 +22,15 @@ ...@@ -22,15 +22,15 @@
#include "memconsole.h" #include "memconsole.h"
static char *memconsole_baseaddr; static ssize_t (*memconsole_read_func)(char *, loff_t, size_t);
static size_t memconsole_length;
static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
struct bin_attribute *bin_attr, char *buf, struct bin_attribute *bin_attr, char *buf,
loff_t pos, size_t count) loff_t pos, size_t count)
{ {
return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr, if (WARN_ON_ONCE(!memconsole_read_func))
memconsole_length); return -EIO;
return memconsole_read_func(buf, pos, count);
} }
static struct bin_attribute memconsole_bin_attr = { static struct bin_attribute memconsole_bin_attr = {
...@@ -38,16 +38,14 @@ static struct bin_attribute memconsole_bin_attr = { ...@@ -38,16 +38,14 @@ static struct bin_attribute memconsole_bin_attr = {
.read = memconsole_read, .read = memconsole_read,
}; };
void memconsole_setup(void *baseaddr, size_t length) void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t))
{ {
memconsole_baseaddr = baseaddr; memconsole_read_func = read_func;
memconsole_length = length;
} }
EXPORT_SYMBOL(memconsole_setup); EXPORT_SYMBOL(memconsole_setup);
int memconsole_sysfs_init(void) int memconsole_sysfs_init(void)
{ {
memconsole_bin_attr.size = memconsole_length;
return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr); return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
} }
EXPORT_SYMBOL(memconsole_sysfs_init); EXPORT_SYMBOL(memconsole_sysfs_init);
......
...@@ -18,13 +18,14 @@ ...@@ -18,13 +18,14 @@
#ifndef __FIRMWARE_GOOGLE_MEMCONSOLE_H #ifndef __FIRMWARE_GOOGLE_MEMCONSOLE_H
#define __FIRMWARE_GOOGLE_MEMCONSOLE_H #define __FIRMWARE_GOOGLE_MEMCONSOLE_H
#include <linux/types.h>
/* /*
* memconsole_setup * memconsole_setup
* *
* Initialize the memory console from raw (virtual) base * Initialize the memory console, passing the function to handle read accesses.
* address and length.
*/ */
void memconsole_setup(void *baseaddr, size_t length); void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t));
/* /*
* memconsole_sysfs_init * memconsole_sysfs_init
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment