Loading Documentation/ABI/testing/sysfs-firmware-sfi 0 → 100644 +15 −0 Original line number Diff line number Diff line What: /sys/firmware/sfi/tables/ Date: May 2010 Contact: Len Brown <lenb@kernel.org> Description: SFI defines a number of small static memory tables so the kernel can get platform information from firmware. The tables are defined in the latest SFI specification: http://simplefirmware.org/documentation While the tables are used by the kernel, user-space can observe them this way: # cd /sys/firmware/sfi/tables # cat $TABLENAME > $TABLENAME.bin drivers/sfi/sfi_acpi.c +41 −0 Original line number Diff line number Diff line Loading @@ -173,3 +173,44 @@ int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, sfi_acpi_put_table(table); return ret; } static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t offset, size_t count) { struct sfi_table_attr *tbl_attr = container_of(bin_attr, struct sfi_table_attr, attr); struct acpi_table_header *th = NULL; struct sfi_table_key key; ssize_t cnt; key.sig = tbl_attr->name; key.oem_id = NULL; key.oem_table_id = NULL; th = sfi_acpi_get_table(&key); if (!th) return 0; cnt = memory_read_from_buffer(buf, count, &offset, th, th->length); sfi_acpi_put_table(th); return cnt; } void __init sfi_acpi_sysfs_init(void) { u32 tbl_cnt, i; struct sfi_table_attr *tbl_attr; tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); for (i = 0; i < tbl_cnt; i++) { tbl_attr = sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]); tbl_attr->attr.read = sfi_acpi_table_show; } return; } drivers/sfi/sfi_core.c +104 −1 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #include <linux/acpi.h> #include <linux/init.h> #include <linux/sfi.h> #include <linux/slab.h> #include "sfi_core.h" Loading Loading @@ -382,6 +383,102 @@ static __init int sfi_find_syst(void) return -1; } static struct kobject *sfi_kobj; static struct kobject *tables_kobj; static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t offset, size_t count) { struct sfi_table_attr *tbl_attr = container_of(bin_attr, struct sfi_table_attr, attr); struct sfi_table_header *th = NULL; struct sfi_table_key key; ssize_t cnt; key.sig = tbl_attr->name; key.oem_id = NULL; key.oem_table_id = NULL; if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) { th = sfi_get_table(&key); if (!th) return 0; cnt = memory_read_from_buffer(buf, count, &offset, th, th->len); sfi_put_table(th); } else cnt = memory_read_from_buffer(buf, count, &offset, syst_va, syst_va->header.len); return cnt; } struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa) { struct sfi_table_attr *tbl_attr; struct sfi_table_header *th; int ret; tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL); if (!tbl_attr) return NULL; th = sfi_map_table(pa); if (!th || !th->sig[0]) { kfree(tbl_attr); return NULL; } sysfs_attr_init(&tbl_attr->attr.attr); memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE); tbl_attr->attr.size = 0; tbl_attr->attr.read = sfi_table_show; tbl_attr->attr.attr.name = tbl_attr->name; tbl_attr->attr.attr.mode = 0400; ret = sysfs_create_bin_file(tables_kobj, &tbl_attr->attr); if (ret) kfree(tbl_attr); sfi_unmap_table(th); return tbl_attr; } static int __init sfi_sysfs_init(void) { int tbl_cnt, i; if (sfi_disabled) return 0; sfi_kobj = kobject_create_and_add("sfi", firmware_kobj); if (!sfi_kobj) return 0; tables_kobj = kobject_create_and_add("tables", sfi_kobj); if (!tables_kobj) { kobject_put(sfi_kobj); return 0; } sfi_sysfs_install_table(syst_pa); tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); for (i = 0; i < tbl_cnt; i++) sfi_sysfs_install_table(syst_va->pentry[i]); sfi_acpi_sysfs_init(); kobject_uevent(sfi_kobj, KOBJ_ADD); kobject_uevent(tables_kobj, KOBJ_ADD); pr_info("SFI sysfs interfaces init success\n"); return 0; } void __init sfi_init(void) { if (!acpi_disabled) Loading @@ -390,7 +487,7 @@ void __init sfi_init(void) if (sfi_disabled) return; pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n"); if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) disable_sfi(); Loading @@ -414,3 +511,9 @@ void __init sfi_init_late(void) sfi_acpi_init(); } /* * The reason we put it here becasue we need wait till the /sys/firmware * is setup, then our interface can be registered in /sys/firmware/sfi */ core_initcall(sfi_sysfs_init); drivers/sfi/sfi_core.h +8 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,12 @@ struct sfi_table_key{ char *oem_table_id; }; /* sysfs interface */ struct sfi_table_attr { struct bin_attribute attr; char name[8]; }; #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } extern int __init sfi_acpi_init(void); Loading @@ -68,3 +74,5 @@ 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); extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa); extern void __init sfi_acpi_sysfs_init(void); include/linux/sfi.h +23 −1 Original line number Diff line number Diff line Loading @@ -73,6 +73,8 @@ #define SFI_SIG_SPIB "SPIB" #define SFI_SIG_I2CB "I2CB" #define SFI_SIG_GPEM "GPEM" #define SFI_SIG_DEVS "DEVS" #define SFI_SIG_GPIO "GPIO" #define SFI_SIGNATURE_SIZE 4 #define SFI_OEM_ID_SIZE 6 Loading Loading @@ -145,6 +147,27 @@ struct sfi_rtc_table_entry { u32 irq; } __packed; struct sfi_device_table_entry { u8 type; /* bus type, I2C, SPI or ...*/ #define SFI_DEV_TYPE_SPI 0 #define SFI_DEV_TYPE_I2C 1 #define SFI_DEV_TYPE_UART 2 #define SFI_DEV_TYPE_HSI 3 #define SFI_DEV_TYPE_IPC 4 u8 host_num; /* attached to host 0, 1...*/ u16 addr; u8 irq; u32 max_freq; char name[16]; } __packed; struct sfi_gpio_table_entry { char controller_name[16]; u16 pin_no; char pin_name[16]; } __packed; struct sfi_spi_table_entry { u16 host_num; /* attached to host 0, 1...*/ u16 cs; /* chip select */ Loading @@ -166,7 +189,6 @@ struct sfi_gpe_table_entry { u16 phys_id; /* physical GPE id */ } __packed; typedef int (*sfi_table_handler) (struct sfi_table_header *table); #ifdef CONFIG_SFI Loading Loading
Documentation/ABI/testing/sysfs-firmware-sfi 0 → 100644 +15 −0 Original line number Diff line number Diff line What: /sys/firmware/sfi/tables/ Date: May 2010 Contact: Len Brown <lenb@kernel.org> Description: SFI defines a number of small static memory tables so the kernel can get platform information from firmware. The tables are defined in the latest SFI specification: http://simplefirmware.org/documentation While the tables are used by the kernel, user-space can observe them this way: # cd /sys/firmware/sfi/tables # cat $TABLENAME > $TABLENAME.bin
drivers/sfi/sfi_acpi.c +41 −0 Original line number Diff line number Diff line Loading @@ -173,3 +173,44 @@ int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, sfi_acpi_put_table(table); return ret; } static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t offset, size_t count) { struct sfi_table_attr *tbl_attr = container_of(bin_attr, struct sfi_table_attr, attr); struct acpi_table_header *th = NULL; struct sfi_table_key key; ssize_t cnt; key.sig = tbl_attr->name; key.oem_id = NULL; key.oem_table_id = NULL; th = sfi_acpi_get_table(&key); if (!th) return 0; cnt = memory_read_from_buffer(buf, count, &offset, th, th->length); sfi_acpi_put_table(th); return cnt; } void __init sfi_acpi_sysfs_init(void) { u32 tbl_cnt, i; struct sfi_table_attr *tbl_attr; tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); for (i = 0; i < tbl_cnt; i++) { tbl_attr = sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]); tbl_attr->attr.read = sfi_acpi_table_show; } return; }
drivers/sfi/sfi_core.c +104 −1 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ #include <linux/acpi.h> #include <linux/init.h> #include <linux/sfi.h> #include <linux/slab.h> #include "sfi_core.h" Loading Loading @@ -382,6 +383,102 @@ static __init int sfi_find_syst(void) return -1; } static struct kobject *sfi_kobj; static struct kobject *tables_kobj; static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t offset, size_t count) { struct sfi_table_attr *tbl_attr = container_of(bin_attr, struct sfi_table_attr, attr); struct sfi_table_header *th = NULL; struct sfi_table_key key; ssize_t cnt; key.sig = tbl_attr->name; key.oem_id = NULL; key.oem_table_id = NULL; if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) { th = sfi_get_table(&key); if (!th) return 0; cnt = memory_read_from_buffer(buf, count, &offset, th, th->len); sfi_put_table(th); } else cnt = memory_read_from_buffer(buf, count, &offset, syst_va, syst_va->header.len); return cnt; } struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa) { struct sfi_table_attr *tbl_attr; struct sfi_table_header *th; int ret; tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL); if (!tbl_attr) return NULL; th = sfi_map_table(pa); if (!th || !th->sig[0]) { kfree(tbl_attr); return NULL; } sysfs_attr_init(&tbl_attr->attr.attr); memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE); tbl_attr->attr.size = 0; tbl_attr->attr.read = sfi_table_show; tbl_attr->attr.attr.name = tbl_attr->name; tbl_attr->attr.attr.mode = 0400; ret = sysfs_create_bin_file(tables_kobj, &tbl_attr->attr); if (ret) kfree(tbl_attr); sfi_unmap_table(th); return tbl_attr; } static int __init sfi_sysfs_init(void) { int tbl_cnt, i; if (sfi_disabled) return 0; sfi_kobj = kobject_create_and_add("sfi", firmware_kobj); if (!sfi_kobj) return 0; tables_kobj = kobject_create_and_add("tables", sfi_kobj); if (!tables_kobj) { kobject_put(sfi_kobj); return 0; } sfi_sysfs_install_table(syst_pa); tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); for (i = 0; i < tbl_cnt; i++) sfi_sysfs_install_table(syst_va->pentry[i]); sfi_acpi_sysfs_init(); kobject_uevent(sfi_kobj, KOBJ_ADD); kobject_uevent(tables_kobj, KOBJ_ADD); pr_info("SFI sysfs interfaces init success\n"); return 0; } void __init sfi_init(void) { if (!acpi_disabled) Loading @@ -390,7 +487,7 @@ void __init sfi_init(void) if (sfi_disabled) return; pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n"); if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) disable_sfi(); Loading @@ -414,3 +511,9 @@ void __init sfi_init_late(void) sfi_acpi_init(); } /* * The reason we put it here becasue we need wait till the /sys/firmware * is setup, then our interface can be registered in /sys/firmware/sfi */ core_initcall(sfi_sysfs_init);
drivers/sfi/sfi_core.h +8 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,12 @@ struct sfi_table_key{ char *oem_table_id; }; /* sysfs interface */ struct sfi_table_attr { struct bin_attribute attr; char name[8]; }; #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } extern int __init sfi_acpi_init(void); Loading @@ -68,3 +74,5 @@ 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); extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa); extern void __init sfi_acpi_sysfs_init(void);
include/linux/sfi.h +23 −1 Original line number Diff line number Diff line Loading @@ -73,6 +73,8 @@ #define SFI_SIG_SPIB "SPIB" #define SFI_SIG_I2CB "I2CB" #define SFI_SIG_GPEM "GPEM" #define SFI_SIG_DEVS "DEVS" #define SFI_SIG_GPIO "GPIO" #define SFI_SIGNATURE_SIZE 4 #define SFI_OEM_ID_SIZE 6 Loading Loading @@ -145,6 +147,27 @@ struct sfi_rtc_table_entry { u32 irq; } __packed; struct sfi_device_table_entry { u8 type; /* bus type, I2C, SPI or ...*/ #define SFI_DEV_TYPE_SPI 0 #define SFI_DEV_TYPE_I2C 1 #define SFI_DEV_TYPE_UART 2 #define SFI_DEV_TYPE_HSI 3 #define SFI_DEV_TYPE_IPC 4 u8 host_num; /* attached to host 0, 1...*/ u16 addr; u8 irq; u32 max_freq; char name[16]; } __packed; struct sfi_gpio_table_entry { char controller_name[16]; u16 pin_no; char pin_name[16]; } __packed; struct sfi_spi_table_entry { u16 host_num; /* attached to host 0, 1...*/ u16 cs; /* chip select */ Loading @@ -166,7 +189,6 @@ struct sfi_gpe_table_entry { u16 phys_id; /* physical GPE id */ } __packed; typedef int (*sfi_table_handler) (struct sfi_table_header *table); #ifdef CONFIG_SFI Loading