summaryrefslogtreecommitdiffstats
path: root/drivers/firmware/google
diff options
context:
space:
mode:
authorMichel Lespinasse <walken@google.com>2014-01-28 08:06:22 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-02-15 14:30:28 -0500
commitcb88759107292b4bf36d13c73129add580d4e26e (patch)
tree5dfc70e1d1692a705fc35acb48af63c06c6a9867 /drivers/firmware/google
parentb12b73f1ca7763a94e0949a0d86eea40b5f69ea6 (diff)
firmware: google memconsole driver fixes
The google memconsole driver is currently broken upstream, as it tries to read memory that is described as reserved in /proc/iomem, by dereferencing a pointer obtained through phys_to_virt(). This triggers a kernel fault as such regions are unmapped after early boot. The proper workaround is to use ioremap_cache() / iounmap() around such accesses. As some unrelated changes, I also converted some printks to use pr_info() and added some missing __init annotations. Tested: booted dbg build, verified I could read /sys/firmware/log Signed-off-by: Michel Lespinasse <walken@google.com> Acked-by: Mike Waychison <mikew@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/firmware/google')
-rw-r--r--drivers/firmware/google/memconsole.c47
1 files changed, 26 insertions, 21 deletions
diff --git a/drivers/firmware/google/memconsole.c b/drivers/firmware/google/memconsole.c
index 2a90ba613613..2f569aaed4c7 100644
--- a/drivers/firmware/google/memconsole.c
+++ b/drivers/firmware/google/memconsole.c
@@ -15,6 +15,7 @@
15#include <linux/kobject.h> 15#include <linux/kobject.h>
16#include <linux/module.h> 16#include <linux/module.h>
17#include <linux/dmi.h> 17#include <linux/dmi.h>
18#include <linux/io.h>
18#include <asm/bios_ebda.h> 19#include <asm/bios_ebda.h>
19 20
20#define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE 21#define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE
@@ -41,15 +42,25 @@ struct biosmemcon_ebda {
41 }; 42 };
42} __packed; 43} __packed;
43 44
44static char *memconsole_baseaddr; 45static u32 memconsole_baseaddr;
45static size_t memconsole_length; 46static size_t memconsole_length;
46 47
47static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, 48static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
48 struct bin_attribute *bin_attr, char *buf, 49 struct bin_attribute *bin_attr, char *buf,
49 loff_t pos, size_t count) 50 loff_t pos, size_t count)
50{ 51{
51 return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr, 52 char *memconsole;
52 memconsole_length); 53 ssize_t ret;
54
55 memconsole = ioremap_cache(memconsole_baseaddr, memconsole_length);
56 if (!memconsole) {
57 pr_err("memconsole: ioremap_cache failed\n");
58 return -ENOMEM;
59 }
60 ret = memory_read_from_buffer(buf, count, &pos, memconsole,
61 memconsole_length);
62 iounmap(memconsole);
63 return ret;
53} 64}
54 65
55static struct bin_attribute memconsole_bin_attr = { 66static struct bin_attribute memconsole_bin_attr = {
@@ -58,43 +69,42 @@ static struct bin_attribute memconsole_bin_attr = {
58}; 69};
59 70
60 71
61static void found_v1_header(struct biosmemcon_ebda *hdr) 72static void __init found_v1_header(struct biosmemcon_ebda *hdr)
62{ 73{
63 printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr); 74 pr_info("BIOS console v1 EBDA structure found at %p\n", hdr);
64 printk(KERN_INFO "BIOS console buffer at 0x%.8x, " 75 pr_info("BIOS console buffer at 0x%.8x, "
65 "start = %d, end = %d, num = %d\n", 76 "start = %d, end = %d, num = %d\n",
66 hdr->v1.buffer_addr, hdr->v1.start, 77 hdr->v1.buffer_addr, hdr->v1.start,
67 hdr->v1.end, hdr->v1.num_chars); 78 hdr->v1.end, hdr->v1.num_chars);
68 79
69 memconsole_length = hdr->v1.num_chars; 80 memconsole_length = hdr->v1.num_chars;
70 memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr); 81 memconsole_baseaddr = hdr->v1.buffer_addr;
71} 82}
72 83
73static void found_v2_header(struct biosmemcon_ebda *hdr) 84static void __init found_v2_header(struct biosmemcon_ebda *hdr)
74{ 85{
75 printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr); 86 pr_info("BIOS console v2 EBDA structure found at %p\n", hdr);
76 printk(KERN_INFO "BIOS console buffer at 0x%.8x, " 87 pr_info("BIOS console buffer at 0x%.8x, "
77 "start = %d, end = %d, num_bytes = %d\n", 88 "start = %d, end = %d, num_bytes = %d\n",
78 hdr->v2.buffer_addr, hdr->v2.start, 89 hdr->v2.buffer_addr, hdr->v2.start,
79 hdr->v2.end, hdr->v2.num_bytes); 90 hdr->v2.end, hdr->v2.num_bytes);
80 91
81 memconsole_length = hdr->v2.end - hdr->v2.start; 92 memconsole_length = hdr->v2.end - hdr->v2.start;
82 memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr 93 memconsole_baseaddr = hdr->v2.buffer_addr + hdr->v2.start;
83 + hdr->v2.start);
84} 94}
85 95
86/* 96/*
87 * Search through the EBDA for the BIOS Memory Console, and 97 * Search through the EBDA for the BIOS Memory Console, and
88 * set the global variables to point to it. Return true if found. 98 * set the global variables to point to it. Return true if found.
89 */ 99 */
90static bool found_memconsole(void) 100static bool __init found_memconsole(void)
91{ 101{
92 unsigned int address; 102 unsigned int address;
93 size_t length, cur; 103 size_t length, cur;
94 104
95 address = get_bios_ebda(); 105 address = get_bios_ebda();
96 if (!address) { 106 if (!address) {
97 printk(KERN_INFO "BIOS EBDA non-existent.\n"); 107 pr_info("BIOS EBDA non-existent.\n");
98 return false; 108 return false;
99 } 109 }
100 110
@@ -122,7 +132,7 @@ static bool found_memconsole(void)
122 } 132 }
123 } 133 }
124 134
125 printk(KERN_INFO "BIOS console EBDA structure not found!\n"); 135 pr_info("BIOS console EBDA structure not found!\n");
126 return false; 136 return false;
127} 137}
128 138
@@ -139,8 +149,6 @@ MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
139 149
140static int __init memconsole_init(void) 150static int __init memconsole_init(void)
141{ 151{
142 int ret;
143
144 if (!dmi_check_system(memconsole_dmi_table)) 152 if (!dmi_check_system(memconsole_dmi_table))
145 return -ENODEV; 153 return -ENODEV;
146 154
@@ -148,10 +156,7 @@ static int __init memconsole_init(void)
148 return -ENODEV; 156 return -ENODEV;
149 157
150 memconsole_bin_attr.size = memconsole_length; 158 memconsole_bin_attr.size = memconsole_length;
151 159 return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
152 ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
153
154 return ret;
155} 160}
156 161
157static void __exit memconsole_exit(void) 162static void __exit memconsole_exit(void)