From: Corey Minyard cminyard@mvista.com
An IPMI device is being added to the qemu code, and it has an SMBIOS entry to describe the interface characteristics. So add the SMBIOS entry to the BIOS so it can handle this.
Signed-off-by: Corey Minyard cminyard@mvista.com --- Makefile | 2 +- src/ipmi.c | 31 +++++++++++++++++++++++++++++++ src/ipmi.h | 32 ++++++++++++++++++++++++++++++++ src/post.c | 2 ++ src/smbios.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/smbios.h | 12 ++++++++++++ src/util.h | 5 +++++ 7 files changed, 138 insertions(+), 1 deletions(-) create mode 100644 src/ipmi.c create mode 100644 src/ipmi.h
diff --git a/Makefile b/Makefile index dfdec5c..1b6eb96 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ SRCBOTH=misc.c stacks.c pmm.c output.c util.c block.c floppy.c ata.c mouse.c \ pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \ usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \ virtio-ring.c virtio-pci.c virtio-blk.c virtio-scsi.c apm.c ahci.c \ - usb-uas.c lsi-scsi.c + usb-uas.c lsi-scsi.c ipmi.c SRC16=$(SRCBOTH) system.c disk.c font.c SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \ acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \ diff --git a/src/ipmi.c b/src/ipmi.c new file mode 100644 index 0000000..bedcdc0 --- /dev/null +++ b/src/ipmi.c @@ -0,0 +1,31 @@ +// IPMI setup information +// +// Copyright (C) 2012 Corey Minyard cminyard@mvista.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "ipmi.h" +#include "util.h" + +struct ipmi_info ipmi_info VAR16VISIBLE; + +void +ipmi_setup(void) +{ + u8 *data; + int size; + + data = romfile_loadfile("etc/ipmi", &size); + if (!data || (size < sizeof(ipmi_info))) { + ipmi_info.interface = 0; /* Disable */ + return; + } + + if (size > sizeof(ipmi_info)) + size = sizeof(ipmi_info); + + memcpy(&ipmi_info, data, size); + free(data); + + ipmi_info.base_addr = le64_to_cpu(ipmi_info.base_addr); +} diff --git a/src/ipmi.h b/src/ipmi.h new file mode 100644 index 0000000..85fdf42 --- /dev/null +++ b/src/ipmi.h @@ -0,0 +1,32 @@ +// IPMI setup information +// +// Copyright (C) 2012 Corey Minyard cminyard@mvista.com +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#ifndef __IPMI_H +#define __IPMI_H + +#include "config.h" // CONFIG_COREBOOT +#include "types.h" + +#define IPMI_MEM_SPACE 0 +#define IPMI_IO_SPACE 1 + +struct ipmi_info { + u8 str_version; /* Version of this structure */ + u8 interface; + u8 reg_space; + u8 reg_spacing; + u8 slave_addr; + u8 irq; + u8 version; + u8 reserved1; + u64 base_addr; +} PACKED; + +extern struct ipmi_info ipmi_info; + +void ipmi_setup(void); + +#endif diff --git a/src/post.c b/src/post.c index 0f31b4c..69834b6 100644 --- a/src/post.c +++ b/src/post.c @@ -28,6 +28,7 @@ #include "virtio-blk.h" // virtio_blk_setup #include "virtio-scsi.h" // virtio_scsi_setup #include "lsi-scsi.h" // lsi_scsi_setup +#include "ipmi.h" // ipmi_setup
/**************************************************************** @@ -255,6 +256,7 @@ maininit(void) pnp_setup(); kbd_setup(); mouse_setup(); + ipmi_setup(); init_bios_tables();
// Run vga option rom diff --git a/src/smbios.c b/src/smbios.c index fc84aad..f480a8d 100644 --- a/src/smbios.c +++ b/src/smbios.c @@ -8,6 +8,7 @@ #include "util.h" // dprintf #include "paravirt.h" // qemu_cfg_smbios_load_field #include "smbios.h" // struct smbios_entry_point +#include "ipmi.h" // struct ipmi_info
struct smbios_entry_point *SMBiosAddr;
@@ -422,6 +423,58 @@ smbios_init_type_32(void *start) return start+2; }
+/* Type 38 -- System Boot Information */ +static void * +smbios_init_type_38(void *start, struct ipmi_info *info) +{ + struct smbios_type_38 *p = (struct smbios_type_38 *)start; + + p->header.type = 38; + p->header.length = sizeof(struct smbios_type_38); + p->header.handle = 0x2100; + + p->interface_type = info->interface; + + p->base_addr = info->base_addr & ~1ULL; + /* Bit 0 goes into a special place */ + p->base_addr_mod_and_irq_info = (info->base_addr & 1) << 4; + + switch (info->reg_spacing) { + case 4: + p->base_addr_mod_and_irq_info |= (1 << 6); + break; + case 16: + p->base_addr_mod_and_irq_info |= (2 << 6); + break; + case 1: + default: + /* zero is the right value */ + break; + } + + if (info->reg_space) + p->base_addr |= 1; /* I/O space */ + + if (info->version) + p->ipmi_version = info->version; + else + p->ipmi_version = 0x15; + + if (info->slave_addr) + p->i2c_slave_addr = info->slave_addr; + else + p->i2c_slave_addr = 0x20; + + p->nv_storage_dev_addr = 0; + + p->interrupt_number = info->irq; + + start += sizeof(struct smbios_type_38); + *((u16 *)start) = 0; + + return start+2; +} + /* Type 127 -- End of Table */ static void * smbios_init_type_127(void *start) @@ -510,6 +563,8 @@ smbios_init(void) }
add_struct(32, p); + if (ipmi_info.interface) + add_struct(38, p, &ipmi_info); /* Add any remaining provided entries before the end marker */ for (i = 0; i < 256; i++) qemu_cfg_smbios_load_external(i, &p, &nr_structs, &max_struct_size, diff --git a/src/smbios.h b/src/smbios.h index 9d54e80..1935335 100644 --- a/src/smbios.h +++ b/src/smbios.h @@ -160,6 +160,18 @@ struct smbios_type_32 { u8 boot_status; } PACKED;
+/* SMBIOS type 38 - IPMI Information */ +struct smbios_type_38 { + struct smbios_structure_header header; + u8 interface_type; + u8 ipmi_version; + u8 i2c_slave_addr; + u8 nv_storage_dev_addr; + u64 base_addr; + u8 base_addr_mod_and_irq_info; + u8 interrupt_number; +} PACKED; + /* SMBIOS type 127 -- End-of-table */ struct smbios_type_127 { struct smbios_structure_header header; diff --git a/src/util.h b/src/util.h index ef8ec7c..415f518 100644 --- a/src/util.h +++ b/src/util.h @@ -134,6 +134,11 @@ static inline u32 le32_to_cpu(u32 x) return x; }
+static inline u64 le64_to_cpu(u64 x) +{ + return x; +} + static inline u32 getesp(void) { u32 esp; asm("movl %%esp, %0" : "=rm"(esp));
On Tue, Jul 31, 2012 at 12:30:36PM -0500, minyard@acm.org wrote:
From: Corey Minyard cminyard@mvista.com
An IPMI device is being added to the qemu code, and it has an SMBIOS entry to describe the interface characteristics. So add the SMBIOS entry to the BIOS so it can handle this.
Hi,
This patch creates a binary ipmi_info struct with IPMI info, and then modifies SeaBIOS to take that struct and translate it into a binary smbios struct. If the ultimate goal is to create an smbios struct, then just create that and send it to SeaBIOS. This has the added benefit that there is no need to modify SeaBIOS as there is already a mechanism to pass smbios tables via fw_cfg (see qemu_cfg_smbios_load_external).
-Kevin
On 07/31/2012 07:51 PM, Kevin O'Connor wrote:
On Tue, Jul 31, 2012 at 12:30:36PM -0500, minyard@acm.org wrote:
From: Corey Minyard cminyard@mvista.com
An IPMI device is being added to the qemu code, and it has an SMBIOS entry to describe the interface characteristics. So add the SMBIOS entry to the BIOS so it can handle this.
Hi,
This patch creates a binary ipmi_info struct with IPMI info, and then modifies SeaBIOS to take that struct and translate it into a binary smbios struct. If the ultimate goal is to create an smbios struct, then just create that and send it to SeaBIOS. This has the added benefit that there is no need to modify SeaBIOS as there is already a mechanism to pass smbios tables via fw_cfg (see qemu_cfg_smbios_load_external).
Sigh. That's what I originally did. There are issues in qemu with doing this from a driver; the SMBIOS entries are already fixed before the driver initialization code runs. I did some changes to fix this, but the qemu folks suggested that I send it over with the firmware interface and do it in the BIOS.
There are some advantages to doing this with a different interface. This way, it's available to other firmware types; OF and uboot could populate device trees from this interface. And SeaBIOS could use the same information to populate some ACPI PNP interfaces that can also be used to configure the driver.
Thanks,
-corey