[SeaBIOS] [PATCH] Add an IPMI SMBIOS entry
Gleb Natapov
gleb at redhat.com
Tue Jul 31 09:10:56 CEST 2012
On Mon, Jul 30, 2012 at 09:57:47PM -0500, minyard at acm.org wrote:
> From: Corey Minyard <cminyard at 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 at mvista.com>
> ---
> Makefile | 2 +-
> src/ipmi.c | 16 ++++++++++++++++
> src/ipmi.h | 27 +++++++++++++++++++++++++++
> src/paravirt.c | 18 ++++++++++++++++++
> src/paravirt.h | 9 +++++++++
> src/post.c | 2 ++
> src/smbios.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> src/smbios.h | 12 ++++++++++++
> src/util.h | 5 +++++
> 9 files changed, 144 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..7521a8b
> --- /dev/null
> +++ b/src/ipmi.c
> @@ -0,0 +1,16 @@
> +// IPMI setup information
> +//
> +// Copyright (C) 2012 Corey Minyard <cminyard at mvista.com>
> +//
> +// This file may be distributed under the terms of the GNU LGPLv3 license.
> +
> +#include "ipmi.h"
> +#include "paravirt.h"
> +
> +struct ipmi_info ipmi_info;
> +
> +void
> +ipmi_setup(void)
> +{
> + qemu_cfg_load_ipmi(&ipmi_info);
> +}
> diff --git a/src/ipmi.h b/src/ipmi.h
> new file mode 100644
> index 0000000..b0cf61e
> --- /dev/null
> +++ b/src/ipmi.h
> @@ -0,0 +1,27 @@
> +// IPMI setup information
> +//
> +// Copyright (C) 2012 Corey Minyard <cminyard at 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"
> +
> +struct ipmi_info {
> + u64 base_addr;
> + u8 interface;
> + u8 reg_space;
> + u8 reg_spacing;
> + u8 slave_addr;
> + u8 irq;
> + u8 version;
> +};
> +
> +extern struct ipmi_info ipmi_info;
> +
> +void ipmi_setup(void);
> +
> +#endif
> diff --git a/src/paravirt.c b/src/paravirt.c
> index 2a98d53..4986cfb 100644
> --- a/src/paravirt.c
> +++ b/src/paravirt.c
> @@ -148,6 +148,24 @@ void* qemu_cfg_e820_load_next(void *addr)
> return addr;
> }
>
> +void qemu_cfg_load_ipmi(struct ipmi_info *info)
> +{
> + qemu_cfg_read_entry(&info->interface, QEMU_CFG_IPMI_INTERFACE, sizeof(u8));
> + qemu_cfg_read_entry(&info->base_addr, QEMU_CFG_IPMI_BASE_ADDR, sizeof(u64));
> +
> + if ((info->interface == 0) || (info->base_addr == 0))
> + return;
> +
> + info->base_addr = le64_to_cpu(info->base_addr);
> + qemu_cfg_read_entry(&info->reg_spacing, QEMU_CFG_IPMI_REG_SPACING,
> + sizeof(u8));
> + qemu_cfg_read_entry(&info->reg_space, QEMU_CFG_IPMI_REG_SPACE, sizeof(u8));
> + qemu_cfg_read_entry(&info->version, QEMU_CFG_IPMI_VERSION, sizeof(u8));
> + qemu_cfg_read_entry(&info->slave_addr, QEMU_CFG_IPMI_SLAVE_ADDR,
> + sizeof(u8));
> + qemu_cfg_read_entry(&info->irq, QEMU_CFG_IPMI_IRQ, sizeof(u8));
> +}
> +
> struct smbios_header {
> u16 length;
> u8 type;
> diff --git a/src/paravirt.h b/src/paravirt.h
> index a284c41..b14e41b 100644
> --- a/src/paravirt.h
> +++ b/src/paravirt.h
> @@ -3,6 +3,7 @@
>
> #include "config.h" // CONFIG_COREBOOT
> #include "util.h"
> +#include "ipmi.h" // struct ipmi_info
>
> /* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx. It
> * should be used to determine that a VM is running under KVM.
> @@ -35,6 +36,13 @@ static inline int kvm_para_available(void)
> #define QEMU_CFG_BOOT_MENU 0x0e
> #define QEMU_CFG_MAX_CPUS 0x0f
> #define QEMU_CFG_FILE_DIR 0x19
> +#define QEMU_CFG_IPMI_INTERFACE 0x30
> +#define QEMU_CFG_IPMI_BASE_ADDR 0x31
> +#define QEMU_CFG_IPMI_REG_SPACE 0x32
> +#define QEMU_CFG_IPMI_REG_SPACING 0x33
> +#define QEMU_CFG_IPMI_SLAVE_ADDR 0x34
> +#define QEMU_CFG_IPMI_IRQ 0x35
> +#define QEMU_CFG_IPMI_VERSION 0x36
Better to add _one_ fw_cfg entry that contains all of the info. But I am
sure Kevin will want this to be passed through file interface anyway.
> #define QEMU_CFG_ARCH_LOCAL 0x8000
> #define QEMU_CFG_ACPI_TABLES (QEMU_CFG_ARCH_LOCAL + 0)
> #define QEMU_CFG_SMBIOS_ENTRIES (QEMU_CFG_ARCH_LOCAL + 1)
> @@ -64,6 +72,7 @@ struct e820_reservation {
> };
> u32 qemu_cfg_e820_entries(void);
> void* qemu_cfg_e820_load_next(void *addr);
> +void qemu_cfg_load_ipmi(struct ipmi_info *info);
> void qemu_cfg_romfile_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..9576c02 100644
> --- a/src/smbios.c
> +++ b/src/smbios.c
> @@ -422,6 +422,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 +562,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));
> --
> 1.7.4.1
>
>
> _______________________________________________
> SeaBIOS mailing list
> SeaBIOS at seabios.org
> http://www.seabios.org/mailman/listinfo/seabios
--
Gleb.
More information about the SeaBIOS
mailing list