2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-11-26 03:09:12 +00:00

[efi] Use EFI-native mechanism for accessing SMBIOS table

EFI provides a copy of the SMBIOS table accessible via the EFI system
table, which we should use instead of manually scanning through the
F000:0000 segment.
This commit is contained in:
Michael Brown 2008-12-04 23:09:48 +00:00
parent 045a22764a
commit 29480dd715
15 changed files with 376 additions and 180 deletions

View File

@ -58,7 +58,7 @@ SRCDIRS += drivers/block
SRCDIRS += drivers/nvs
SRCDIRS += drivers/bitbash
SRCDIRS += drivers/infiniband
SRCDIRS += interface/pxe interface/efi
SRCDIRS += interface/pxe interface/efi interface/smbios
SRCDIRS += tests
SRCDIRS += crypto crypto/axtls crypto/matrixssl
SRCDIRS += hci hci/commands hci/tui

View File

@ -9,10 +9,9 @@
#define ERRFILE_memtop_umalloc ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 )
#define ERRFILE_memmap ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 )
#define ERRFILE_pnpbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 )
#define ERRFILE_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
#define ERRFILE_bios_smbios ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 )
#define ERRFILE_biosint ( ERRFILE_ARCH | ERRFILE_CORE | 0x00040000 )
#define ERRFILE_int13 ( ERRFILE_ARCH | ERRFILE_CORE | 0x00050000 )
#define ERRFILE_smbios_settings ( ERRFILE_ARCH | ERRFILE_CORE | 0x00060000 )
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )

View File

@ -0,0 +1,12 @@
#ifndef _BITS_SMBIOS_H
#define _BITS_SMBIOS_H
/** @file
*
* i386-specific SMBIOS API implementations
*
*/
#include <gpxe/bios_smbios.h>
#endif /* _BITS_SMBIOS_H */

View File

@ -0,0 +1,16 @@
#ifndef _GPXE_BIOS_SMBIOS_H
#define _GPXE_BIOS_SMBIOS_H
/** @file
*
* Standard PC-BIOS SMBIOS interface
*
*/
#ifdef SMBIOS_PCBIOS
#define SMBIOS_PREFIX_pcbios
#else
#define SMBIOS_PREFIX_pcbios __pcbios_
#endif
#endif /* _GPXE_BIOS_SMBIOS_H */

View File

@ -1,60 +0,0 @@
#ifndef _SMBIOS_H
#define _SMBIOS_H
/** @file
*
* System Management BIOS
*/
#include <stdint.h>
/** An SMBIOS structure header */
struct smbios_header {
/** Type */
uint8_t type;
/** Length */
uint8_t len;
/** Handle */
uint16_t handle;
} __attribute__ (( packed ));
/** SMBIOS structure descriptor */
struct smbios_structure {
/** Copy of SMBIOS structure header */
struct smbios_header header;
/** Offset of structure within SMBIOS */
size_t offset;
/** Length of strings section */
size_t strings_len;
};
/** SMBIOS system information structure */
struct smbios_system_information {
/** SMBIOS structure header */
struct smbios_header header;
/** Manufacturer string */
uint8_t manufacturer;
/** Product string */
uint8_t product;
/** Version string */
uint8_t version;
/** Serial number string */
uint8_t serial;
/** UUID */
uint8_t uuid[16];
/** Wake-up type */
uint8_t wakeup;
} __attribute__ (( packed ));
/** SMBIOS system information structure type */
#define SMBIOS_TYPE_SYSTEM_INFORMATION 1
extern int find_smbios_structure ( unsigned int type,
struct smbios_structure *structure );
extern int read_smbios_structure ( struct smbios_structure *structure,
void *data, size_t len );
extern int read_smbios_string ( struct smbios_structure *structure,
unsigned int index,
void *data, size_t len );
#endif /* _SMBIOS_H */

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <gpxe/uaccess.h>
#include <gpxe/smbios.h>
#include <realmode.h>
#include <pnpbios.h>
/** @file
*
* System Management BIOS
*
*/
/**
* Find SMBIOS
*
* @v smbios SMBIOS entry point descriptor structure to fill in
* @ret rc Return status code
*/
static int bios_find_smbios ( struct smbios *smbios ) {
union {
struct smbios_entry entry;
uint8_t bytes[256]; /* 256 is maximum length possible */
} u;
static unsigned int offset = 0;
size_t len;
unsigned int i;
uint8_t sum;
/* Try to find SMBIOS */
for ( ; offset < 0x10000 ; offset += 0x10 ) {
/* Read start of header and verify signature */
copy_from_real ( &u.entry, BIOS_SEG, offset,
sizeof ( u.entry ));
if ( u.entry.signature != SMBIOS_SIGNATURE )
continue;
/* Read whole header and verify checksum */
len = u.entry.len;
copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
for ( i = 0 , sum = 0 ; i < len ; i++ ) {
sum += u.bytes[i];
}
if ( sum != 0 ) {
DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n",
BIOS_SEG, offset, sum );
continue;
}
/* Fill result structure */
DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n",
u.entry.major, u.entry.minor, BIOS_SEG, offset );
smbios->address = phys_to_user ( u.entry.smbios_address );
smbios->len = u.entry.smbios_len;
smbios->count = u.entry.smbios_count;
return 0;
}
DBG ( "No SMBIOS found\n" );
return -ENODEV;
}
PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios );

