Commit 746942d06acdb4dd78d16baa5f3728a48a033bdd
Exists in
master
and in
4 other branches
Merge branch 'sfi-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6
* 'sfi-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6: SFI: remove unneeded includes sfi: Remove unused code SFI: Hook PCI MMCONFIG x86: add arch-specific SFI support SFI: add capability to parse ACPI tables SFI: add platform-independent core support SFI: create linux/sfi.h SFI: Simple Firmware Interface - MAINTAINERS, Kconfig
Showing 16 changed files Side-by-side Diff
- MAINTAINERS
- arch/x86/Kconfig
- arch/x86/kernel/Makefile
- arch/x86/kernel/setup.c
- arch/x86/kernel/sfi.c
- arch/x86/pci/mmconfig-shared.c
- arch/x86/pci/mmconfig_32.c
- drivers/Makefile
- drivers/sfi/Kconfig
- drivers/sfi/Makefile
- drivers/sfi/sfi_acpi.c
- drivers/sfi/sfi_core.c
- drivers/sfi/sfi_core.h
- include/linux/sfi.h
- include/linux/sfi_acpi.h
- init/main.c
MAINTAINERS
... | ... | @@ -4669,6 +4669,18 @@ |
4669 | 4669 | S: Supported |
4670 | 4670 | F: drivers/pci/hotplug/shpchp* |
4671 | 4671 | |
4672 | +SIMPLE FIRMWARE INTERFACE (SFI) | |
4673 | +P: Len Brown | |
4674 | +M: lenb@kernel.org | |
4675 | +L: sfi-devel@simplefirmware.org | |
4676 | +W: http://simplefirmware.org/ | |
4677 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git | |
4678 | +S: Supported | |
4679 | +F: arch/x86/kernel/*sfi* | |
4680 | +F: drivers/sfi/ | |
4681 | +F: include/linux/sfi*.h | |
4682 | + | |
4683 | + | |
4672 | 4684 | SIMTEC EB110ATX (Chalice CATS) |
4673 | 4685 | P: Ben Dooks |
4674 | 4686 | M: Vincent Sanders <support@simtec.co.uk> |
arch/x86/Kconfig
... | ... | @@ -1666,6 +1666,8 @@ |
1666 | 1666 | |
1667 | 1667 | source "drivers/acpi/Kconfig" |
1668 | 1668 | |
1669 | +source "drivers/sfi/Kconfig" | |
1670 | + | |
1669 | 1671 | config X86_APM_BOOT |
1670 | 1672 | bool |
1671 | 1673 | default y |
... | ... | @@ -1861,7 +1863,7 @@ |
1861 | 1863 | |
1862 | 1864 | config PCI_MMCONFIG |
1863 | 1865 | def_bool y |
1864 | - depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) | |
1866 | + depends on X86_32 && PCI && (ACPI || SFI) && (PCI_GOMMCONFIG || PCI_GOANY) | |
1865 | 1867 | |
1866 | 1868 | config PCI_OLPC |
1867 | 1869 | def_bool y |
arch/x86/kernel/Makefile
arch/x86/kernel/setup.c
... | ... | @@ -27,6 +27,7 @@ |
27 | 27 | #include <linux/screen_info.h> |
28 | 28 | #include <linux/ioport.h> |
29 | 29 | #include <linux/acpi.h> |
30 | +#include <linux/sfi.h> | |
30 | 31 | #include <linux/apm_bios.h> |
31 | 32 | #include <linux/initrd.h> |
32 | 33 | #include <linux/bootmem.h> |
... | ... | @@ -984,6 +985,8 @@ |
984 | 985 | * Read APIC and some other early information from ACPI tables. |
985 | 986 | */ |
986 | 987 | acpi_boot_init(); |
988 | + | |
989 | + sfi_init(); | |
987 | 990 | |
988 | 991 | /* |
989 | 992 | * get boot-time SMP configuration: |
arch/x86/kernel/sfi.c
1 | +/* | |
2 | + * sfi.c - x86 architecture SFI support. | |
3 | + * | |
4 | + * Copyright (c) 2009, Intel Corporation. | |
5 | + * | |
6 | + * This program is free software; you can redistribute it and/or modify it | |
7 | + * under the terms and conditions of the GNU General Public License, | |
8 | + * version 2, as published by the Free Software Foundation. | |
9 | + * | |
10 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
11 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | + * more details. | |
14 | + * | |
15 | + * You should have received a copy of the GNU General Public License along with | |
16 | + * this program; if not, write to the Free Software Foundation, Inc., | |
17 | + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | + * | |
19 | + */ | |
20 | + | |
21 | +#define KMSG_COMPONENT "SFI" | |
22 | +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
23 | + | |
24 | +#include <linux/acpi.h> | |
25 | +#include <linux/init.h> | |
26 | +#include <linux/sfi.h> | |
27 | +#include <linux/io.h> | |
28 | + | |
29 | +#include <asm/io_apic.h> | |
30 | +#include <asm/mpspec.h> | |
31 | +#include <asm/setup.h> | |
32 | +#include <asm/apic.h> | |
33 | + | |
34 | +#ifdef CONFIG_X86_LOCAL_APIC | |
35 | +static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; | |
36 | + | |
37 | +void __init mp_sfi_register_lapic_address(unsigned long address) | |
38 | +{ | |
39 | + mp_lapic_addr = address; | |
40 | + | |
41 | + set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); | |
42 | + if (boot_cpu_physical_apicid == -1U) | |
43 | + boot_cpu_physical_apicid = read_apic_id(); | |
44 | + | |
45 | + pr_info("Boot CPU = %d\n", boot_cpu_physical_apicid); | |
46 | +} | |
47 | + | |
48 | +/* All CPUs enumerated by SFI must be present and enabled */ | |
49 | +void __cpuinit mp_sfi_register_lapic(u8 id) | |
50 | +{ | |
51 | + if (MAX_APICS - id <= 0) { | |
52 | + pr_warning("Processor #%d invalid (max %d)\n", | |
53 | + id, MAX_APICS); | |
54 | + return; | |
55 | + } | |
56 | + | |
57 | + pr_info("registering lapic[%d]\n", id); | |
58 | + | |
59 | + generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR))); | |
60 | +} | |
61 | + | |
62 | +static int __init sfi_parse_cpus(struct sfi_table_header *table) | |
63 | +{ | |
64 | + struct sfi_table_simple *sb; | |
65 | + struct sfi_cpu_table_entry *pentry; | |
66 | + int i; | |
67 | + int cpu_num; | |
68 | + | |
69 | + sb = (struct sfi_table_simple *)table; | |
70 | + cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry); | |
71 | + pentry = (struct sfi_cpu_table_entry *)sb->pentry; | |
72 | + | |
73 | + for (i = 0; i < cpu_num; i++) { | |
74 | + mp_sfi_register_lapic(pentry->apic_id); | |
75 | + pentry++; | |
76 | + } | |
77 | + | |
78 | + smp_found_config = 1; | |
79 | + return 0; | |
80 | +} | |
81 | +#endif /* CONFIG_X86_LOCAL_APIC */ | |
82 | + | |
83 | +#ifdef CONFIG_X86_IO_APIC | |
84 | +static u32 gsi_base; | |
85 | + | |
86 | +static int __init sfi_parse_ioapic(struct sfi_table_header *table) | |
87 | +{ | |
88 | + struct sfi_table_simple *sb; | |
89 | + struct sfi_apic_table_entry *pentry; | |
90 | + int i, num; | |
91 | + | |
92 | + sb = (struct sfi_table_simple *)table; | |
93 | + num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry); | |
94 | + pentry = (struct sfi_apic_table_entry *)sb->pentry; | |
95 | + | |
96 | + for (i = 0; i < num; i++) { | |
97 | + mp_register_ioapic(i, pentry->phys_addr, gsi_base); | |
98 | + gsi_base += io_apic_get_redir_entries(i); | |
99 | + pentry++; | |
100 | + } | |
101 | + | |
102 | + WARN(pic_mode, KERN_WARNING | |
103 | + "SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n"); | |
104 | + pic_mode = 0; | |
105 | + return 0; | |
106 | +} | |
107 | +#endif /* CONFIG_X86_IO_APIC */ | |
108 | + | |
109 | +/* | |
110 | + * sfi_platform_init(): register lapics & io-apics | |
111 | + */ | |
112 | +int __init sfi_platform_init(void) | |
113 | +{ | |
114 | +#ifdef CONFIG_X86_LOCAL_APIC | |
115 | + mp_sfi_register_lapic_address(sfi_lapic_addr); | |
116 | + sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); | |
117 | +#endif | |
118 | +#ifdef CONFIG_X86_IO_APIC | |
119 | + sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic); | |
120 | +#endif | |
121 | + return 0; | |
122 | +} |
arch/x86/pci/mmconfig-shared.c
... | ... | @@ -13,10 +13,12 @@ |
13 | 13 | #include <linux/pci.h> |
14 | 14 | #include <linux/init.h> |
15 | 15 | #include <linux/acpi.h> |
16 | +#include <linux/sfi_acpi.h> | |
16 | 17 | #include <linux/bitmap.h> |
17 | 18 | #include <linux/sort.h> |
18 | 19 | #include <asm/e820.h> |
19 | 20 | #include <asm/pci_x86.h> |
21 | +#include <asm/acpi.h> | |
20 | 22 | |
21 | 23 | #define PREFIX "PCI: " |
22 | 24 | |
... | ... | @@ -493,7 +495,7 @@ |
493 | 495 | (unsigned int)cfg->start_bus_number, |
494 | 496 | (unsigned int)cfg->end_bus_number); |
495 | 497 | |
496 | - if (!early) | |
498 | + if (!early && !acpi_disabled) | |
497 | 499 | valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); |
498 | 500 | |
499 | 501 | if (valid) |
... | ... | @@ -608,7 +610,7 @@ |
608 | 610 | } |
609 | 611 | |
610 | 612 | if (!known_bridge) |
611 | - acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); | |
613 | + acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); | |
612 | 614 | |
613 | 615 | pci_mmcfg_reject_broken(early); |
614 | 616 |
arch/x86/pci/mmconfig_32.c
... | ... | @@ -11,9 +11,9 @@ |
11 | 11 | |
12 | 12 | #include <linux/pci.h> |
13 | 13 | #include <linux/init.h> |
14 | -#include <linux/acpi.h> | |
15 | 14 | #include <asm/e820.h> |
16 | 15 | #include <asm/pci_x86.h> |
16 | +#include <acpi/acpi.h> | |
17 | 17 | |
18 | 18 | /* Assume systems with more busses have correct MCFG */ |
19 | 19 | #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) |
drivers/Makefile
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | obj-$(CONFIG_RAPIDIO) += rapidio/ |
12 | 12 | obj-y += video/ |
13 | 13 | obj-$(CONFIG_ACPI) += acpi/ |
14 | +obj-$(CONFIG_SFI) += sfi/ | |
14 | 15 | # PnP must come after ACPI since it will eventually need to check if acpi |
15 | 16 | # was used and do nothing if so |
16 | 17 | obj-$(CONFIG_PNP) += pnp/ |
drivers/sfi/Kconfig
1 | +# | |
2 | +# SFI Configuration | |
3 | +# | |
4 | + | |
5 | +menuconfig SFI | |
6 | + bool "SFI (Simple Firmware Interface) Support" | |
7 | + ---help--- | |
8 | + The Simple Firmware Interface (SFI) provides a lightweight method | |
9 | + for platform firmware to pass information to the operating system | |
10 | + via static tables in memory. Kernel SFI support is required to | |
11 | + boot on SFI-only platforms. Currently, all SFI-only platforms are | |
12 | + based on the 2nd generation Intel Atom processor platform, | |
13 | + code-named Moorestown. | |
14 | + | |
15 | + For more information, see http://simplefirmware.org | |
16 | + | |
17 | + Say 'Y' here to enable the kernel to boot on SFI-only platforms. |
drivers/sfi/Makefile
drivers/sfi/sfi_acpi.c
1 | +/* sfi_acpi.c Simple Firmware Interface - ACPI extensions */ | |
2 | + | |
3 | +/* | |
4 | + | |
5 | + This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | + redistributing this file, you may do so under either license. | |
7 | + | |
8 | + GPL LICENSE SUMMARY | |
9 | + | |
10 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
11 | + | |
12 | + This program is free software; you can redistribute it and/or modify | |
13 | + it under the terms of version 2 of the GNU General Public License as | |
14 | + published by the Free Software Foundation. | |
15 | + | |
16 | + This program is distributed in the hope that it will be useful, but | |
17 | + WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | + General Public License for more details. | |
20 | + | |
21 | + You should have received a copy of the GNU General Public License | |
22 | + along with this program; if not, write to the Free Software | |
23 | + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | + The full GNU General Public License is included in this distribution | |
25 | + in the file called LICENSE.GPL. | |
26 | + | |
27 | + BSD LICENSE | |
28 | + | |
29 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
30 | + | |
31 | + Redistribution and use in source and binary forms, with or without | |
32 | + modification, are permitted provided that the following conditions | |
33 | + are met: | |
34 | + | |
35 | + * Redistributions of source code must retain the above copyright | |
36 | + notice, this list of conditions and the following disclaimer. | |
37 | + * Redistributions in binary form must reproduce the above copyright | |
38 | + notice, this list of conditions and the following disclaimer in | |
39 | + the documentation and/or other materials provided with the | |
40 | + distribution. | |
41 | + * Neither the name of Intel Corporation nor the names of its | |
42 | + contributors may be used to endorse or promote products derived | |
43 | + from this software without specific prior written permission. | |
44 | + | |
45 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
46 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
47 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
48 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
49 | + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
50 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
51 | + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
52 | + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
53 | + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
54 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
55 | + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
56 | + | |
57 | +*/ | |
58 | + | |
59 | +#define KMSG_COMPONENT "SFI" | |
60 | +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
61 | + | |
62 | +#include <linux/kernel.h> | |
63 | +#include <acpi/acpi.h> | |
64 | + | |
65 | +#include <linux/sfi.h> | |
66 | +#include "sfi_core.h" | |
67 | + | |
68 | +/* | |
69 | + * SFI can access ACPI-defined tables via an optional ACPI XSDT. | |
70 | + * | |
71 | + * This allows re-use, and avoids re-definition, of standard tables. | |
72 | + * For example, the "MCFG" table is defined by PCI, reserved by ACPI, | |
73 | + * and is expected to be present many SFI-only systems. | |
74 | + */ | |
75 | + | |
76 | +static struct acpi_table_xsdt *xsdt_va __read_mostly; | |
77 | + | |
78 | +#define XSDT_GET_NUM_ENTRIES(ptable, entry_type) \ | |
79 | + ((ptable->header.length - sizeof(struct acpi_table_header)) / \ | |
80 | + (sizeof(entry_type))) | |
81 | + | |
82 | +static inline struct sfi_table_header *acpi_to_sfi_th( | |
83 | + struct acpi_table_header *th) | |
84 | +{ | |
85 | + return (struct sfi_table_header *)th; | |
86 | +} | |
87 | + | |
88 | +static inline struct acpi_table_header *sfi_to_acpi_th( | |
89 | + struct sfi_table_header *th) | |
90 | +{ | |
91 | + return (struct acpi_table_header *)th; | |
92 | +} | |
93 | + | |
94 | +/* | |
95 | + * sfi_acpi_parse_xsdt() | |
96 | + * | |
97 | + * Parse the ACPI XSDT for later access by sfi_acpi_table_parse(). | |
98 | + */ | |
99 | +static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *th) | |
100 | +{ | |
101 | + struct sfi_table_key key = SFI_ANY_KEY; | |
102 | + int tbl_cnt, i; | |
103 | + void *ret; | |
104 | + | |
105 | + xsdt_va = (struct acpi_table_xsdt *)th; | |
106 | + tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); | |
107 | + for (i = 0; i < tbl_cnt; i++) { | |
108 | + ret = sfi_check_table(xsdt_va->table_offset_entry[i], &key); | |
109 | + if (IS_ERR(ret)) { | |
110 | + disable_sfi(); | |
111 | + return -1; | |
112 | + } | |
113 | + } | |
114 | + | |
115 | + return 0; | |
116 | +} | |
117 | + | |
118 | +int __init sfi_acpi_init(void) | |
119 | +{ | |
120 | + struct sfi_table_key xsdt_key = { .sig = SFI_SIG_XSDT }; | |
121 | + | |
122 | + sfi_table_parse(SFI_SIG_XSDT, NULL, NULL, sfi_acpi_parse_xsdt); | |
123 | + | |
124 | + /* Only call the get_table to keep the table mapped */ | |
125 | + xsdt_va = (struct acpi_table_xsdt *)sfi_get_table(&xsdt_key); | |
126 | + return 0; | |
127 | +} | |
128 | + | |
129 | +static struct acpi_table_header *sfi_acpi_get_table(struct sfi_table_key *key) | |
130 | +{ | |
131 | + u32 tbl_cnt, i; | |
132 | + void *ret; | |
133 | + | |
134 | + tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); | |
135 | + for (i = 0; i < tbl_cnt; i++) { | |
136 | + ret = sfi_check_table(xsdt_va->table_offset_entry[i], key); | |
137 | + if (!IS_ERR(ret) && ret) | |
138 | + return sfi_to_acpi_th(ret); | |
139 | + } | |
140 | + | |
141 | + return NULL; | |
142 | +} | |
143 | + | |
144 | +static void sfi_acpi_put_table(struct acpi_table_header *table) | |
145 | +{ | |
146 | + sfi_put_table(acpi_to_sfi_th(table)); | |
147 | +} | |
148 | + | |
149 | +/* | |
150 | + * sfi_acpi_table_parse() | |
151 | + * | |
152 | + * Find specified table in XSDT, run handler on it and return its return value | |
153 | + */ | |
154 | +int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, | |
155 | + int(*handler)(struct acpi_table_header *)) | |
156 | +{ | |
157 | + struct acpi_table_header *table = NULL; | |
158 | + struct sfi_table_key key; | |
159 | + int ret = 0; | |
160 | + | |
161 | + if (sfi_disabled) | |
162 | + return -1; | |
163 | + | |
164 | + key.sig = signature; | |
165 | + key.oem_id = oem_id; | |
166 | + key.oem_table_id = oem_table_id; | |
167 | + | |
168 | + table = sfi_acpi_get_table(&key); | |
169 | + if (!table) | |
170 | + return -EINVAL; | |
171 | + | |
172 | + ret = handler(table); | |
173 | + sfi_acpi_put_table(table); | |
174 | + return ret; | |
175 | +} |
drivers/sfi/sfi_core.c
1 | +/* sfi_core.c Simple Firmware Interface - core internals */ | |
2 | + | |
3 | +/* | |
4 | + | |
5 | + This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | + redistributing this file, you may do so under either license. | |
7 | + | |
8 | + GPL LICENSE SUMMARY | |
9 | + | |
10 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
11 | + | |
12 | + This program is free software; you can redistribute it and/or modify | |
13 | + it under the terms of version 2 of the GNU General Public License as | |
14 | + published by the Free Software Foundation. | |
15 | + | |
16 | + This program is distributed in the hope that it will be useful, but | |
17 | + WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | + General Public License for more details. | |
20 | + | |
21 | + You should have received a copy of the GNU General Public License | |
22 | + along with this program; if not, write to the Free Software | |
23 | + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | + The full GNU General Public License is included in this distribution | |
25 | + in the file called LICENSE.GPL. | |
26 | + | |
27 | + BSD LICENSE | |
28 | + | |
29 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
30 | + | |
31 | + Redistribution and use in source and binary forms, with or without | |
32 | + modification, are permitted provided that the following conditions | |
33 | + are met: | |
34 | + | |
35 | + * Redistributions of source code must retain the above copyright | |
36 | + notice, this list of conditions and the following disclaimer. | |
37 | + * Redistributions in binary form must reproduce the above copyright | |
38 | + notice, this list of conditions and the following disclaimer in | |
39 | + the documentation and/or other materials provided with the | |
40 | + distribution. | |
41 | + * Neither the name of Intel Corporation nor the names of its | |
42 | + contributors may be used to endorse or promote products derived | |
43 | + from this software without specific prior written permission. | |
44 | + | |
45 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
46 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
47 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
48 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
49 | + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
50 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
51 | + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
52 | + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
53 | + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
54 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
55 | + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
56 | + | |
57 | +*/ | |
58 | + | |
59 | +#define KMSG_COMPONENT "SFI" | |
60 | +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
61 | + | |
62 | +#include <linux/bootmem.h> | |
63 | +#include <linux/kernel.h> | |
64 | +#include <linux/module.h> | |
65 | +#include <linux/errno.h> | |
66 | +#include <linux/types.h> | |
67 | +#include <linux/acpi.h> | |
68 | +#include <linux/init.h> | |
69 | +#include <linux/sfi.h> | |
70 | + | |
71 | +#include "sfi_core.h" | |
72 | + | |
73 | +#define ON_SAME_PAGE(addr1, addr2) \ | |
74 | + (((unsigned long)(addr1) & PAGE_MASK) == \ | |
75 | + ((unsigned long)(addr2) & PAGE_MASK)) | |
76 | +#define TABLE_ON_PAGE(page, table, size) (ON_SAME_PAGE(page, table) && \ | |
77 | + ON_SAME_PAGE(page, table + size)) | |
78 | + | |
79 | +int sfi_disabled __read_mostly; | |
80 | +EXPORT_SYMBOL(sfi_disabled); | |
81 | + | |
82 | +static u64 syst_pa __read_mostly; | |
83 | +static struct sfi_table_simple *syst_va __read_mostly; | |
84 | + | |
85 | +/* | |
86 | + * FW creates and saves the SFI tables in memory. When these tables get | |
87 | + * used, they may need to be mapped to virtual address space, and the mapping | |
88 | + * can happen before or after the ioremap() is ready, so a flag is needed | |
89 | + * to indicating this | |
90 | + */ | |
91 | +static u32 sfi_use_ioremap __read_mostly; | |
92 | + | |
93 | +static void __iomem *sfi_map_memory(u64 phys, u32 size) | |
94 | +{ | |
95 | + if (!phys || !size) | |
96 | + return NULL; | |
97 | + | |
98 | + if (sfi_use_ioremap) | |
99 | + return ioremap(phys, size); | |
100 | + else | |
101 | + return early_ioremap(phys, size); | |
102 | +} | |
103 | + | |
104 | +static void sfi_unmap_memory(void __iomem *virt, u32 size) | |
105 | +{ | |
106 | + if (!virt || !size) | |
107 | + return; | |
108 | + | |
109 | + if (sfi_use_ioremap) | |
110 | + iounmap(virt); | |
111 | + else | |
112 | + early_iounmap(virt, size); | |
113 | +} | |
114 | + | |
115 | +static void sfi_print_table_header(unsigned long long pa, | |
116 | + struct sfi_table_header *header) | |
117 | +{ | |
118 | + pr_info("%4.4s %llX, %04X (v%d %6.6s %8.8s)\n", | |
119 | + header->sig, pa, | |
120 | + header->len, header->rev, header->oem_id, | |
121 | + header->oem_table_id); | |
122 | +} | |
123 | + | |
124 | +/* | |
125 | + * sfi_verify_table() | |
126 | + * Sanity check table lengh, calculate checksum | |
127 | + */ | |
128 | +static __init int sfi_verify_table(struct sfi_table_header *table) | |
129 | +{ | |
130 | + | |
131 | + u8 checksum = 0; | |
132 | + u8 *puchar = (u8 *)table; | |
133 | + u32 length = table->len; | |
134 | + | |
135 | + /* Sanity check table length against arbitrary 1MB limit */ | |
136 | + if (length > 0x100000) { | |
137 | + pr_err("Invalid table length 0x%x\n", length); | |
138 | + return -1; | |
139 | + } | |
140 | + | |
141 | + while (length--) | |
142 | + checksum += *puchar++; | |
143 | + | |
144 | + if (checksum) { | |
145 | + pr_err("Checksum %2.2X should be %2.2X\n", | |
146 | + table->csum, table->csum - checksum); | |
147 | + return -1; | |
148 | + } | |
149 | + return 0; | |
150 | +} | |
151 | + | |
152 | +/* | |
153 | + * sfi_map_table() | |
154 | + * | |
155 | + * Return address of mapped table | |
156 | + * Check for common case that we can re-use mapping to SYST, | |
157 | + * which requires syst_pa, syst_va to be initialized. | |
158 | + */ | |
159 | +struct sfi_table_header *sfi_map_table(u64 pa) | |
160 | +{ | |
161 | + struct sfi_table_header *th; | |
162 | + u32 length; | |
163 | + | |
164 | + if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) | |
165 | + th = sfi_map_memory(pa, sizeof(struct sfi_table_header)); | |
166 | + else | |
167 | + th = (void *)syst_va + (pa - syst_pa); | |
168 | + | |
169 | + /* If table fits on same page as its header, we are done */ | |
170 | + if (TABLE_ON_PAGE(th, th, th->len)) | |
171 | + return th; | |
172 | + | |
173 | + /* Entire table does not fit on same page as SYST */ | |
174 | + length = th->len; | |
175 | + if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) | |
176 | + sfi_unmap_memory(th, sizeof(struct sfi_table_header)); | |
177 | + | |
178 | + return sfi_map_memory(pa, length); | |
179 | +} | |
180 | + | |
181 | +/* | |
182 | + * sfi_unmap_table() | |
183 | + * | |
184 | + * Undoes effect of sfi_map_table() by unmapping table | |
185 | + * if it did not completely fit on same page as SYST. | |
186 | + */ | |
187 | +void sfi_unmap_table(struct sfi_table_header *th) | |
188 | +{ | |
189 | + if (!TABLE_ON_PAGE(syst_va, th, th->len)) | |
190 | + sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ? | |
191 | + sizeof(*th) : th->len); | |
192 | +} | |
193 | + | |
194 | +static int sfi_table_check_key(struct sfi_table_header *th, | |
195 | + struct sfi_table_key *key) | |
196 | +{ | |
197 | + | |
198 | + if (strncmp(th->sig, key->sig, SFI_SIGNATURE_SIZE) | |
199 | + || (key->oem_id && strncmp(th->oem_id, | |
200 | + key->oem_id, SFI_OEM_ID_SIZE)) | |
201 | + || (key->oem_table_id && strncmp(th->oem_table_id, | |
202 | + key->oem_table_id, SFI_OEM_TABLE_ID_SIZE))) | |
203 | + return -1; | |
204 | + | |
205 | + return 0; | |
206 | +} | |
207 | + | |
208 | +/* | |
209 | + * This function will be used in 2 cases: | |
210 | + * 1. used to enumerate and verify the tables addressed by SYST/XSDT, | |
211 | + * thus no signature will be given (in kernel boot phase) | |
212 | + * 2. used to parse one specific table, signature must exist, and | |
213 | + * the mapped virt address will be returned, and the virt space | |
214 | + * will be released by call sfi_put_table() later | |
215 | + * | |
216 | + * Return value: | |
217 | + * NULL: when can't find a table matching the key | |
218 | + * ERR_PTR(error): error value | |
219 | + * virt table address: when a matched table is found | |
220 | + */ | |
221 | +struct sfi_table_header *sfi_check_table(u64 pa, struct sfi_table_key *key) | |
222 | +{ | |
223 | + struct sfi_table_header *th; | |
224 | + void *ret = NULL; | |
225 | + | |
226 | + th = sfi_map_table(pa); | |
227 | + if (!th) | |
228 | + return ERR_PTR(-ENOMEM); | |
229 | + | |
230 | + if (!key->sig) { | |
231 | + sfi_print_table_header(pa, th); | |
232 | + if (sfi_verify_table(th)) | |
233 | + ret = ERR_PTR(-EINVAL); | |
234 | + } else { | |
235 | + if (!sfi_table_check_key(th, key)) | |
236 | + return th; /* Success */ | |
237 | + } | |
238 | + | |
239 | + sfi_unmap_table(th); | |
240 | + return ret; | |
241 | +} | |
242 | + | |
243 | +/* | |
244 | + * sfi_get_table() | |
245 | + * | |
246 | + * Search SYST for the specified table with the signature in | |
247 | + * the key, and return the mapped table | |
248 | + */ | |
249 | +struct sfi_table_header *sfi_get_table(struct sfi_table_key *key) | |
250 | +{ | |
251 | + struct sfi_table_header *th; | |
252 | + u32 tbl_cnt, i; | |
253 | + | |
254 | + tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); | |
255 | + for (i = 0; i < tbl_cnt; i++) { | |
256 | + th = sfi_check_table(syst_va->pentry[i], key); | |
257 | + if (!IS_ERR(th) && th) | |
258 | + return th; | |
259 | + } | |
260 | + | |
261 | + return NULL; | |
262 | +} | |
263 | + | |
264 | +void sfi_put_table(struct sfi_table_header *th) | |
265 | +{ | |
266 | + sfi_unmap_table(th); | |
267 | +} | |
268 | + | |
269 | +/* Find table with signature, run handler on it */ | |
270 | +int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, | |
271 | + sfi_table_handler handler) | |
272 | +{ | |
273 | + struct sfi_table_header *table = NULL; | |
274 | + struct sfi_table_key key; | |
275 | + int ret = -EINVAL; | |
276 | + | |
277 | + if (sfi_disabled || !handler || !signature) | |
278 | + goto exit; | |
279 | + | |
280 | + key.sig = signature; | |
281 | + key.oem_id = oem_id; | |
282 | + key.oem_table_id = oem_table_id; | |
283 | + | |
284 | + table = sfi_get_table(&key); | |
285 | + if (!table) | |
286 | + goto exit; | |
287 | + | |
288 | + ret = handler(table); | |
289 | + sfi_put_table(table); | |
290 | +exit: | |
291 | + return ret; | |
292 | +} | |
293 | +EXPORT_SYMBOL_GPL(sfi_table_parse); | |
294 | + | |
295 | +/* | |
296 | + * sfi_parse_syst() | |
297 | + * Checksum all the tables in SYST and print their headers | |
298 | + * | |
299 | + * success: set syst_va, return 0 | |
300 | + */ | |
301 | +static int __init sfi_parse_syst(void) | |
302 | +{ | |
303 | + struct sfi_table_key key = SFI_ANY_KEY; | |
304 | + int tbl_cnt, i; | |
305 | + void *ret; | |
306 | + | |
307 | + syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple)); | |
308 | + if (!syst_va) | |
309 | + return -ENOMEM; | |
310 | + | |
311 | + tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); | |
312 | + for (i = 0; i < tbl_cnt; i++) { | |
313 | + ret = sfi_check_table(syst_va->pentry[i], &key); | |
314 | + if (IS_ERR(ret)) | |
315 | + return PTR_ERR(ret); | |
316 | + } | |
317 | + | |
318 | + return 0; | |
319 | +} | |
320 | + | |
321 | +/* | |
322 | + * The OS finds the System Table by searching 16-byte boundaries between | |
323 | + * physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region | |
324 | + * starting at the low address and shall stop searching when the 1st valid SFI | |
325 | + * System Table is found. | |
326 | + * | |
327 | + * success: set syst_pa, return 0 | |
328 | + * fail: return -1 | |
329 | + */ | |
330 | +static __init int sfi_find_syst(void) | |
331 | +{ | |
332 | + unsigned long offset, len; | |
333 | + void *start; | |
334 | + | |
335 | + len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN; | |
336 | + start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len); | |
337 | + if (!start) | |
338 | + return -1; | |
339 | + | |
340 | + for (offset = 0; offset < len; offset += 16) { | |
341 | + struct sfi_table_header *syst_hdr; | |
342 | + | |
343 | + syst_hdr = start + offset; | |
344 | + if (strncmp(syst_hdr->sig, SFI_SIG_SYST, | |
345 | + SFI_SIGNATURE_SIZE)) | |
346 | + continue; | |
347 | + | |
348 | + if (syst_hdr->len > PAGE_SIZE) | |
349 | + continue; | |
350 | + | |
351 | + sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset, | |
352 | + syst_hdr); | |
353 | + | |
354 | + if (sfi_verify_table(syst_hdr)) | |
355 | + continue; | |
356 | + | |
357 | + /* | |
358 | + * Enforce SFI spec mandate that SYST reside within a page. | |
359 | + */ | |
360 | + if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) { | |
361 | + pr_info("SYST 0x%llx + 0x%x crosses page\n", | |
362 | + syst_pa, syst_hdr->len); | |
363 | + continue; | |
364 | + } | |
365 | + | |
366 | + /* Success */ | |
367 | + syst_pa = SFI_SYST_SEARCH_BEGIN + offset; | |
368 | + sfi_unmap_memory(start, len); | |
369 | + return 0; | |
370 | + } | |
371 | + | |
372 | + sfi_unmap_memory(start, len); | |
373 | + return -1; | |
374 | +} | |
375 | + | |
376 | +void __init sfi_init(void) | |
377 | +{ | |
378 | + if (!acpi_disabled) | |
379 | + disable_sfi(); | |
380 | + | |
381 | + if (sfi_disabled) | |
382 | + return; | |
383 | + | |
384 | + pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); | |
385 | + | |
386 | + if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) | |
387 | + disable_sfi(); | |
388 | + | |
389 | + return; | |
390 | +} | |
391 | + | |
392 | +void __init sfi_init_late(void) | |
393 | +{ | |
394 | + int length; | |
395 | + | |
396 | + if (sfi_disabled) | |
397 | + return; | |
398 | + | |
399 | + length = syst_va->header.len; | |
400 | + sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple)); | |
401 | + | |
402 | + /* Use ioremap now after it is ready */ | |
403 | + sfi_use_ioremap = 1; | |
404 | + syst_va = sfi_map_memory(syst_pa, length); | |
405 | + | |
406 | + sfi_acpi_init(); | |
407 | +} |
drivers/sfi/sfi_core.h
1 | +/* sfi_core.h Simple Firmware Interface, internal header */ | |
2 | + | |
3 | +/* | |
4 | + | |
5 | + This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | + redistributing this file, you may do so under either license. | |
7 | + | |
8 | + GPL LICENSE SUMMARY | |
9 | + | |
10 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
11 | + | |
12 | + This program is free software; you can redistribute it and/or modify | |
13 | + it under the terms of version 2 of the GNU General Public License as | |
14 | + published by the Free Software Foundation. | |
15 | + | |
16 | + This program is distributed in the hope that it will be useful, but | |
17 | + WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | + General Public License for more details. | |
20 | + | |
21 | + You should have received a copy of the GNU General Public License | |
22 | + along with this program; if not, write to the Free Software | |
23 | + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | + The full GNU General Public License is included in this distribution | |
25 | + in the file called LICENSE.GPL. | |
26 | + | |
27 | + BSD LICENSE | |
28 | + | |
29 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
30 | + | |
31 | + Redistribution and use in source and binary forms, with or without | |
32 | + modification, are permitted provided that the following conditions | |
33 | + are met: | |
34 | + | |
35 | + * Redistributions of source code must retain the above copyright | |
36 | + notice, this list of conditions and the following disclaimer. | |
37 | + * Redistributions in binary form must reproduce the above copyright | |
38 | + notice, this list of conditions and the following disclaimer in | |
39 | + the documentation and/or other materials provided with the | |
40 | + distribution. | |
41 | + * Neither the name of Intel Corporation nor the names of its | |
42 | + contributors may be used to endorse or promote products derived | |
43 | + from this software without specific prior written permission. | |
44 | + | |
45 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
46 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
47 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
48 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
49 | + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
50 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
51 | + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
52 | + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
53 | + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
54 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
55 | + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
56 | + | |
57 | +*/ | |
58 | +struct sfi_table_key{ | |
59 | + char *sig; | |
60 | + char *oem_id; | |
61 | + char *oem_table_id; | |
62 | +}; | |
63 | + | |
64 | +#define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } | |
65 | + | |
66 | +extern int __init sfi_acpi_init(void); | |
67 | +extern struct sfi_table_header *sfi_check_table(u64 paddr, | |
68 | + struct sfi_table_key *key); | |
69 | +struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); | |
70 | +extern void sfi_put_table(struct sfi_table_header *table); |
include/linux/sfi.h
1 | +/* sfi.h Simple Firmware Interface */ | |
2 | + | |
3 | +/* | |
4 | + | |
5 | + This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | + redistributing this file, you may do so under either license. | |
7 | + | |
8 | + GPL LICENSE SUMMARY | |
9 | + | |
10 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
11 | + | |
12 | + This program is free software; you can redistribute it and/or modify | |
13 | + it under the terms of version 2 of the GNU General Public License as | |
14 | + published by the Free Software Foundation. | |
15 | + | |
16 | + This program is distributed in the hope that it will be useful, but | |
17 | + WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | + General Public License for more details. | |
20 | + | |
21 | + You should have received a copy of the GNU General Public License | |
22 | + along with this program; if not, write to the Free Software | |
23 | + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | + The full GNU General Public License is included in this distribution | |
25 | + in the file called LICENSE.GPL. | |
26 | + | |
27 | + BSD LICENSE | |
28 | + | |
29 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
30 | + | |
31 | + Redistribution and use in source and binary forms, with or without | |
32 | + modification, are permitted provided that the following conditions | |
33 | + are met: | |
34 | + | |
35 | + * Redistributions of source code must retain the above copyright | |
36 | + notice, this list of conditions and the following disclaimer. | |
37 | + * Redistributions in binary form must reproduce the above copyright | |
38 | + notice, this list of conditions and the following disclaimer in | |
39 | + the documentation and/or other materials provided with the | |
40 | + distribution. | |
41 | + * Neither the name of Intel Corporation nor the names of its | |
42 | + contributors may be used to endorse or promote products derived | |
43 | + from this software without specific prior written permission. | |
44 | + | |
45 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
46 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
47 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
48 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
49 | + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
50 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
51 | + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
52 | + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
53 | + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
54 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
55 | + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
56 | + | |
57 | +*/ | |
58 | + | |
59 | +#ifndef _LINUX_SFI_H | |
60 | +#define _LINUX_SFI_H | |
61 | + | |
62 | +/* Table signatures reserved by the SFI specification */ | |
63 | +#define SFI_SIG_SYST "SYST" | |
64 | +#define SFI_SIG_FREQ "FREQ" | |
65 | +#define SFI_SIG_IDLE "IDLE" | |
66 | +#define SFI_SIG_CPUS "CPUS" | |
67 | +#define SFI_SIG_MTMR "MTMR" | |
68 | +#define SFI_SIG_MRTC "MRTC" | |
69 | +#define SFI_SIG_MMAP "MMAP" | |
70 | +#define SFI_SIG_APIC "APIC" | |
71 | +#define SFI_SIG_XSDT "XSDT" | |
72 | +#define SFI_SIG_WAKE "WAKE" | |
73 | +#define SFI_SIG_SPIB "SPIB" | |
74 | +#define SFI_SIG_I2CB "I2CB" | |
75 | +#define SFI_SIG_GPEM "GPEM" | |
76 | + | |
77 | +#define SFI_SIGNATURE_SIZE 4 | |
78 | +#define SFI_OEM_ID_SIZE 6 | |
79 | +#define SFI_OEM_TABLE_ID_SIZE 8 | |
80 | + | |
81 | +#define SFI_SYST_SEARCH_BEGIN 0x000E0000 | |
82 | +#define SFI_SYST_SEARCH_END 0x000FFFFF | |
83 | + | |
84 | +#define SFI_GET_NUM_ENTRIES(ptable, entry_type) \ | |
85 | + ((ptable->header.len - sizeof(struct sfi_table_header)) / \ | |
86 | + (sizeof(entry_type))) | |
87 | +/* | |
88 | + * Table structures must be byte-packed to match the SFI specification, | |
89 | + * as they are provided by the BIOS. | |
90 | + */ | |
91 | +struct sfi_table_header { | |
92 | + char sig[SFI_SIGNATURE_SIZE]; | |
93 | + u32 len; | |
94 | + u8 rev; | |
95 | + u8 csum; | |
96 | + char oem_id[SFI_OEM_ID_SIZE]; | |
97 | + char oem_table_id[SFI_OEM_TABLE_ID_SIZE]; | |
98 | +} __packed; | |
99 | + | |
100 | +struct sfi_table_simple { | |
101 | + struct sfi_table_header header; | |
102 | + u64 pentry[1]; | |
103 | +} __packed; | |
104 | + | |
105 | +/* Comply with UEFI spec 2.1 */ | |
106 | +struct sfi_mem_entry { | |
107 | + u32 type; | |
108 | + u64 phys_start; | |
109 | + u64 virt_start; | |
110 | + u64 pages; | |
111 | + u64 attrib; | |
112 | +} __packed; | |
113 | + | |
114 | +struct sfi_cpu_table_entry { | |
115 | + u32 apic_id; | |
116 | +} __packed; | |
117 | + | |
118 | +struct sfi_cstate_table_entry { | |
119 | + u32 hint; /* MWAIT hint */ | |
120 | + u32 latency; /* latency in ms */ | |
121 | +} __packed; | |
122 | + | |
123 | +struct sfi_apic_table_entry { | |
124 | + u64 phys_addr; /* phy base addr for APIC reg */ | |
125 | +} __packed; | |
126 | + | |
127 | +struct sfi_freq_table_entry { | |
128 | + u32 freq_mhz; /* in MHZ */ | |
129 | + u32 latency; /* transition latency in ms */ | |
130 | + u32 ctrl_val; /* value to write to PERF_CTL */ | |
131 | +} __packed; | |
132 | + | |
133 | +struct sfi_wake_table_entry { | |
134 | + u64 phys_addr; /* pointer to where the wake vector locates */ | |
135 | +} __packed; | |
136 | + | |
137 | +struct sfi_timer_table_entry { | |
138 | + u64 phys_addr; /* phy base addr for the timer */ | |
139 | + u32 freq_hz; /* in HZ */ | |
140 | + u32 irq; | |
141 | +} __packed; | |
142 | + | |
143 | +struct sfi_rtc_table_entry { | |
144 | + u64 phys_addr; /* phy base addr for the RTC */ | |
145 | + u32 irq; | |
146 | +} __packed; | |
147 | + | |
148 | +struct sfi_spi_table_entry { | |
149 | + u16 host_num; /* attached to host 0, 1...*/ | |
150 | + u16 cs; /* chip select */ | |
151 | + u16 irq_info; | |
152 | + char name[16]; | |
153 | + u8 dev_info[10]; | |
154 | +} __packed; | |
155 | + | |
156 | +struct sfi_i2c_table_entry { | |
157 | + u16 host_num; | |
158 | + u16 addr; /* slave addr */ | |
159 | + u16 irq_info; | |
160 | + char name[16]; | |
161 | + u8 dev_info[10]; | |
162 | +} __packed; | |
163 | + | |
164 | +struct sfi_gpe_table_entry { | |
165 | + u16 logical_id; /* logical id */ | |
166 | + u16 phys_id; /* physical GPE id */ | |
167 | +} __packed; | |
168 | + | |
169 | + | |
170 | +typedef int (*sfi_table_handler) (struct sfi_table_header *table); | |
171 | + | |
172 | +#ifdef CONFIG_SFI | |
173 | +extern void __init sfi_init(void); | |
174 | +extern int __init sfi_platform_init(void); | |
175 | +extern void __init sfi_init_late(void); | |
176 | +extern int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, | |
177 | + sfi_table_handler handler); | |
178 | + | |
179 | +extern int sfi_disabled; | |
180 | +static inline void disable_sfi(void) | |
181 | +{ | |
182 | + sfi_disabled = 1; | |
183 | +} | |
184 | + | |
185 | +#else /* !CONFIG_SFI */ | |
186 | + | |
187 | +static inline void sfi_init(void) | |
188 | +{ | |
189 | +} | |
190 | + | |
191 | +static inline void sfi_init_late(void) | |
192 | +{ | |
193 | +} | |
194 | + | |
195 | +#define sfi_disabled 0 | |
196 | + | |
197 | +static inline int sfi_table_parse(char *signature, char *oem_id, | |
198 | + char *oem_table_id, | |
199 | + sfi_table_handler handler) | |
200 | +{ | |
201 | + return -1; | |
202 | +} | |
203 | + | |
204 | +#endif /* !CONFIG_SFI */ | |
205 | + | |
206 | +#endif /*_LINUX_SFI_H*/ |
include/linux/sfi_acpi.h
1 | +/* sfi.h Simple Firmware Interface */ | |
2 | + | |
3 | +/* | |
4 | + | |
5 | + This file is provided under a dual BSD/GPLv2 license. When using or | |
6 | + redistributing this file, you may do so under either license. | |
7 | + | |
8 | + GPL LICENSE SUMMARY | |
9 | + | |
10 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
11 | + | |
12 | + This program is free software; you can redistribute it and/or modify | |
13 | + it under the terms of version 2 of the GNU General Public License as | |
14 | + published by the Free Software Foundation. | |
15 | + | |
16 | + This program is distributed in the hope that it will be useful, but | |
17 | + WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
19 | + General Public License for more details. | |
20 | + | |
21 | + You should have received a copy of the GNU General Public License | |
22 | + along with this program; if not, write to the Free Software | |
23 | + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | |
24 | + The full GNU General Public License is included in this distribution | |
25 | + in the file called LICENSE.GPL. | |
26 | + | |
27 | + BSD LICENSE | |
28 | + | |
29 | + Copyright(c) 2009 Intel Corporation. All rights reserved. | |
30 | + | |
31 | + Redistribution and use in source and binary forms, with or without | |
32 | + modification, are permitted provided that the following conditions | |
33 | + are met: | |
34 | + | |
35 | + * Redistributions of source code must retain the above copyright | |
36 | + notice, this list of conditions and the following disclaimer. | |
37 | + * Redistributions in binary form must reproduce the above copyright | |
38 | + notice, this list of conditions and the following disclaimer in | |
39 | + the documentation and/or other materials provided with the | |
40 | + distribution. | |
41 | + * Neither the name of Intel Corporation nor the names of its | |
42 | + contributors may be used to endorse or promote products derived | |
43 | + from this software without specific prior written permission. | |
44 | + | |
45 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
46 | + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
47 | + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
48 | + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
49 | + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
50 | + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
51 | + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
52 | + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
53 | + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
54 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
55 | + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
56 | + | |
57 | +*/ | |
58 | + | |
59 | +#ifndef _LINUX_SFI_ACPI_H | |
60 | +#define _LINUX_SFI_ACPI_H | |
61 | + | |
62 | +#ifdef CONFIG_SFI | |
63 | +#include <acpi/acpi.h> /* struct acpi_table_header */ | |
64 | + | |
65 | +extern int sfi_acpi_table_parse(char *signature, char *oem_id, | |
66 | + char *oem_table_id, | |
67 | + int (*handler)(struct acpi_table_header *)); | |
68 | + | |
69 | +static inline int acpi_sfi_table_parse(char *signature, | |
70 | + int (*handler)(struct acpi_table_header *)) | |
71 | +{ | |
72 | + if (!acpi_table_parse(signature, handler)) | |
73 | + return 0; | |
74 | + | |
75 | + return sfi_acpi_table_parse(signature, NULL, NULL, handler); | |
76 | +} | |
77 | +#else /* !CONFIG_SFI */ | |
78 | + | |
79 | +static inline int sfi_acpi_table_parse(char *signature, char *oem_id, | |
80 | + char *oem_table_id, | |
81 | + int (*handler)(struct acpi_table_header *)) | |
82 | +{ | |
83 | + return -1; | |
84 | +} | |
85 | + | |
86 | +static inline int acpi_sfi_table_parse(char *signature, | |
87 | + int (*handler)(struct acpi_table_header *)) | |
88 | +{ | |
89 | + return acpi_table_parse(signature, handler); | |
90 | +} | |
91 | +#endif /* !CONFIG_SFI */ | |
92 | + | |
93 | +#endif /*_LINUX_SFI_ACPI_H*/ |
init/main.c
... | ... | @@ -68,6 +68,7 @@ |
68 | 68 | #include <linux/async.h> |
69 | 69 | #include <linux/kmemcheck.h> |
70 | 70 | #include <linux/kmemtrace.h> |
71 | +#include <linux/sfi.h> | |
71 | 72 | #include <linux/shmem_fs.h> |
72 | 73 | #include <trace/boot.h> |
73 | 74 | |
... | ... | @@ -689,6 +690,7 @@ |
689 | 690 | check_bugs(); |
690 | 691 | |
691 | 692 | acpi_early_init(); /* before LAPIC and SMP init */ |
693 | + sfi_init_late(); | |
692 | 694 | |
693 | 695 | ftrace_init(); |
694 | 696 |