[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