View File

@ -14,6 +14,7 @@
#define TIMER_EFI
#define NAP_EFIX86
#define UMALLOC_EFI
#define SMBIOS_EFI
#define IMAGE_EFI /* EFI image support */

View File

@ -14,6 +14,7 @@
#define CONSOLE_PCBIOS
#define NAP_PCBIOS
#define UMALLOC_MEMTOP
#define SMBIOS_PCBIOS
#define IMAGE_ELF /* ELF image support */
#define IMAGE_MULTIBOOT /* MultiBoot image support */

View File

@ -0,0 +1,34 @@
/** @file
GUIDs used to locate the SMBIOS tables in the UEFI 2.0 system table.
This GUID in the system table is the only legal way to search for and
locate the SMBIOS tables. Do not search the 0xF0000 segment to find SMBIOS
tables.
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@par Revision Reference:
GUIDs defined in UEFI 2.0 spec.
**/
#ifndef __SMBIOS_GUID_H__
#define __SMBIOS_GUID_H__
#define EFI_SMBIOS_TABLE_GUID \
{ \
0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
}
#define SMBIOS_TABLE_GUID EFI_SMBIOS_TABLE_GUID
extern EFI_GUID gEfiSmbiosTableGuid;
#endif

View File

@ -0,0 +1,16 @@
#ifndef _GPXE_EFI_SMBIOS_H
#define _GPXE_EFI_SMBIOS_H
/** @file
*
* gPXE SMBIOS API for EFI
*
*/
#ifdef SMBIOS_EFI
#define SMBIOS_PREFIX_efi
#else
#define SMBIOS_PREFIX_efi __efi_
#endif
#endif /* _GPXE_EFI_SMBIOS_H */

View File

@ -164,6 +164,9 @@
#define ERRFILE_iscsiboot ( ERRFILE_OTHER | 0x000f0000 )
#define ERRFILE_efi_pci ( ERRFILE_OTHER | 0x00100000 )
#define ERRFILE_efi_snp ( ERRFILE_OTHER | 0x00110000 )
#define ERRFILE_smbios ( ERRFILE_OTHER | 0x00120000 )
#define ERRFILE_smbios_settings ( ERRFILE_OTHER | 0x00130000 )
#define ERRFILE_efi_smbios ( ERRFILE_OTHER | 0x00140000 )
/** @} */

140
src/include/gpxe/smbios.h Normal file
View File

