Index: stand/efi/loader/main.c =================================================================== --- stand/efi/loader/main.c +++ stand/efi/loader/main.c @@ -1161,17 +1161,32 @@ efi_init_environment(); #if !defined(__arm__) + int found = 0; for (k = 0; k < ST->NumberOfTableEntries; k++) { + guid = &ST->ConfigurationTable[k].VendorGuid; + if (!memcmp(guid, &smbios3, sizeof(EFI_GUID))) { + found = 3; + break; + } + } + for (k = 0; found == 0 && k < ST->NumberOfTableEntries; k++) { guid = &ST->ConfigurationTable[k].VendorGuid; if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) { - char buf[40]; + found = 2; + break; + } + } + if (found > 0) { + char buf[40]; - snprintf(buf, sizeof(buf), "%p", - ST->ConfigurationTable[k].VendorTable); + snprintf(buf, sizeof(buf), "%p", + ST->ConfigurationTable[k].VendorTable); + if (found == 3) { + setenv("hint.smbios3.0.mem", buf, 1); + } else { setenv("hint.smbios.0.mem", buf, 1); - smbios_detect(ST->ConfigurationTable[k].VendorTable); - break; } + smbios_detect(ST->ConfigurationTable[k].VendorTable); } #endif Index: stand/libsa/smbios.c =================================================================== --- stand/libsa/smbios.c +++ stand/libsa/smbios.c @@ -54,10 +54,12 @@ #define SMBIOS_STEP 0x10 #define SMBIOS_SIG "_SM_" #define SMBIOS_DMI_SIG "_DMI_" +#define SMBIOS3_SIG "_SM3_" #define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off))) #define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off))) #define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off))) +#define SMBIOS_GET64(base, off) (*(uint64_t *)((base) + (off))) #define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01) #define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base)) @@ -98,6 +100,11 @@ caddr_t cp; /* Search on 16-byte boundaries. */ + for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) + if (strncmp(cp, SMBIOS3_SIG, 5) == 0 && + smbios_checksum(cp, SMBIOS_GET8(cp, 0x06)) == 0) + return (cp); + for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) if (strncmp(cp, SMBIOS_SIG, 4) == 0 && smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 && @@ -423,7 +430,9 @@ return (NULL); for (dmi = smbios.addr, i = 0; - dmi < smbios.addr + smbios.length && i < smbios.count; i++) { + dmi < smbios.addr + smbios.length && + (smbios.count == 0 || i < smbios.count); + i++) { if (SMBIOS_GET8(dmi, 0) == type) return dmi; /* Find structure terminator. */ @@ -437,25 +446,44 @@ } static void -smbios_probe(const caddr_t addr) +smbios_probe(caddr_t addr) { caddr_t saddr, info; uintptr_t paddr; + uint32_t searchlen; + bool ep_64bit; if (smbios.probed) return; smbios.probed = 1; + if (addr == 0) { + addr = PTOV(SMBIOS_START); + searchlen = SMBIOS_LENGTH; + } else { + searchlen = 1; + } + /* Search signatures and validate checksums. */ - saddr = smbios_sigsearch(addr ? addr : PTOV(SMBIOS_START), - SMBIOS_LENGTH); + saddr = smbios_sigsearch(addr, searchlen); if (saddr == NULL) return; - smbios.length = SMBIOS_GET16(saddr, 0x16); /* Structure Table Length */ - paddr = SMBIOS_GET32(saddr, 0x18); /* Structure Table Address */ - smbios.count = SMBIOS_GET16(saddr, 0x1c); /* No of SMBIOS Structures */ - smbios.ver = SMBIOS_GET8(saddr, 0x1e); /* SMBIOS BCD Revision */ + ep_64bit = (SMBIOS_GET8(saddr, 0x3) == '3') ? true : false; + + if (ep_64bit) { + /* SMBIOS 3.0 (64-bit) Entry Point */ + smbios.length = SMBIOS_GET32(saddr, 0xc); /* Structure table maximum size */ + paddr = SMBIOS_GET64(saddr, 0x10); /* Structure table address */ + smbios.ver = 0; + smbios.count = 0; + } else { + /* SMBIOS 2.1 (32-bit) Entry Point */ + smbios.length = SMBIOS_GET16(saddr, 0x16); /* Structure Table Length */ + paddr = SMBIOS_GET32(saddr, 0x18); /* Structure Table Address */ + smbios.count = SMBIOS_GET16(saddr, 0x1c); /* No of SMBIOS Structures */ + smbios.ver = SMBIOS_GET8(saddr, 0x1e); /* SMBIOS BCD Revision */ + } if (smbios.ver != 0) { smbios.major = smbios.ver >> 4; @@ -464,8 +492,13 @@ smbios.ver = 0; } if (smbios.ver == 0) { - smbios.major = SMBIOS_GET8(saddr, 0x06);/* SMBIOS Major Version */ - smbios.minor = SMBIOS_GET8(saddr, 0x07);/* SMBIOS Minor Version */ + if (ep_64bit) { + smbios.major = SMBIOS_GET8(saddr, 0x07);/* SMBIOS Major Version */ + smbios.minor = SMBIOS_GET8(saddr, 0x08);/* SMBIOS Minor Version */ + } else { + smbios.major = SMBIOS_GET8(saddr, 0x06);/* SMBIOS Major Version */ + smbios.minor = SMBIOS_GET8(saddr, 0x07);/* SMBIOS Minor Version */ + } } smbios.ver = (smbios.major << 8) | smbios.minor; smbios.addr = PTOV(paddr); @@ -489,12 +522,17 @@ caddr_t dmi; size_t i; + if (smbios.addr != NULL) + return; + smbios_probe(addr); if (smbios.addr == NULL) return; for (dmi = smbios.addr, i = 0; - dmi < smbios.addr + smbios.length && i < smbios.count; i++) + dmi < smbios.addr + smbios.length && + (smbios.count == 0 || i < smbios.count); + i++) dmi = smbios_parse_table(dmi); sprintf(buf, "%d.%d", smbios.major, smbios.minor); Index: sys/amd64/conf/GENERIC =================================================================== --- sys/amd64/conf/GENERIC +++ sys/amd64/conf/GENERIC @@ -129,6 +129,7 @@ # Bus support. device acpi +device smbios options IOMMU device pci options PCI_HP # PCI-Express native HotPlug Index: sys/amd64/conf/MINIMAL =================================================================== --- sys/amd64/conf/MINIMAL +++ sys/amd64/conf/MINIMAL @@ -103,6 +103,7 @@ # Bus support. device acpi +device smbios options IOMMU device pci Index: sys/amd64/include/pc/bios.h =================================================================== --- sys/amd64/include/pc/bios.h +++ sys/amd64/include/pc/bios.h @@ -64,38 +64,6 @@ u_int32_t xattr; } __packed; -/* - * System Management BIOS - */ -#define SMBIOS_START 0xf0000 -#define SMBIOS_STEP 0x10 -#define SMBIOS_OFF 0 -#define SMBIOS_LEN 4 -#define SMBIOS_SIG "_SM_" - -struct smbios_eps { - uint8_t anchor_string[4]; /* '_SM_' */ - uint8_t checksum; - uint8_t length; - uint8_t major_version; - uint8_t minor_version; - uint16_t maximum_structure_size; - uint8_t entry_point_revision; - uint8_t formatted_area[5]; - uint8_t intermediate_anchor_string[5]; /* '_DMI_' */ - uint8_t intermediate_checksum; - uint16_t structure_table_length; - uint32_t structure_table_address; - uint16_t number_structures; - uint8_t BCD_revision; -}; - -struct smbios_structure_header { - uint8_t type; - uint8_t length; - uint16_t handle; -}; - #ifdef _KERNEL #define BIOS_PADDRTOVADDR(x) ((x) + KERNBASE) #define BIOS_VADDRTOPADDR(x) ((x) - KERNBASE) Index: sys/arm64/conf/GENERIC =================================================================== --- sys/arm64/conf/GENERIC +++ sys/arm64/conf/GENERIC @@ -383,6 +383,7 @@ options FDT device acpi +device smbios # DTBs makeoptions MODULES_EXTRA="dtb/allwinner dtb/freescale dtb/imx8 dtb/nvidia dtb/mv dtb/rockchip dtb/rpi" Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -3095,6 +3095,7 @@ dev/siis/siis.c optional siis pci dev/sis/if_sis.c optional sis pci dev/sk/if_sk.c optional sk pci +dev/smbios/smbios.c optional smbios dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus Index: sys/conf/files.x86 =================================================================== --- sys/conf/files.x86 +++ sys/conf/files.x86 @@ -293,7 +293,6 @@ x86/acpica/acpi_apm.c optional acpi x86/acpica/acpi_wakeup.c optional acpi x86/acpica/srat.c optional acpi -x86/bios/smbios.c optional smbios x86/bios/vpd.c optional vpd x86/cpufreq/est.c optional cpufreq x86/cpufreq/hwpstate_amd.c optional cpufreq Index: sys/dev/acpica/acpi_resource.c =================================================================== --- sys/dev/acpica/acpi_resource.c +++ sys/dev/acpica/acpi_resource.c @@ -496,6 +496,13 @@ acpi_MatchHid(handle, "ARMHC9FF") != ACPI_MATCHHID_NOMATCH) arc.ignore_producer_flag = true; + /* + * The DesignWare I2C Controller on Ampere Altra sets ResourceProducer on + * memory resources. + */ + if (acpi_MatchHid(handle, "APMC0D0F") != ACPI_MATCHHID_NOMATCH) + arc.ignore_producer_flag = true; + status = AcpiWalkResources(handle, "_CRS", acpi_parse_resource, &arc); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { printf("can't fetch resources for %s - %s\n", Index: sys/dev/ichiic/ig4_acpi.c =================================================================== --- sys/dev/ichiic/ig4_acpi.c +++ sys/dev/ichiic/ig4_acpi.c @@ -89,8 +89,16 @@ sc = device_get_softc(dev); sc->dev = dev; - /* All the HIDs matched are Atom SOCs. */ - sc->version = IG4_ATOM; + if (acpi_MatchHid(acpi_get_handle(dev), "APMC0D0F") != + ACPI_MATCHHID_NOMATCH) { + sc->version = IG4_EMAG; + } else { + /* + * All the other HIDs matched are compatible with Atom + * mode. + */ + sc->version = IG4_ATOM; + } sc->regs_rid = 0; sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->regs_rid, RF_ACTIVE); Index: sys/dev/ichiic/ig4_iic.c =================================================================== --- sys/dev/ichiic/ig4_iic.c +++ sys/dev/ichiic/ig4_iic.c @@ -91,8 +91,11 @@ * Ig4 hardware parameters except Haswell are taken from intel_lpss driver */ static const struct ig4_hw ig4iic_hw[] = { - [IG4_HASWELL] = { + [IG4_EMAG] = { .ic_clock_rate = 100, /* MHz */ + }, + [IG4_HASWELL] = { + .ic_clock_rate = 100, .sda_hold_time = 90, /* nsec */ .txfifo_depth = 32, .rxfifo_depth = 32, @@ -267,7 +270,7 @@ int error; int txlvl = -1; u_int count_us = 0; - u_int limit_us = 25000; /* 25ms */ + u_int limit_us = 1000000; /* 1sec */ for (;;) { /* @@ -801,7 +804,13 @@ elems = obj->Package.Elements; *scl_hcnt = elems[0].Integer.Value & IG4_SCL_CLOCK_MASK; *scl_lcnt = elems[1].Integer.Value & IG4_SCL_CLOCK_MASK; - *sda_hold = elems[2].Integer.Value & IG4_SDA_TX_HOLD_MASK; + if (elems[2].Integer.Value != 0) { + /* + * If the value in the table is zero, stick + * with value calculated earlier for sda_hold. + */ + *sda_hold = elems[2].Integer.Value & IG4_SDA_TX_HOLD_MASK; + } status = AE_OK; } Index: sys/dev/ichiic/ig4_var.h =================================================================== --- sys/dev/ichiic/ig4_var.h +++ sys/dev/ichiic/ig4_var.h @@ -44,6 +44,7 @@ #include "iicbus_if.h" enum ig4_vers { + IG4_EMAG, IG4_HASWELL, IG4_ATOM, IG4_SKYLAKE, Index: sys/dev/iicbus/iicsmb.c =================================================================== --- sys/dev/iicbus/iicsmb.c +++ sys/dev/iicbus/iicsmb.c @@ -455,7 +455,7 @@ int error; /* Have to do this because the command is split in two transfers. */ - error = iicbus_request_bus(parent, dev, IIC_WAIT); + error = iicbus_request_bus(parent, dev, IIC_WAIT | IIC_RECURSIVE); if (error == 0) error = TRANSFER_MSGS(dev, msgs); if (error == 0) { Index: sys/dev/ipmi/ipmi_isa.c =================================================================== --- sys/dev/ipmi/ipmi_isa.c +++ sys/dev/ipmi/ipmi_isa.c @@ -286,3 +286,4 @@ }; DRIVER_MODULE(ipmi_isa, isa, ipmi_isa_driver, ipmi_devclass, 0, 0); +MODULE_DEPEND(ipmi_isa, smbios, 1, 1, 1); Index: sys/dev/ipmi/ipmi_pci.c =================================================================== --- sys/dev/ipmi/ipmi_pci.c +++ sys/dev/ipmi/ipmi_pci.c @@ -179,6 +179,7 @@ }; DRIVER_MODULE(ipmi_pci, pci, ipmi_pci_driver, ipmi_devclass, 0, 0); +MODULE_DEPEND(ipmi_pci, smbios, 1, 1, 1); /* Native IPMI on PCI driver. */ Index: sys/dev/ipmi/ipmi_smbios.c =================================================================== --- sys/dev/ipmi/ipmi_smbios.c +++ sys/dev/ipmi/ipmi_smbios.c @@ -39,7 +39,10 @@ #include #include +#if defined(__amd64__) || defined(__i386__) #include +#endif +#include #ifdef LOCAL_MODULE #include @@ -84,8 +87,7 @@ MTX_SYSINIT(ipmi_info, &ipmi_info_mtx, "ipmi info", MTX_DEF); static void ipmi_smbios_probe(struct ipmi_get_info *); -static int smbios_cksum(struct smbios_eps *); -static void smbios_walk_table(uint8_t *, int, smbios_callback_t, +static void smbios_walk_table(uint8_t *, vm_size_t, smbios_callback_t, void *); static void smbios_ipmi_info(struct smbios_structure_header *, void *); @@ -144,11 +146,12 @@ } static void -smbios_walk_table(uint8_t *p, int entries, smbios_callback_t cb, void *arg) +smbios_walk_table(uint8_t *table, vm_size_t size, smbios_callback_t cb, void *arg) { struct smbios_structure_header *s; + uint8_t *p; - while (entries--) { + for (p = table; p < table + size;) { s = (struct smbios_structure_header *)p; cb(s, arg); @@ -157,8 +160,11 @@ * formatted area of this structure. */ p += s->length; - while (!(p[0] == 0 && p[1] == 0)) + while (!(p[0] == 0 && p[1] == 0)) { p++; + if (p >= table + size) + return; + } /* * Skip over the double-nul to the start of the next @@ -176,41 +182,23 @@ static void ipmi_smbios_probe(struct ipmi_get_info *info) { - struct smbios_eps *header; void *table; - u_int32_t addr; + vm_paddr_t table_paddr; + vm_size_t table_size; + int err; bzero(info, sizeof(struct ipmi_get_info)); - /* Find the SMBIOS table header. */ - addr = bios_sigsearch(SMBIOS_START, SMBIOS_SIG, SMBIOS_LEN, - SMBIOS_STEP, SMBIOS_OFF); - if (addr == 0) + err = smbios_get_structure_table(&table_paddr, &table_size); + if (err != 0) return; - /* - * Map the header. We first map a fixed size to get the actual - * length and then map it a second time with the actual length so - * we can verify the checksum. - */ - header = pmap_mapbios(addr, sizeof(struct smbios_eps)); - table = pmap_mapbios(addr, header->length); - pmap_unmapbios((vm_offset_t)header, sizeof(struct smbios_eps)); - header = table; - if (smbios_cksum(header) != 0) { - pmap_unmapbios((vm_offset_t)header, header->length); - return; - } + table = pmap_mapbios(table_paddr, table_size); - /* Now map the actual table and walk it looking for an IPMI entry. */ - table = pmap_mapbios(header->structure_table_address, - header->structure_table_length); - smbios_walk_table(table, header->number_structures, smbios_ipmi_info, - info); + smbios_walk_table(table, table_size, smbios_ipmi_info, info); /* Unmap everything. */ - pmap_unmapbios((vm_offset_t)table, header->structure_table_length); - pmap_unmapbios((vm_offset_t)header, header->length); + pmap_unmapbios((vm_offset_t)table, table_size); } /* @@ -248,19 +236,3 @@ return (info->iface_type != 0); } - -static int -smbios_cksum(struct smbios_eps *e) -{ - u_int8_t *ptr; - u_int8_t cksum; - int i; - - ptr = (u_int8_t *)e; - cksum = 0; - for (i = 0; i < e->length; i++) { - cksum += ptr[i]; - } - - return (cksum); -} Index: sys/dev/ipmi/ipmi_smbus.c =================================================================== --- sys/dev/ipmi/ipmi_smbus.c +++ sys/dev/ipmi/ipmi_smbus.c @@ -131,3 +131,8 @@ DRIVER_MODULE(ipmi_smbus, smbus, ipmi_smbus_driver, ipmi_devclass, 0, 0); MODULE_DEPEND(ipmi_smbus, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_DEPEND(ipmi_smbus, smbios, 1, 1, 1); +#if defined(__aarch64__) +MODULE_DEPEND(ipmi_smbus, iicsmb, 1, 1, 1); +MODULE_DEPEND(ipmi_smbus, ig4iic, 1, 1, 1); +#endif Index: sys/dev/ipmi/ipmi_ssif.c =================================================================== --- sys/dev/ipmi/ipmi_ssif.c +++ sys/dev/ipmi/ipmi_ssif.c @@ -297,7 +297,7 @@ len += count - 1; /* If this was the last block we are done. */ - if (ssif_buf[0] != 0xff) + if (ssif_buf[0] == 0xff) break; block++; } Index: sys/dev/smbios/smbios.h =================================================================== --- sys/dev/smbios/smbios.h +++ sys/dev/smbios/smbios.h @@ -29,40 +29,10 @@ * $FreeBSD$ */ -#ifndef _MACHINE_PC_BIOS_H_ -#define _MACHINE_PC_BIOS_H_ +#ifndef _SMBIOS_H_ +#define _SMBIOS_H_ -/* - * Int 15:E820 'SMAP' structure - */ -#define SMAP_SIG 0x534D4150 /* 'SMAP' */ - -#define SMAP_TYPE_MEMORY 1 -#define SMAP_TYPE_RESERVED 2 -#define SMAP_TYPE_ACPI_RECLAIM 3 -#define SMAP_TYPE_ACPI_NVS 4 -#define SMAP_TYPE_ACPI_ERROR 5 -#define SMAP_TYPE_DISABLED 6 -#define SMAP_TYPE_PMEM 7 -#define SMAP_TYPE_PRAM 12 - -#define SMAP_XATTR_ENABLED 0x00000001 -#define SMAP_XATTR_NON_VOLATILE 0x00000002 -#define SMAP_XATTR_MASK (SMAP_XATTR_ENABLED | SMAP_XATTR_NON_VOLATILE) - -struct bios_smap { - u_int64_t base; - u_int64_t length; - u_int32_t type; -} __packed; - -/* Structure extended to include extended attribute field in ACPI 3.0. */ -struct bios_smap_xattr { - u_int64_t base; - u_int64_t length; - u_int32_t type; - u_int32_t xattr; -} __packed; +int smbios_get_structure_table(vm_paddr_t *table, vm_size_t *size); /* * System Management BIOS @@ -72,6 +42,8 @@ #define SMBIOS_OFF 0 #define SMBIOS_LEN 4 #define SMBIOS_SIG "_SM_" +#define SMBIOS3_LEN 5 +#define SMBIOS3_SIG "_SM3_" struct smbios_eps { uint8_t anchor_string[4]; /* '_SM_' */ @@ -90,37 +62,23 @@ uint8_t BCD_revision; }; +struct smbios3_eps { + uint8_t anchor_string[5]; /* '_SM3_' */ + uint8_t checksum; + uint8_t length; + uint8_t major_version; + uint8_t minor_version; + uint8_t docrev; + uint8_t entry_point_revision; + uint8_t reserved; + uint32_t structure_table_max_size; + uint64_t structure_table_address; +}; + struct smbios_structure_header { uint8_t type; uint8_t length; uint16_t handle; }; -#ifdef _KERNEL -#define BIOS_PADDRTOVADDR(x) ((x) + KERNBASE) -#define BIOS_VADDRTOPADDR(x) ((x) - KERNBASE) - -struct bios_oem_signature { - char * anchor; /* search anchor string in BIOS memory */ - size_t offset; /* offset from anchor (may be negative) */ - size_t totlen; /* total length of BIOS string to copy */ -} __packed; - -struct bios_oem_range { - u_int from; /* shouldn't be below 0xe0000 */ - u_int to; /* shouldn't be above 0xfffff */ -} __packed; - -struct bios_oem { - struct bios_oem_range range; - struct bios_oem_signature signature[]; -} __packed; - -int bios_oem_strings(struct bios_oem *oem, u_char *buffer, size_t maxlen); -uint32_t bios_sigsearch(uint32_t start, u_char *sig, int siglen, int paralen, - int sigofs); -void bios_add_smap_entries(struct bios_smap *smapbase, u_int32_t smapsize, - vm_paddr_t *physmap, int *physmap_idx); -#endif - -#endif /* _MACHINE_PC_BIOS_H_ */ +#endif /* _SMBIOS_H_ */ Index: sys/dev/smbios/smbios.c =================================================================== --- sys/dev/smbios/smbios.c +++ sys/dev/smbios/smbios.c @@ -46,7 +46,12 @@ #include #include #include +#if defined(__amd64__) || defined(__i386__) #include +#endif +#include + +static struct smbios_softc *smbios; /* * System Management BIOS Reference Specification, v2.4 Final @@ -58,11 +63,15 @@ struct resource * res; int rid; - struct smbios_eps * eps; + union { + struct smbios_eps * eps; + struct smbios3_eps * eps3; + }; + bool eps_64bit; }; #define RES2EPS(res) ((struct smbios_eps *)rman_get_virtual(res)) -#define ADDR2EPS(addr) ((struct smbios_eps *)BIOS_PADDRTOVADDR(addr)) +#define RES2EPS3(res) ((struct smbios3_eps *)rman_get_virtual(res)) static devclass_t smbios_devclass; @@ -72,30 +81,61 @@ static int smbios_detach (device_t); static int smbios_modevent (module_t, int, void *); -static int smbios_cksum (struct smbios_eps *); +static bool smbios_eps_64bit(void *); +static int smbios_cksum (void *); static void smbios_identify (driver_t *driver, device_t parent) { + struct smbios3_eps *eps3; + struct smbios_eps *eps; device_t child; - u_int32_t addr; + vm_paddr_t addr; int length; int rid; + bool eps_64bit; if (!device_is_alive(parent)) return; - addr = bios_sigsearch(SMBIOS_START, SMBIOS_SIG, SMBIOS_LEN, - SMBIOS_STEP, SMBIOS_OFF); + if (resource_long_value("smbios3", 0, "mem", &addr) != 0) { +#if defined(__amd64__) || defined(__i386__) + addr = bios_sigsearch(SMBIOS_START, SMBIOS3_SIG, SMBIOS3_LEN, + SMBIOS_STEP, SMBIOS_OFF); +#else + addr = 0; +#endif + } + if (addr != 0) { + eps_64bit = true; + } else { + eps_64bit = false; + if (resource_long_value("smbios", 0, "mem", &addr) != 0) { +#if defined(__amd64__) || defined(__i386__) + addr = bios_sigsearch(SMBIOS_START, SMBIOS_SIG, SMBIOS_LEN, + SMBIOS_STEP, SMBIOS_OFF); +#else + addr = 0; +#endif + } + } + + if (addr != 0) { + if (eps_64bit) { + eps3 = pmap_mapbios(addr, 0x18); + length = eps3->length; + } else { + eps = pmap_mapbios(addr, 0x1f); + length = eps->length; + } rid = 0; - length = ADDR2EPS(addr)->length; - if (length != 0x1f) { + if (!eps_64bit && length != 0x1f) { u_int8_t major, minor; - major = ADDR2EPS(addr)->major_version; - minor = ADDR2EPS(addr)->minor_version; + major = eps->major_version; + minor = eps->minor_version; /* SMBIOS v2.1 implementation might use 0x1e. */ if (length == 0x1e && major == 2 && minor == 1) @@ -108,6 +148,11 @@ device_set_driver(child, driver); bus_set_resource(child, SYS_RES_MEMORY, rid, addr, length); device_set_desc(child, "System Management BIOS"); + + if (eps_64bit) + pmap_unmapbios((vm_offset_t)eps3, 0x18); + else + pmap_unmapbios((vm_offset_t)eps, 0x1f); } return; @@ -129,7 +174,7 @@ goto bad; } - if (smbios_cksum(RES2EPS(res))) { + if (smbios_cksum(rman_get_virtual(res))) { device_printf(dev, "SMBIOS checksum failed.\n"); error = ENXIO; goto bad; @@ -159,16 +204,24 @@ error = ENOMEM; goto bad; } - sc->eps = RES2EPS(sc->res); - - device_printf(dev, "Version: %u.%u", - sc->eps->major_version, sc->eps->minor_version); - if (bcd2bin(sc->eps->BCD_revision)) - printf(", BCD Revision: %u.%u", - bcd2bin(sc->eps->BCD_revision >> 4), - bcd2bin(sc->eps->BCD_revision & 0x0f)); + sc->eps_64bit = smbios_eps_64bit(rman_get_virtual(sc->res)); + + if (sc->eps_64bit) { + sc->eps3 = RES2EPS3(sc->res); + device_printf(dev, "Version: %u.%u", + sc->eps3->major_version, sc->eps3->minor_version); + } else { + sc->eps = RES2EPS(sc->res); + device_printf(dev, "Version: %u.%u", + sc->eps->major_version, sc->eps->minor_version); + if (bcd2bin(sc->eps->BCD_revision)) + printf(", BCD Revision: %u.%u", + bcd2bin(sc->eps->BCD_revision >> 4), + bcd2bin(sc->eps->BCD_revision & 0x0f)); + } printf("\n"); + smbios = sc; return (0); bad: if (sc->res) @@ -181,6 +234,7 @@ { struct smbios_softc *sc; + smbios = NULL; sc = device_get_softc(dev); if (sc->res) @@ -189,6 +243,23 @@ return (0); } +int +smbios_get_structure_table(vm_paddr_t *table, vm_size_t *size) +{ + + if (smbios == NULL) + return (ENXIO); + if (smbios->eps_64bit) { + *table = smbios->eps3->structure_table_address; + *size = smbios->eps3->structure_table_max_size; + } else { + *table = smbios->eps->structure_table_address; + *size = smbios->eps->structure_table_length; + } + return (0); +} + + static int smbios_modevent (mod, what, arg) module_t mod; @@ -234,16 +305,35 @@ DRIVER_MODULE(smbios, nexus, smbios_driver, smbios_devclass, smbios_modevent, 0); MODULE_VERSION(smbios, 1); +static bool +smbios_eps_64bit (void *v) +{ + struct smbios3_eps *e; + + e = (struct smbios3_eps *)v; + return (memcmp(e->anchor_string, SMBIOS3_SIG, SMBIOS3_LEN) == 0); +} + static int -smbios_cksum (struct smbios_eps *e) +smbios_cksum (void *v) { + struct smbios3_eps *eps3; + struct smbios_eps *eps; u_int8_t *ptr; u_int8_t cksum; + u_int8_t length; int i; - ptr = (u_int8_t *)e; + if (smbios_eps_64bit(v)) { + eps3 = (struct smbios3_eps *)v; + length = eps3->length; + } else { + eps = (struct smbios_eps *)v; + length = eps->length; + } + ptr = (u_int8_t *)v; cksum = 0; - for (i = 0; i < e->length; i++) { + for (i = 0; i < length; i++) { cksum += ptr[i]; } Index: sys/i386/conf/GENERIC =================================================================== --- sys/i386/conf/GENERIC +++ sys/i386/conf/GENERIC @@ -115,6 +115,7 @@ # Bus support. device acpi +device smbios device pci options PCI_HP # PCI-Express native HotPlug options PCI_IOV # PCI SR-IOV support Index: sys/i386/conf/MINIMAL =================================================================== --- sys/i386/conf/MINIMAL +++ sys/i386/conf/MINIMAL @@ -104,6 +104,7 @@ # Bus support. device acpi +device smbios device pci # atkbdc0 controls both the keyboard and the PS/2 mouse Index: sys/i386/include/pc/bios.h =================================================================== --- sys/i386/include/pc/bios.h +++ sys/i386/include/pc/bios.h @@ -234,38 +234,6 @@ u_int32_t xattr; } __packed; -/* - * System Management BIOS - */ -#define SMBIOS_START 0xf0000 -#define SMBIOS_STEP 0x10 -#define SMBIOS_OFF 0 -#define SMBIOS_LEN 4 -#define SMBIOS_SIG "_SM_" - -struct smbios_eps { - uint8_t anchor_string[4]; /* '_SM_' */ - uint8_t checksum; - uint8_t length; - uint8_t major_version; - uint8_t minor_version; - uint16_t maximum_structure_size; - uint8_t entry_point_revision; - uint8_t formatted_area[5]; - uint8_t intermediate_anchor_string[5]; /* '_DMI_' */ - uint8_t intermediate_checksum; - uint16_t structure_table_length; - uint32_t structure_table_address; - uint16_t number_structures; - uint8_t BCD_revision; -}; - -struct smbios_structure_header { - uint8_t type; - uint8_t length; - uint16_t handle; -}; - #ifdef _KERNEL #define BIOS_PADDRTOVADDR(x) ((x) + PMAP_MAP_LOW) #define BIOS_VADDRTOPADDR(x) ((x) - PMAP_MAP_LOW) Index: sys/modules/bios/smbios/Makefile =================================================================== --- sys/modules/bios/smbios/Makefile +++ sys/modules/bios/smbios/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ # -.PATH: ${SRCTOP}/sys/x86/bios +.PATH: ${SRCTOP}/sys/dev/smbios KMOD= smbios SRCS= smbios.c \ Index: sys/modules/ipmi/Makefile =================================================================== --- sys/modules/ipmi/Makefile +++ sys/modules/ipmi/Makefile @@ -14,12 +14,17 @@ SRCS+= ipmi_acpi.c SRCS+= opt_acpi.h SRCS+= acpi_if.h +SRCS+= ipmi_smbios.c +SRCS+= ipmi_ssif.c +SRCS+= ipmi_pci.c +SRCS+= ipmi_smbus.c +SRCS+= pci_if.h +SRCS+= smbus_if.h .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" -SRCS+= ipmi_smbios.c ipmi_ssif.c -SRCS+= ipmi_isa.c ipmi_pci.c ipmi_smbus.c -SRCS+= isa_if.h pci_if.h smbus_if.h +SRCS+= ipmi_isa.c +SRCS+= isa_if.h SUBDIR+= ipmi_linux