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
This commit is contained in:
		
						commit
						746942d06a
					
				
							
								
								
									
										12
									
								
								MAINTAINERS
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								MAINTAINERS
									
									
									
									
									
								
							| @ -4669,6 +4669,18 @@ L:	linux-pci@vger.kernel.org | ||||
| S:	Supported | ||||
| F:	drivers/pci/hotplug/shpchp* | ||||
| 
 | ||||
| SIMPLE FIRMWARE INTERFACE (SFI) | ||||
| P:	Len Brown | ||||
| M:	lenb@kernel.org | ||||
| L:	sfi-devel@simplefirmware.org | ||||
| W:	http://simplefirmware.org/ | ||||
| T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git | ||||
| S:	Supported | ||||
| F:	arch/x86/kernel/*sfi* | ||||
| F:	drivers/sfi/ | ||||
| F:	include/linux/sfi*.h | ||||
| 
 | ||||
| 
 | ||||
| SIMTEC EB110ATX (Chalice CATS) | ||||
| P:	Ben Dooks | ||||
| M:	Vincent Sanders <support@simtec.co.uk> | ||||
|  | ||||
| @ -1666,6 +1666,8 @@ source "kernel/power/Kconfig" | ||||
| 
 | ||||
| source "drivers/acpi/Kconfig" | ||||
| 
 | ||||
| source "drivers/sfi/Kconfig" | ||||
| 
 | ||||
| config X86_APM_BOOT | ||||
| 	bool | ||||
| 	default y | ||||
| @ -1861,7 +1863,7 @@ config PCI_DIRECT | ||||
| 
 | ||||
| config PCI_MMCONFIG | ||||
| 	def_bool y | ||||
| 	depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) | ||||
| 	depends on X86_32 && PCI && (ACPI || SFI) && (PCI_GOMMCONFIG || PCI_GOANY) | ||||
| 
 | ||||
| config PCI_OLPC | ||||
| 	def_bool y | ||||
|  | ||||
| @ -56,6 +56,7 @@ obj-$(CONFIG_INTEL_TXT)		+= tboot.o | ||||
| obj-$(CONFIG_STACKTRACE)	+= stacktrace.o | ||||
| obj-y				+= cpu/ | ||||
| obj-y				+= acpi/ | ||||
| obj-$(CONFIG_SFI)		+= sfi.o | ||||
| obj-y				+= reboot.o | ||||
| obj-$(CONFIG_MCA)		+= mca_32.o | ||||
| obj-$(CONFIG_X86_MSR)		+= msr.o | ||||
|  | ||||
| @ -27,6 +27,7 @@ | ||||
| #include <linux/screen_info.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/acpi.h> | ||||
| #include <linux/sfi.h> | ||||
| #include <linux/apm_bios.h> | ||||
| #include <linux/initrd.h> | ||||
| #include <linux/bootmem.h> | ||||
| @ -985,6 +986,8 @@ void __init setup_arch(char **cmdline_p) | ||||
| 	 */ | ||||
| 	acpi_boot_init(); | ||||
| 
 | ||||
| 	sfi_init(); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * get boot-time SMP configuration: | ||||
| 	 */ | ||||
|  | ||||
							
								
								
									
										122
									
								
								arch/x86/kernel/sfi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								arch/x86/kernel/sfi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,122 @@ | ||||
| /*
 | ||||
|  * sfi.c - x86 architecture SFI support. | ||||
|  * | ||||
|  * Copyright (c) 2009, Intel Corporation. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it | ||||
|  * under the terms and conditions of the GNU General Public License, | ||||
|  * version 2, as published by the Free Software Foundation. | ||||
|  * | ||||
|  * This program is distributed in the hope it will be useful, but WITHOUT | ||||
|  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for | ||||
|  * more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with | ||||
|  * this program; if not, write to the Free Software Foundation, Inc., | ||||
|  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #define KMSG_COMPONENT "SFI" | ||||
| #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||||
| 
 | ||||
| #include <linux/acpi.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/sfi.h> | ||||
| #include <linux/io.h> | ||||
| 
 | ||||
| #include <asm/io_apic.h> | ||||
| #include <asm/mpspec.h> | ||||
| #include <asm/setup.h> | ||||
| #include <asm/apic.h> | ||||
| 
 | ||||
| #ifdef CONFIG_X86_LOCAL_APIC | ||||
| static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; | ||||
| 
 | ||||
| void __init mp_sfi_register_lapic_address(unsigned long address) | ||||
| { | ||||
| 	mp_lapic_addr = address; | ||||
| 
 | ||||
| 	set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); | ||||
| 	if (boot_cpu_physical_apicid == -1U) | ||||
| 		boot_cpu_physical_apicid = read_apic_id(); | ||||
| 
 | ||||
| 	pr_info("Boot CPU = %d\n", boot_cpu_physical_apicid); | ||||
| } | ||||
| 
 | ||||
| /* All CPUs enumerated by SFI must be present and enabled */ | ||||
| void __cpuinit mp_sfi_register_lapic(u8 id) | ||||
| { | ||||
| 	if (MAX_APICS - id <= 0) { | ||||
| 		pr_warning("Processor #%d invalid (max %d)\n", | ||||
| 			id, MAX_APICS); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	pr_info("registering lapic[%d]\n", id); | ||||
| 
 | ||||
| 	generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR))); | ||||
| } | ||||
| 
 | ||||
| static int __init sfi_parse_cpus(struct sfi_table_header *table) | ||||
| { | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	struct sfi_cpu_table_entry *pentry; | ||||
| 	int i; | ||||
| 	int cpu_num; | ||||
| 
 | ||||
| 	sb = (struct sfi_table_simple *)table; | ||||
| 	cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry); | ||||
| 	pentry = (struct sfi_cpu_table_entry *)sb->pentry; | ||||
| 
 | ||||
| 	for (i = 0; i < cpu_num; i++) { | ||||
| 		mp_sfi_register_lapic(pentry->apic_id); | ||||
| 		pentry++; | ||||
| 	} | ||||
| 
 | ||||
| 	smp_found_config = 1; | ||||
| 	return 0; | ||||
| } | ||||
| #endif /* CONFIG_X86_LOCAL_APIC */ | ||||
| 
 | ||||
| #ifdef CONFIG_X86_IO_APIC | ||||
| static u32 gsi_base; | ||||
| 
 | ||||
| static int __init sfi_parse_ioapic(struct sfi_table_header *table) | ||||
| { | ||||
| 	struct sfi_table_simple *sb; | ||||
| 	struct sfi_apic_table_entry *pentry; | ||||
| 	int i, num; | ||||
| 
 | ||||
| 	sb = (struct sfi_table_simple *)table; | ||||
| 	num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry); | ||||
| 	pentry = (struct sfi_apic_table_entry *)sb->pentry; | ||||
| 
 | ||||
| 	for (i = 0; i < num; i++) { | ||||
| 		mp_register_ioapic(i, pentry->phys_addr, gsi_base); | ||||
| 		gsi_base += io_apic_get_redir_entries(i); | ||||
| 		pentry++; | ||||
| 	} | ||||
| 
 | ||||
| 	WARN(pic_mode, KERN_WARNING | ||||
| 		"SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n"); | ||||
| 	pic_mode = 0; | ||||
| 	return 0; | ||||
| } | ||||
| #endif /* CONFIG_X86_IO_APIC */ | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_platform_init(): register lapics & io-apics | ||||
|  */ | ||||
| int __init sfi_platform_init(void) | ||||
| { | ||||
| #ifdef CONFIG_X86_LOCAL_APIC | ||||
| 	mp_sfi_register_lapic_address(sfi_lapic_addr); | ||||
| 	sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); | ||||
| #endif | ||||
| #ifdef CONFIG_X86_IO_APIC | ||||
| 	sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic); | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| @ -13,10 +13,12 @@ | ||||
| #include <linux/pci.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/acpi.h> | ||||
| #include <linux/sfi_acpi.h> | ||||
| #include <linux/bitmap.h> | ||||
| #include <linux/sort.h> | ||||
| #include <asm/e820.h> | ||||
| #include <asm/pci_x86.h> | ||||
| #include <asm/acpi.h> | ||||
| 
 | ||||
| #define PREFIX "PCI: " | ||||
| 
 | ||||
| @ -493,7 +495,7 @@ static void __init pci_mmcfg_reject_broken(int early) | ||||
| 		       (unsigned int)cfg->start_bus_number, | ||||
| 		       (unsigned int)cfg->end_bus_number); | ||||
| 
 | ||||
| 		if (!early) | ||||
| 		if (!early && !acpi_disabled) | ||||
| 			valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); | ||||
| 
 | ||||
| 		if (valid) | ||||
| @ -608,7 +610,7 @@ static void __init __pci_mmcfg_init(int early) | ||||
| 	} | ||||
| 
 | ||||
| 	if (!known_bridge) | ||||
| 		acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); | ||||
| 		acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); | ||||
| 
 | ||||
| 	pci_mmcfg_reject_broken(early); | ||||
| 
 | ||||
|  | ||||
| @ -11,9 +11,9 @@ | ||||
| 
 | ||||
| #include <linux/pci.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/acpi.h> | ||||
| #include <asm/e820.h> | ||||
| #include <asm/pci_x86.h> | ||||
| #include <acpi/acpi.h> | ||||
| 
 | ||||
| /* Assume systems with more busses have correct MCFG */ | ||||
| #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) | ||||
|  | ||||
| @ -11,6 +11,7 @@ obj-$(CONFIG_PARISC)		+= parisc/ | ||||
| obj-$(CONFIG_RAPIDIO)		+= rapidio/ | ||||
| obj-y				+= video/ | ||||
| obj-$(CONFIG_ACPI)		+= acpi/ | ||||
| obj-$(CONFIG_SFI)		+= sfi/ | ||||
| # PnP must come after ACPI since it will eventually need to check if acpi
 | ||||
| # was used and do nothing if so
 | ||||
| obj-$(CONFIG_PNP)		+= pnp/ | ||||
|  | ||||
							
								
								
									
										17
									
								
								drivers/sfi/Kconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								drivers/sfi/Kconfig
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| # | ||||
| # SFI Configuration | ||||
| # | ||||
| 
 | ||||
| menuconfig SFI | ||||
| 	bool "SFI (Simple Firmware Interface) Support" | ||||
| 	---help--- | ||||
| 	The Simple Firmware Interface (SFI) provides a lightweight method | ||||
| 	for platform firmware to pass information to the operating system | ||||
| 	via static tables in memory.  Kernel SFI support is required to | ||||
| 	boot on SFI-only platforms.  Currently, all SFI-only platforms are | ||||
| 	based on the 2nd generation Intel Atom processor platform, | ||||
| 	code-named Moorestown. | ||||
| 
 | ||||
| 	For more information, see http://simplefirmware.org | ||||
| 
 | ||||
| 	Say 'Y' here to enable the kernel to boot on SFI-only platforms. | ||||
							
								
								
									
										3
									
								
								drivers/sfi/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								drivers/sfi/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| obj-y	+= sfi_acpi.o | ||||
| obj-y	+= sfi_core.o | ||||
| 
 | ||||
							
								
								
									
										175
									
								
								drivers/sfi/sfi_acpi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								drivers/sfi/sfi_acpi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,175 @@ | ||||
| /* sfi_acpi.c Simple Firmware Interface - ACPI extensions */ | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
|   This file is provided under a dual BSD/GPLv2 license.  When using or | ||||
|   redistributing this file, you may do so under either license. | ||||
| 
 | ||||
|   GPL LICENSE SUMMARY | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify | ||||
|   it under the terms of version 2 of the GNU General Public License as | ||||
|   published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, but | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|   General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|   The full GNU General Public License is included in this distribution | ||||
|   in the file called LICENSE.GPL. | ||||
| 
 | ||||
|   BSD LICENSE | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions | ||||
|   are met: | ||||
| 
 | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|     * Neither the name of Intel Corporation nor the names of its | ||||
|       contributors may be used to endorse or promote products derived | ||||
|       from this software without specific prior written permission. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
|   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #define KMSG_COMPONENT "SFI" | ||||
| #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||||
| 
 | ||||
| #include <linux/kernel.h> | ||||
| #include <acpi/acpi.h> | ||||
| 
 | ||||
| #include <linux/sfi.h> | ||||
| #include "sfi_core.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * SFI can access ACPI-defined tables via an optional ACPI XSDT. | ||||
|  * | ||||
|  * This allows re-use, and avoids re-definition, of standard tables. | ||||
|  * For example, the "MCFG" table is defined by PCI, reserved by ACPI, | ||||
|  * and is expected to be present many SFI-only systems. | ||||
|  */ | ||||
| 
 | ||||
| static struct acpi_table_xsdt *xsdt_va __read_mostly; | ||||
| 
 | ||||
| #define XSDT_GET_NUM_ENTRIES(ptable, entry_type) \ | ||||
| 	((ptable->header.length - sizeof(struct acpi_table_header)) / \ | ||||
| 	(sizeof(entry_type))) | ||||
| 
 | ||||
| static inline struct sfi_table_header *acpi_to_sfi_th( | ||||
| 				struct acpi_table_header *th) | ||||
| { | ||||
| 	return (struct sfi_table_header *)th; | ||||
| } | ||||
| 
 | ||||