@ -0,0 +1,140 @@
#ifndef _GPXE_SMBIOS_H
#define _GPXE_SMBIOS_H
/** @file
*
* System Management BIOS
*
*/
#include <stdint.h>
#include <gpxe/api.h>
#include <config/general.h>
#include <gpxe/uaccess.h>
/**
* Provide an SMBIOS API implementation
*
* @v _prefix Subsystem prefix
* @v _api_func API function
* @v _func Implementing function
*/
#define PROVIDE_SMBIOS( _subsys, _api_func, _func ) \
PROVIDE_SINGLE_API ( SMBIOS_PREFIX_ ## _subsys, _api_func, _func )
/* Include all architecture-independent SMBIOS API headers */
#include <gpxe/efi/efi_smbios.h>
/* Include all architecture-dependent SMBIOS API headers */
#include <bits/smbios.h>
/** Signature for SMBIOS entry point */
#define SMBIOS_SIGNATURE \
( ( '_' << 0 ) + ( 'S' << 8 ) + ( 'M' << 16 ) + ( '_' << 24 ) )
/**
* SMBIOS entry point
*
* This is the single table which describes the list of SMBIOS
* structures. It is located by scanning through the BIOS segment.
*/
struct smbios_entry {
/** Signature
*
* Must be equal to SMBIOS_SIGNATURE
*/
uint32_t signature;
/** Checksum */
uint8_t checksum;
/** Length */
uint8_t len;
/** Major version */
uint8_t major;
/** Minor version */
uint8_t minor;
/** Maximum structure size */
uint16_t max;
/** Entry point revision */
uint8_t revision;
/** Formatted area */
uint8_t formatted[5];
/** DMI Signature */
uint8_t dmi_signature[5];
/** DMI checksum */
uint8_t dmi_checksum;
/** Structure table length */
uint16_t smbios_len;
/** Structure table address */
uint32_t smbios_address;
/** Number of SMBIOS structures */
uint16_t smbios_count;
/** BCD revision */
uint8_t bcd_revision;
} __attribute__ (( packed ));
/** An SMBIOS structure header */
struct smbios_header {
/** Type */
uint8_t type;
/** Length */
uint8_t len;
/** Handle */
uint16_t handle;
} __attribute__ (( packed ));
/** SMBIOS structure descriptor */
struct smbios_structure {
/** Copy of SMBIOS structure header */
struct smbios_header header;
/** Offset of structure within SMBIOS */
size_t offset;
/** Length of strings section */
size_t strings_len;
};
/** SMBIOS system information structure */
struct smbios_system_information {
/** SMBIOS structure header */
struct smbios_header header;
/** Manufacturer string */
uint8_t manufacturer;
/** Product string */
uint8_t product;
/** Version string */
uint8_t version;
/** Serial number string */
uint8_t serial;
/** UUID */
uint8_t uuid[16];
/** Wake-up type */
uint8_t wakeup;
} __attribute__ (( packed ));
/** SMBIOS system information structure type */
#define SMBIOS_TYPE_SYSTEM_INFORMATION 1
/**
* SMBIOS entry point descriptor
*
* This contains the information from the SMBIOS entry point that we
* care about.
*/
struct smbios {
/** Start of SMBIOS structures */
userptr_t address;
/** Length of SMBIOS structures */
size_t len;
/** Number of SMBIOS structures */
unsigned int count;
};
extern int find_smbios ( struct smbios *smbios );
extern int find_smbios_structure ( unsigned int type,
struct smbios_structure *structure );
extern int read_smbios_structure ( struct smbios_structure *structure,
void *data, size_t len );
extern int read_smbios_string ( struct smbios_structure *structure,
unsigned int index,
void *data, size_t len );
#endif /* _GPXE_SMBIOS_H */

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <errno.h>
#include <gpxe/smbios.h>
#include <gpxe/efi/efi.h>
#include <gpxe/efi/Guid/SmBios.h>
/** @file
*
* gPXE SMBIOS API for EFI
*
*/
/** SMBIOS configuration table */
static struct smbios_entry *smbios_entry;
EFI_USE_TABLE ( EFI_SMBIOS_TABLE, &smbios_entry, 0 );
/**
* Find SMBIOS
*
* @v smbios SMBIOS entry point descriptor structure to fill in
* @ret rc Return status code
*/
static int efi_find_smbios ( struct smbios *smbios ) {
if ( ! smbios_entry ) {
DBG ( "No SMBIOS table provided\n" );
return -ENODEV;
}
if ( smbios_entry->signature != SMBIOS_SIGNATURE ) {
DBG ( "Invalid SMBIOS signature\n" );
return -ENODEV;
}
smbios->address = phys_to_user ( smbios_entry->smbios_address );
smbios->len = smbios_entry->smbios_len;
smbios->count = smbios_entry->smbios_count;
DBG ( "Found SMBIOS v%d.%d entry point at %p (%x+%zx)\n",
smbios_entry->major, smbios_entry->minor, smbios_entry,
smbios_entry->smbios_address, smbios->len );
return 0;
}
PROVIDE_SMBIOS ( efi, find_smbios, efi_find_smbios );

View File

@ -21,9 +21,7 @@
#include <errno.h>
#include <assert.h>
#include <gpxe/uaccess.h>
#include <realmode.h>
#include <pnpbios.h>
#include <smbios.h>
#include <gpxe/smbios.h>
/** @file
*
@ -31,123 +29,11 @@
*
*/
/** Signature for SMBIOS entry point */
#define SMBIOS_SIGNATURE \
( ( '_' << 0 ) + ( 'S' << 8 ) + ( 'M' << 16 ) + ( '_' << 24 ) )
/**
* SMBIOS entry point
*
* This is the single table which describes the list of SMBIOS
* structures. It is located by scanning through the BIOS segment.
*/
struct smbios_entry {
/** Signature
*
* Must be equal to SMBIOS_SIGNATURE
*/
uint32_t signature;
/** Checksum */
uint8_t checksum;
/** Length */
uint8_t len;
/** Major version */
uint8_t major;
/** Minor version */
uint8_t minor;
/** Maximum structure size */
uint16_t max;
/** Entry point revision */
uint8_t revision;
/** Formatted area */
uint8_t formatted[5];
/** DMI Signature */
uint8_t dmi_signature[5];
/** DMI checksum */
uint8_t dmi_checksum;
/** Structure table length */
uint16_t smbios_len;
/** Structure table address */
physaddr_t smbios_address;
/** Number of SMBIOS structures */
uint16_t smbios_count;
/** BCD revision */
uint8_t bcd_revision;
} __attribute__ (( packed ));
/**
* SMBIOS entry point descriptor
*
* This contains the information from the SMBIOS entry point that we
* care about.
*/
struct smbios {
/** Start of SMBIOS structures */
userptr_t address;
/** Length of SMBIOS structures */
size_t len;
/** Number of SMBIOS structures */
unsigned int count;
};
/** SMBIOS entry point descriptor */
static struct smbios smbios = {
.address = UNULL,
};
/**
* Find SMBIOS
*
* @ret rc Return status code
*/
static int find_smbios ( void ) {
union {
struct smbios_entry entry;
uint8_t bytes[256]; /* 256 is maximum length possible */
} u;
static unsigned int offset = 0;
size_t len;
unsigned int i;
uint8_t sum;
/* Return cached result if avaiable */
if ( smbios.address != UNULL )
return 0;
/* Try to find SMBIOS */
for ( ; offset < 0x10000 ; offset += 0x10 ) {
/* Read start of header and verify signature */
copy_from_real ( &u.entry, BIOS_SEG, offset,
sizeof ( u.entry ));
if ( u.entry.signature != SMBIOS_SIGNATURE )
continue;
/* Read whole header and verify checksum */
len = u.entry.len;
copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
for ( i = 0 , sum = 0 ; i < len ; i++ ) {
sum += u.bytes[i];
}
if ( sum != 0 ) {
DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n",
BIOS_SEG, offset, sum );
continue;
}
/* Fill result structure */
DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n",
u.entry.major, u.entry.minor, BIOS_SEG, offset );
smbios.address = phys_to_user ( u.entry.smbios_address );
smbios.len = u.entry.smbios_len;
smbios.count = u.entry.smbios_count;
return 0;
}
DBG ( "No SMBIOS found\n" );
return -ENODEV;
}
/**
* Find SMBIOS strings terminator
*
@ -182,8 +68,10 @@ int find_smbios_structure ( unsigned int type,
int rc;
/* Find SMBIOS */
if ( ( rc = find_smbios() ) != 0 )
if ( ( smbios.address == UNULL ) &&
( ( rc = find_smbios ( &smbios ) ) != 0 ) )
return rc;
assert ( smbios.address != UNULL );
/* Scan through list of structures */
while ( ( ( offset + sizeof ( structure->header ) ) < smbios.len )

View File

@ -22,7 +22,7 @@
#include <gpxe/settings.h>
#include <gpxe/init.h>
#include <gpxe/uuid.h>
#include <smbios.h>
#include <gpxe/smbios.h>
/** SMBIOS settings tag magic number */
#define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */