diff options
author | Michel Lespinasse <walken@google.com> | 2014-01-28 08:06:22 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-15 14:30:28 -0500 |
commit | cb88759107292b4bf36d13c73129add580d4e26e (patch) | |
tree | 5dfc70e1d1692a705fc35acb48af63c06c6a9867 /drivers/firmware/google | |
parent | b12b73f1ca7763a94e0949a0d86eea40b5f69ea6 (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.c | 47 |
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 | ||
44 | static char *memconsole_baseaddr; | 45 | static u32 memconsole_baseaddr; |
45 | static size_t memconsole_length; | 46 | static size_t memconsole_length; |
46 | 47 | ||
47 | static ssize_t memconsole_read(struct file *filp, struct kobject *kobp, | 48 | static 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 | ||
55 | static struct bin_attribute memconsole_bin_attr = { | 66 | static struct bin_attribute memconsole_bin_attr = { |
@@ -58,43 +69,42 @@ static struct bin_attribute memconsole_bin_attr = { | |||
58 | }; | 69 | }; |
59 | 70 | ||
60 | 71 | ||
61 | static void found_v1_header(struct biosmemcon_ebda *hdr) | 72 | static 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 | ||
73 | static void found_v2_header(struct biosmemcon_ebda *hdr) | 84 | static 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 | */ |
90 | static bool found_memconsole(void) | 100 | static 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 | ||
140 | static int __init memconsole_init(void) | 150 | static 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 | ||
157 | static void __exit memconsole_exit(void) | 162 | static void __exit memconsole_exit(void) |