aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorLeif Lindholm <leif.lindholm@linaro.org>2013-09-05 06:34:54 -0400
committerMatt Fleming <matt.fleming@intel.com>2013-09-05 08:29:29 -0400
commit272686bf46a34f86d270cf192f68769667792026 (patch)
tree4a2ac56e098cc6477ad50839fd5db40719867bd0 /drivers/firmware
parentd02d0545f1fc62302fd9973a530b8029f1d9a9f1 (diff)
efi: x86: ia64: provide a generic efi_config_init()
Common to (U)EFI support on all platforms is the global "efi" data structure, and the code that parses the System Table to locate addresses to populate that structure with. This patch adds both of these to the global EFI driver code and removes the local definition of the global "efi" data structure from the x86 and ia64 code. Squashed into one big patch to avoid breaking bisection. Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> Acked-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/efi/efi.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5145fa344ad5..e1010d450b65 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -13,11 +13,27 @@
13 * This file is released under the GPLv2. 13 * This file is released under the GPLv2.
14 */ 14 */
15 15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
16#include <linux/kobject.h> 18#include <linux/kobject.h>
17#include <linux/module.h> 19#include <linux/module.h>
18#include <linux/init.h> 20#include <linux/init.h>
19#include <linux/device.h> 21#include <linux/device.h>
20#include <linux/efi.h> 22#include <linux/efi.h>
23#include <linux/io.h>
24
25struct efi __read_mostly efi = {
26 .mps = EFI_INVALID_TABLE_ADDR,
27 .acpi = EFI_INVALID_TABLE_ADDR,
28 .acpi20 = EFI_INVALID_TABLE_ADDR,
29 .smbios = EFI_INVALID_TABLE_ADDR,
30 .sal_systab = EFI_INVALID_TABLE_ADDR,
31 .boot_info = EFI_INVALID_TABLE_ADDR,
32 .hcdp = EFI_INVALID_TABLE_ADDR,
33 .uga = EFI_INVALID_TABLE_ADDR,
34 .uv_systab = EFI_INVALID_TABLE_ADDR,
35};
36EXPORT_SYMBOL(efi);
21 37
22static struct kobject *efi_kobj; 38static struct kobject *efi_kobj;
23static struct kobject *efivars_kobj; 39static struct kobject *efivars_kobj;
@@ -132,3 +148,95 @@ err_put:
132} 148}
133 149
134subsys_initcall(efisubsys_init); 150subsys_initcall(efisubsys_init);
151
152
153static __initdata efi_config_table_type_t common_tables[] = {
154 {ACPI_20_TABLE_GUID, "ACPI 2.0", &efi.acpi20},
155 {ACPI_TABLE_GUID, "ACPI", &efi.acpi},
156 {HCDP_TABLE_GUID, "HCDP", &efi.hcdp},
157 {MPS_TABLE_GUID, "MPS", &efi.mps},
158 {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab},
159 {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios},
160 {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga},
161 {NULL_GUID, NULL, 0},
162};
163
164static __init int match_config_table(efi_guid_t *guid,
165 unsigned long table,
166 efi_config_table_type_t *table_types)
167{
168 u8 str[EFI_VARIABLE_GUID_LEN + 1];
169 int i;
170
171 if (table_types) {
172 efi_guid_unparse(guid, str);
173
174 for (i = 0; efi_guidcmp(table_types[i].guid, NULL_GUID); i++) {
175 efi_guid_unparse(&table_types[i].guid, str);
176
177 if (!efi_guidcmp(*guid, table_types[i].guid)) {
178 *(table_types[i].ptr) = table;
179 pr_cont(" %s=0x%lx ",
180 table_types[i].name, table);
181 return 1;
182 }
183 }
184 }
185
186 return 0;
187}
188
189int __init efi_config_init(efi_config_table_type_t *arch_tables)
190{
191 void *config_tables, *tablep;
192 int i, sz;
193
194 if (efi_enabled(EFI_64BIT))
195 sz = sizeof(efi_config_table_64_t);
196 else
197 sz = sizeof(efi_config_table_32_t);
198
199 /*
200 * Let's see what config tables the firmware passed to us.
201 */
202 config_tables = early_memremap(efi.systab->tables,
203 efi.systab->nr_tables * sz);
204 if (config_tables == NULL) {
205 pr_err("Could not map Configuration table!\n");
206 return -ENOMEM;
207 }
208
209 tablep = config_tables;
210 pr_info("");
211 for (i = 0; i < efi.systab->nr_tables; i++) {
212 efi_guid_t guid;
213 unsigned long table;
214
215 if (efi_enabled(EFI_64BIT)) {
216 u64 table64;
217 guid = ((efi_config_table_64_t *)tablep)->guid;
218 table64 = ((efi_config_table_64_t *)tablep)->table;
219 table = table64;
220#ifndef CONFIG_64BIT
221 if (table64 >> 32) {
222 pr_cont("\n");
223 pr_err("Table located above 4GB, disabling EFI.\n");
224 early_iounmap(config_tables,
225 efi.systab->nr_tables * sz);
226 return -EINVAL;
227 }
228#endif
229 } else {
230 guid = ((efi_config_table_32_t *)tablep)->guid;
231 table = ((efi_config_table_32_t *)tablep)->table;
232 }
233
234 if (!match_config_table(&guid, table, common_tables))
235 match_config_table(&guid, table, arch_tables);
236
237 tablep += sz;
238 }
239 pr_cont("\n");
240 early_iounmap(config_tables, efi.systab->nr_tables * sz);
241 return 0;
242}