| static inline struct acpi_table_header *sfi_to_acpi_th( | ||||
| 				struct sfi_table_header *th) | ||||
| { | ||||
| 	return (struct acpi_table_header *)th; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_acpi_parse_xsdt() | ||||
|  * | ||||
|  * Parse the ACPI XSDT for later access by sfi_acpi_table_parse(). | ||||
|  */ | ||||
| static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *th) | ||||
| { | ||||
| 	struct sfi_table_key key = SFI_ANY_KEY; | ||||
| 	int tbl_cnt, i; | ||||
| 	void *ret; | ||||
| 
 | ||||
| 	xsdt_va = (struct acpi_table_xsdt *)th; | ||||
| 	tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); | ||||
| 	for (i = 0; i < tbl_cnt; i++) { | ||||
| 		ret = sfi_check_table(xsdt_va->table_offset_entry[i], &key); | ||||
| 		if (IS_ERR(ret)) { | ||||
| 			disable_sfi(); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int __init sfi_acpi_init(void) | ||||
| { | ||||
| 	struct sfi_table_key xsdt_key = { .sig = SFI_SIG_XSDT }; | ||||
| 
 | ||||
| 	sfi_table_parse(SFI_SIG_XSDT, NULL, NULL, sfi_acpi_parse_xsdt); | ||||
| 
 | ||||
| 	/* Only call the get_table to keep the table mapped */ | ||||
| 	xsdt_va = (struct acpi_table_xsdt *)sfi_get_table(&xsdt_key); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct acpi_table_header *sfi_acpi_get_table(struct sfi_table_key *key) | ||||
| { | ||||
| 	u32 tbl_cnt, i; | ||||
| 	void *ret; | ||||
| 
 | ||||
| 	tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); | ||||
| 	for (i = 0; i < tbl_cnt; i++) { | ||||
| 		ret = sfi_check_table(xsdt_va->table_offset_entry[i], key); | ||||
| 		if (!IS_ERR(ret) && ret) | ||||
| 			return sfi_to_acpi_th(ret); | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static void sfi_acpi_put_table(struct acpi_table_header *table) | ||||
| { | ||||
| 	sfi_put_table(acpi_to_sfi_th(table)); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_acpi_table_parse() | ||||
|  * | ||||
|  * Find specified table in XSDT, run handler on it and return its return value | ||||
|  */ | ||||
| int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, | ||||
| 			int(*handler)(struct acpi_table_header *)) | ||||
| { | ||||
| 	struct acpi_table_header *table = NULL; | ||||
| 	struct sfi_table_key key; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	if (sfi_disabled) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	key.sig = signature; | ||||
| 	key.oem_id = oem_id; | ||||
| 	key.oem_table_id = oem_table_id; | ||||
| 
 | ||||
| 	table = sfi_acpi_get_table(&key); | ||||
| 	if (!table) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	ret = handler(table); | ||||
| 	sfi_acpi_put_table(table); | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										407
									
								
								drivers/sfi/sfi_core.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										407
									
								
								drivers/sfi/sfi_core.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,407 @@ | ||||
| /* sfi_core.c Simple Firmware Interface - core internals */ | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
|   This file is provided under a dual BSD/GPLv2 license.  When using or | ||||
|   redistributing this file, you may do so under either license. | ||||
| 
 | ||||
|   GPL LICENSE SUMMARY | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify | ||||
|   it under the terms of version 2 of the GNU General Public License as | ||||
|   published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, but | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|   General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|   The full GNU General Public License is included in this distribution | ||||
|   in the file called LICENSE.GPL. | ||||
| 
 | ||||
|   BSD LICENSE | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions | ||||
|   are met: | ||||
| 
 | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|     * Neither the name of Intel Corporation nor the names of its | ||||
|       contributors may be used to endorse or promote products derived | ||||
|       from this software without specific prior written permission. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
|   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #define KMSG_COMPONENT "SFI" | ||||
| #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||||
| 
 | ||||
| #include <linux/bootmem.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/errno.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/acpi.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/sfi.h> | ||||
| 
 | ||||
| #include "sfi_core.h" | ||||
| 
 | ||||
| #define ON_SAME_PAGE(addr1, addr2) \ | ||||
| 	(((unsigned long)(addr1) & PAGE_MASK) == \ | ||||
| 	((unsigned long)(addr2) & PAGE_MASK)) | ||||
| #define TABLE_ON_PAGE(page, table, size) (ON_SAME_PAGE(page, table) && \ | ||||
| 				ON_SAME_PAGE(page, table + size)) | ||||
| 
 | ||||
| int sfi_disabled __read_mostly; | ||||
| EXPORT_SYMBOL(sfi_disabled); | ||||
| 
 | ||||
| static u64 syst_pa __read_mostly; | ||||
| static struct sfi_table_simple *syst_va __read_mostly; | ||||
| 
 | ||||
| /*
 | ||||
|  * FW creates and saves the SFI tables in memory. When these tables get | ||||
|  * used, they may need to be mapped to virtual address space, and the mapping | ||||
|  * can happen before or after the ioremap() is ready, so a flag is needed | ||||
|  * to indicating this | ||||
|  */ | ||||
| static u32 sfi_use_ioremap __read_mostly; | ||||
| 
 | ||||
| static void __iomem *sfi_map_memory(u64 phys, u32 size) | ||||
| { | ||||
| 	if (!phys || !size) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	if (sfi_use_ioremap) | ||||
| 		return ioremap(phys, size); | ||||
| 	else | ||||
| 		return early_ioremap(phys, size); | ||||
| } | ||||
| 
 | ||||
| static void sfi_unmap_memory(void __iomem *virt, u32 size) | ||||
| { | ||||
| 	if (!virt || !size) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (sfi_use_ioremap) | ||||
| 		iounmap(virt); | ||||
| 	else | ||||
| 		early_iounmap(virt, size); | ||||
| } | ||||
| 
 | ||||
| static void sfi_print_table_header(unsigned long long pa, | ||||
| 				struct sfi_table_header *header) | ||||
| { | ||||
| 	pr_info("%4.4s %llX, %04X (v%d %6.6s %8.8s)\n", | ||||
| 		header->sig, pa, | ||||
| 		header->len, header->rev, header->oem_id, | ||||
| 		header->oem_table_id); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_verify_table() | ||||
|  * Sanity check table lengh, calculate checksum | ||||
|  */ | ||||
| static __init int sfi_verify_table(struct sfi_table_header *table) | ||||
| { | ||||
| 
 | ||||
| 	u8 checksum = 0; | ||||
| 	u8 *puchar = (u8 *)table; | ||||
| 	u32 length = table->len; | ||||
| 
 | ||||
| 	/* Sanity check table length against arbitrary 1MB limit */ | ||||
| 	if (length > 0x100000) { | ||||
| 		pr_err("Invalid table length 0x%x\n", length); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	while (length--) | ||||
| 		checksum += *puchar++; | ||||
| 
 | ||||
| 	if (checksum) { | ||||
| 		pr_err("Checksum %2.2X should be %2.2X\n", | ||||
| 			table->csum, table->csum - checksum); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_map_table() | ||||
|  * | ||||
|  * Return address of mapped table | ||||
|  * Check for common case that we can re-use mapping to SYST, | ||||
|  * which requires syst_pa, syst_va to be initialized. | ||||
|  */ | ||||
| struct sfi_table_header *sfi_map_table(u64 pa) | ||||
| { | ||||
| 	struct sfi_table_header *th; | ||||
| 	u32 length; | ||||
| 
 | ||||
| 	if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) | ||||
| 		th = sfi_map_memory(pa, sizeof(struct sfi_table_header)); | ||||
| 	else | ||||
| 		th = (void *)syst_va + (pa - syst_pa); | ||||
| 
 | ||||
| 	 /* If table fits on same page as its header, we are done */ | ||||
| 	if (TABLE_ON_PAGE(th, th, th->len)) | ||||
| 		return th; | ||||
| 
 | ||||
| 	/* Entire table does not fit on same page as SYST */ | ||||
| 	length = th->len; | ||||
| 	if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) | ||||
| 		sfi_unmap_memory(th, sizeof(struct sfi_table_header)); | ||||
| 
 | ||||
| 	return sfi_map_memory(pa, length); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_unmap_table() | ||||
|  * | ||||
|  * Undoes effect of sfi_map_table() by unmapping table | ||||
|  * if it did not completely fit on same page as SYST. | ||||
|  */ | ||||
| void sfi_unmap_table(struct sfi_table_header *th) | ||||
| { | ||||
| 	if (!TABLE_ON_PAGE(syst_va, th, th->len)) | ||||
| 		sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ? | ||||
| 					sizeof(*th) : th->len); | ||||
| } | ||||
| 
 | ||||
| static int sfi_table_check_key(struct sfi_table_header *th, | ||||
| 				struct sfi_table_key *key) | ||||
| { | ||||
| 
 | ||||
| 	if (strncmp(th->sig, key->sig, SFI_SIGNATURE_SIZE) | ||||
| 		|| (key->oem_id && strncmp(th->oem_id, | ||||
| 				key->oem_id, SFI_OEM_ID_SIZE)) | ||||
| 		|| (key->oem_table_id && strncmp(th->oem_table_id, | ||||
| 				key->oem_table_id, SFI_OEM_TABLE_ID_SIZE))) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This function will be used in 2 cases: | ||||
|  * 1. used to enumerate and verify the tables addressed by SYST/XSDT, | ||||
|  *    thus no signature will be given (in kernel boot phase) | ||||
|  * 2. used to parse one specific table, signature must exist, and | ||||
|  *    the mapped virt address will be returned, and the virt space | ||||
|  *    will be released by call sfi_put_table() later | ||||
|  * | ||||
|  * Return value: | ||||
|  *	NULL:			when can't find a table matching the key | ||||
|  *	ERR_PTR(error):		error value | ||||
|  *	virt table address:	when a matched table is found | ||||
|  */ | ||||
| struct sfi_table_header *sfi_check_table(u64 pa, struct sfi_table_key *key) | ||||
| { | ||||
| 	struct sfi_table_header *th; | ||||
| 	void *ret = NULL; | ||||
| 
 | ||||
| 	th = sfi_map_table(pa); | ||||
| 	if (!th) | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	if (!key->sig) { | ||||
| 		sfi_print_table_header(pa, th); | ||||
| 		if (sfi_verify_table(th)) | ||||
| 			ret = ERR_PTR(-EINVAL); | ||||
| 	} else { | ||||
| 		if (!sfi_table_check_key(th, key)) | ||||
| 			return th;	/* Success */ | ||||
| 	} | ||||
| 
 | ||||
| 	sfi_unmap_table(th); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_get_table() | ||||
|  * | ||||
|  * Search SYST for the specified table with the signature in | ||||
|  * the key, and return the mapped table | ||||
|  */ | ||||
| struct sfi_table_header *sfi_get_table(struct sfi_table_key *key) | ||||
| { | ||||
| 	struct sfi_table_header *th; | ||||
| 	u32 tbl_cnt, i; | ||||
| 
 | ||||
| 	tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); | ||||
| 	for (i = 0; i < tbl_cnt; i++) { | ||||
| 		th = sfi_check_table(syst_va->pentry[i], key); | ||||
| 		if (!IS_ERR(th) && th) | ||||
| 			return th; | ||||
| 	} | ||||
| 
 | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| void sfi_put_table(struct sfi_table_header *th) | ||||
| { | ||||
| 	sfi_unmap_table(th); | ||||
| } | ||||
| 
 | ||||
| /* Find table with signature, run handler on it */ | ||||
| int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, | ||||
| 			sfi_table_handler handler) | ||||
| { | ||||
| 	struct sfi_table_header *table = NULL; | ||||
| 	struct sfi_table_key key; | ||||
| 	int ret = -EINVAL; | ||||
| 
 | ||||
| 	if (sfi_disabled || !handler || !signature) | ||||
| 		goto exit; | ||||
| 
 | ||||
| 	key.sig = signature; | ||||
| 	key.oem_id = oem_id; | ||||
| 	key.oem_table_id = oem_table_id; | ||||
| 
 | ||||
| 	table = sfi_get_table(&key); | ||||
| 	if (!table) | ||||
| 		goto exit; | ||||
| 
 | ||||
| 	ret = handler(table); | ||||
| 	sfi_put_table(table); | ||||
| exit: | ||||
| 	return ret; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(sfi_table_parse); | ||||
| 
 | ||||
| /*
 | ||||
|  * sfi_parse_syst() | ||||
|  * Checksum all the tables in SYST and print their headers | ||||
|  * | ||||
|  * success: set syst_va, return 0 | ||||
|  */ | ||||
| static int __init sfi_parse_syst(void) | ||||
| { | ||||
| 	struct sfi_table_key key = SFI_ANY_KEY; | ||||
| 	int tbl_cnt, i; | ||||
| 	void *ret; | ||||
| 
 | ||||
| 	syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple)); | ||||
| 	if (!syst_va) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); | ||||
| 	for (i = 0; i < tbl_cnt; i++) { | ||||
| 		ret = sfi_check_table(syst_va->pentry[i], &key); | ||||
| 		if (IS_ERR(ret)) | ||||
| 			return PTR_ERR(ret); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * The OS finds the System Table by searching 16-byte boundaries between | ||||
|  * physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region | ||||
|  * starting at the low address and shall stop searching when the 1st valid SFI | ||||
|  * System Table is found. | ||||
|  * | ||||
|  * success: set syst_pa, return 0 | ||||
|  * fail: return -1 | ||||
|  */ | ||||
| static __init int sfi_find_syst(void) | ||||
| { | ||||
| 	unsigned long offset, len; | ||||
| 	void *start; | ||||
| 
 | ||||
| 	len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN; | ||||
| 	start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len); | ||||
| 	if (!start) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	for (offset = 0; offset < len; offset += 16) { | ||||
| 		struct sfi_table_header *syst_hdr; | ||||
| 
 | ||||
| 		syst_hdr = start + offset; | ||||
| 		if (strncmp(syst_hdr->sig, SFI_SIG_SYST, | ||||
| 				SFI_SIGNATURE_SIZE)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (syst_hdr->len > PAGE_SIZE) | ||||
| 			continue; | ||||
| 
 | ||||
| 		sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset, | ||||
| 					syst_hdr); | ||||
| 
 | ||||
| 		if (sfi_verify_table(syst_hdr)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Enforce SFI spec mandate that SYST reside within a page. | ||||
| 		 */ | ||||
| 		if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) { | ||||
| 			pr_info("SYST 0x%llx + 0x%x crosses page\n", | ||||
| 					syst_pa, syst_hdr->len); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* Success */ | ||||
| 		syst_pa = SFI_SYST_SEARCH_BEGIN + offset; | ||||
| 		sfi_unmap_memory(start, len); | ||||
| 		return 0; | ||||
| 	} | ||||
| 
 | ||||
| 	sfi_unmap_memory(start, len); | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| void __init sfi_init(void) | ||||
| { | ||||
| 	if (!acpi_disabled) | ||||
| 		disable_sfi(); | ||||
| 
 | ||||
| 	if (sfi_disabled) | ||||
| 		return; | ||||
| 
 | ||||
| 	pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); | ||||
| 
 | ||||
| 	if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) | ||||
| 		disable_sfi(); | ||||
| 
 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| void __init sfi_init_late(void) | ||||
| { | ||||
| 	int length; | ||||
| 
 | ||||
| 	if (sfi_disabled) | ||||
| 		return; | ||||
| 
 | ||||
| 	length = syst_va->header.len; | ||||
| 	sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple)); | ||||
| 
 | ||||
| 	/* Use ioremap now after it is ready */ | ||||
| 	sfi_use_ioremap = 1; | ||||
| 	syst_va = sfi_map_memory(syst_pa, length); | ||||
| 
 | ||||
| 	sfi_acpi_init(); | ||||
| } | ||||
							
								
								
									
										70
									
								
								drivers/sfi/sfi_core.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								drivers/sfi/sfi_core.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| /* sfi_core.h Simple Firmware Interface, internal header */ | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
|   This file is provided under a dual BSD/GPLv2 license.  When using or | ||||
|   redistributing this file, you may do so under either license. | ||||
| 
 | ||||
|   GPL LICENSE SUMMARY | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify | ||||
|   it under the terms of version 2 of the GNU General Public License as | ||||
|   published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, but | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|   General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|   The full GNU General Public License is included in this distribution | ||||
|   in the file called LICENSE.GPL. | ||||
| 
 | ||||
|   BSD LICENSE | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions | ||||
|   are met: | ||||
| 
 | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|     * Neither the name of Intel Corporation nor the names of its | ||||
|       contributors may be used to endorse or promote products derived | ||||
|       from this software without specific prior written permission. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
|   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| */ | ||||
| struct sfi_table_key{ | ||||
| 	char	*sig; | ||||
| 	char	*oem_id; | ||||
| 	char	*oem_table_id; | ||||
| }; | ||||
| 
 | ||||
| #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } | ||||
| 
 | ||||
| extern int __init sfi_acpi_init(void); | ||||
| extern  struct sfi_table_header *sfi_check_table(u64 paddr, | ||||
| 					struct sfi_table_key *key); | ||||
| struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); | ||||
| extern void sfi_put_table(struct sfi_table_header *table); | ||||
							
								
								
									
										206
									
								
								include/linux/sfi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								include/linux/sfi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,206 @@ | ||||
| /* sfi.h Simple Firmware Interface */ | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
|   This file is provided under a dual BSD/GPLv2 license.  When using or | ||||
|   redistributing this file, you may do so under either license. | ||||
| 
 | ||||
|   GPL LICENSE SUMMARY | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify | ||||
|   it under the terms of version 2 of the GNU General Public License as | ||||
|   published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, but | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|   General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|   The full GNU General Public License is included in this distribution | ||||
|   in the file called LICENSE.GPL. | ||||
| 
 | ||||
|   BSD LICENSE | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions | ||||
|   are met: | ||||
| 
 | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|     * Neither the name of Intel Corporation nor the names of its | ||||
|       contributors may be used to endorse or promote products derived | ||||
|       from this software without specific prior written permission. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
|   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef _LINUX_SFI_H | ||||
| #define _LINUX_SFI_H | ||||
| 
 | ||||
| /* Table signatures reserved by the SFI specification */ | ||||
| #define SFI_SIG_SYST		"SYST" | ||||
| #define SFI_SIG_FREQ		"FREQ" | ||||
| #define SFI_SIG_IDLE		"IDLE" | ||||
| #define SFI_SIG_CPUS		"CPUS" | ||||
| #define SFI_SIG_MTMR		"MTMR" | ||||
| #define SFI_SIG_MRTC		"MRTC" | ||||
| #define SFI_SIG_MMAP		"MMAP" | ||||
| #define SFI_SIG_APIC		"APIC" | ||||
| #define SFI_SIG_XSDT		"XSDT" | ||||
| #define SFI_SIG_WAKE		"WAKE" | ||||
| #define SFI_SIG_SPIB		"SPIB" | ||||
| #define SFI_SIG_I2CB		"I2CB" | ||||
| #define SFI_SIG_GPEM		"GPEM" | ||||
| 
 | ||||
| #define SFI_SIGNATURE_SIZE	4 | ||||
| #define SFI_OEM_ID_SIZE		6 | ||||
| #define SFI_OEM_TABLE_ID_SIZE	8 | ||||
| 
 | ||||
| #define SFI_SYST_SEARCH_BEGIN		0x000E0000 | ||||
| #define SFI_SYST_SEARCH_END		0x000FFFFF | ||||
| 
 | ||||
| #define SFI_GET_NUM_ENTRIES(ptable, entry_type) \ | ||||
| 	((ptable->header.len - sizeof(struct sfi_table_header)) / \ | ||||
| 	(sizeof(entry_type))) | ||||
| /*
 | ||||
|  * Table structures must be byte-packed to match the SFI specification, | ||||
|  * as they are provided by the BIOS. | ||||
|  */ | ||||
| struct sfi_table_header { | ||||
| 	char	sig[SFI_SIGNATURE_SIZE]; | ||||
| 	u32	len; | ||||
| 	u8	rev; | ||||
| 	u8	csum; | ||||
| 	char	oem_id[SFI_OEM_ID_SIZE]; | ||||
| 	char	oem_table_id[SFI_OEM_TABLE_ID_SIZE]; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_table_simple { | ||||
| 	struct sfi_table_header		header; | ||||
| 	u64				pentry[1]; | ||||
| } __packed; | ||||
| 
 | ||||
| /* Comply with UEFI spec 2.1 */ | ||||
| struct sfi_mem_entry { | ||||
| 	u32	type; | ||||
| 	u64	phys_start; | ||||
| 	u64	virt_start; | ||||
| 	u64	pages; | ||||
| 	u64	attrib; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_cpu_table_entry { | ||||
| 	u32	apic_id; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_cstate_table_entry { | ||||
| 	u32	hint;		/* MWAIT hint */ | ||||
| 	u32	latency;	/* latency in ms */ | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_apic_table_entry { | ||||
| 	u64	phys_addr;	/* phy base addr for APIC reg */ | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_freq_table_entry { | ||||
| 	u32	freq_mhz;	/* in MHZ */ | ||||
| 	u32	latency;	/* transition latency in ms */ | ||||
| 	u32	ctrl_val;	/* value to write to PERF_CTL */ | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_wake_table_entry { | ||||
| 	u64	phys_addr;	/* pointer to where the wake vector locates */ | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_timer_table_entry { | ||||
| 	u64	phys_addr;	/* phy base addr for the timer */ | ||||
| 	u32	freq_hz;	/* in HZ */ | ||||
| 	u32	irq; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_rtc_table_entry { | ||||
| 	u64	phys_addr;	/* phy base addr for the RTC */ | ||||
| 	u32	irq; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_spi_table_entry { | ||||
| 	u16	host_num;	/* attached to host 0, 1...*/ | ||||
| 	u16	cs;		/* chip select */ | ||||
| 	u16	irq_info; | ||||
| 	char	name[16]; | ||||
| 	u8	dev_info[10]; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_i2c_table_entry { | ||||
| 	u16	host_num; | ||||
| 	u16	addr;		/* slave addr */ | ||||
| 	u16	irq_info; | ||||
| 	char	name[16]; | ||||
| 	u8	dev_info[10]; | ||||
| } __packed; | ||||
| 
 | ||||
| struct sfi_gpe_table_entry { | ||||
| 	u16	logical_id;	/* logical id */ | ||||
| 	u16	phys_id;	/* physical GPE id */ | ||||
| } __packed; | ||||
| 
 | ||||
| 
 | ||||
| typedef int (*sfi_table_handler) (struct sfi_table_header *table); | ||||
| 
 | ||||
| #ifdef CONFIG_SFI | ||||
| extern void __init sfi_init(void); | ||||
| extern int __init sfi_platform_init(void); | ||||
| extern void __init sfi_init_late(void); | ||||
| extern int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, | ||||
| 				sfi_table_handler handler); | ||||
| 
 | ||||
| extern int sfi_disabled; | ||||
| static inline void disable_sfi(void) | ||||
| { | ||||
| 	sfi_disabled = 1; | ||||
| } | ||||
| 
 | ||||
| #else /* !CONFIG_SFI */ | ||||
| 
 | ||||
| static inline void sfi_init(void) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| static inline void sfi_init_late(void) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| #define sfi_disabled	0 | ||||
| 
 | ||||
| static inline int sfi_table_parse(char *signature, char *oem_id, | ||||
| 					char *oem_table_id, | ||||
| 					sfi_table_handler handler) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| #endif /* !CONFIG_SFI */ | ||||
| 
 | ||||
| #endif /*_LINUX_SFI_H*/ | ||||
							
								
								
									
										93
									
								
								include/linux/sfi_acpi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								include/linux/sfi_acpi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| /* sfi.h Simple Firmware Interface */ | ||||
| 
 | ||||
| /*
 | ||||
| 
 | ||||
|   This file is provided under a dual BSD/GPLv2 license.  When using or | ||||
|   redistributing this file, you may do so under either license. | ||||
| 
 | ||||
|   GPL LICENSE SUMMARY | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   This program is free software; you can redistribute it and/or modify | ||||
|   it under the terms of version 2 of the GNU General Public License as | ||||
|   published by the Free Software Foundation. | ||||
| 
 | ||||
|   This program is distributed in the hope that it will be useful, but | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | ||||
|   General Public License for more details. | ||||
| 
 | ||||
|   You should have received a copy of the GNU General Public License | ||||
|   along with this program; if not, write to the Free Software | ||||
|   Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|   The full GNU General Public License is included in this distribution | ||||
|   in the file called LICENSE.GPL. | ||||
| 
 | ||||
|   BSD LICENSE | ||||
| 
 | ||||
|   Copyright(c) 2009 Intel Corporation. All rights reserved. | ||||
| 
 | ||||
|   Redistribution and use in source and binary forms, with or without | ||||
|   modification, are permitted provided that the following conditions | ||||
|   are met: | ||||
| 
 | ||||
|     * Redistributions of source code must retain the above copyright | ||||
|       notice, this list of conditions and the following disclaimer. | ||||
|     * Redistributions in binary form must reproduce the above copyright | ||||
|       notice, this list of conditions and the following disclaimer in | ||||
|       the documentation and/or other materials provided with the | ||||
|       distribution. | ||||
|     * Neither the name of Intel Corporation nor the names of its | ||||
|       contributors may be used to endorse or promote products derived | ||||
|       from this software without specific prior written permission. | ||||
| 
 | ||||
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||||
|   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
|   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| #ifndef _LINUX_SFI_ACPI_H | ||||
| #define _LINUX_SFI_ACPI_H | ||||
| 
 | ||||
| #ifdef CONFIG_SFI | ||||
| #include <acpi/acpi.h>		/* struct acpi_table_header */ | ||||
| 
 | ||||
| extern int sfi_acpi_table_parse(char *signature, char *oem_id, | ||||
| 				char *oem_table_id, | ||||
| 				int (*handler)(struct acpi_table_header *)); | ||||
| 
 | ||||
| static inline int acpi_sfi_table_parse(char *signature, | ||||
| 				int (*handler)(struct acpi_table_header *)) | ||||
| { | ||||
| 	if (!acpi_table_parse(signature, handler)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	return sfi_acpi_table_parse(signature, NULL, NULL, handler); | ||||
| } | ||||
| #else /* !CONFIG_SFI */ | ||||
| 
 | ||||
| static inline int sfi_acpi_table_parse(char *signature, char *oem_id, | ||||
| 				char *oem_table_id, | ||||
| 				int (*handler)(struct acpi_table_header *)) | ||||
| { | ||||
| 	return -1; | ||||
| } | ||||
| 
 | ||||
| static inline int acpi_sfi_table_parse(char *signature, | ||||
| 				int (*handler)(struct acpi_table_header *)) | ||||
| { | ||||
| 	return acpi_table_parse(signature, handler); | ||||
| } | ||||
| #endif /* !CONFIG_SFI */ | ||||
| 
 | ||||
| #endif /*_LINUX_SFI_ACPI_H*/ | ||||
| @ -68,6 +68,7 @@ | ||||
| #include <linux/async.h> | ||||
| #include <linux/kmemcheck.h> | ||||
| #include <linux/kmemtrace.h> | ||||
| #include <linux/sfi.h> | ||||
| #include <linux/shmem_fs.h> | ||||
| #include <trace/boot.h> | ||||
| 
 | ||||
| @ -689,6 +690,7 @@ asmlinkage void __init start_kernel(void) | ||||
| 	check_bugs(); | ||||
| 
 | ||||
| 	acpi_early_init(); /* before LAPIC and SMP init */ | ||||
| 	sfi_init_late(); | ||||
| 
 | ||||
| 	ftrace_init(); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user