1/* 2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19FILE_LICENCE ( GPL2_OR_LATER ); 20 21#include <stdint.h> 22#include <string.h> 23#include <errno.h> 24#include <gpxe/settings.h> 25#include <gpxe/init.h> 26#include <gpxe/uuid.h> 27#include <gpxe/smbios.h> 28 29/** SMBIOS settings tag magic number */ 30#define SMBIOS_TAG_MAGIC 0x5B /* "SmBios" */ 31 32/** 33 * Construct SMBIOS empty tag 34 * 35 * @ret tag SMBIOS setting tag 36 */ 37#define SMBIOS_EMPTY_TAG ( SMBIOS_TAG_MAGIC << 24 ) 38 39/** 40 * Construct SMBIOS raw-data tag 41 * 42 * @v _type SMBIOS structure type number 43 * @v _structure SMBIOS structure data type 44 * @v _field Field within SMBIOS structure data type 45 * @ret tag SMBIOS setting tag 46 */ 47#define SMBIOS_RAW_TAG( _type, _structure, _field ) \ 48 ( ( SMBIOS_TAG_MAGIC << 24 ) | \ 49 ( (_type) << 16 ) | \ 50 ( offsetof ( _structure, _field ) << 8 ) | \ 51 ( sizeof ( ( ( _structure * ) 0 )->_field ) ) ) 52 53/** 54 * Construct SMBIOS string tag 55 * 56 * @v _type SMBIOS structure type number 57 * @v _structure SMBIOS structure data type 58 * @v _field Field within SMBIOS structure data type 59 * @ret tag SMBIOS setting tag 60 */ 61#define SMBIOS_STRING_TAG( _type, _structure, _field ) \ 62 ( ( SMBIOS_TAG_MAGIC << 24 ) | \ 63 ( (_type) << 16 ) | \ 64 ( offsetof ( _structure, _field ) << 8 ) ) 65 66/** 67 * Fetch value of SMBIOS setting 68 * 69 * @v settings Settings block, or NULL to search all blocks 70 * @v setting Setting to fetch 71 * @v data Buffer to fill with setting data 72 * @v len Length of buffer 73 * @ret len Length of setting data, or negative error 74 */ 75static int smbios_fetch ( struct settings *settings __unused, 76 struct setting *setting, 77 void *data, size_t len ) { 78 struct smbios_structure structure; 79 unsigned int tag_magic; 80 unsigned int tag_type; 81 unsigned int tag_offset; 82 unsigned int tag_len; 83 int rc; 84 85 /* Split tag into type, offset and length */ 86 tag_magic = ( setting->tag >> 24 ); 87 tag_type = ( ( setting->tag >> 16 ) & 0xff ); 88 tag_offset = ( ( setting->tag >> 8 ) & 0xff ); 89 tag_len = ( setting->tag & 0xff ); 90 if ( tag_magic != SMBIOS_TAG_MAGIC ) 91 return -ENOENT; 92 93 /* Find SMBIOS structure */ 94 if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 ) 95 return rc; 96 97 { 98 uint8_t buf[structure.header.len]; 99 100 /* Read SMBIOS structure */ 101 if ( ( rc = read_smbios_structure ( &structure, buf, 102 sizeof ( buf ) ) ) != 0 ) 103 return rc; 104 105 if ( tag_len == 0 ) { 106 /* String */ 107 return read_smbios_string ( &structure, 108 buf[tag_offset], 109 data, len ); 110 } else { 111 /* Raw data */ 112 if ( len > tag_len ) 113 len = tag_len; 114 memcpy ( data, &buf[tag_offset], len ); 115 return tag_len; 116 } 117 } 118} 119 120/** SMBIOS settings operations */ 121static struct settings_operations smbios_settings_operations = { 122 .fetch = smbios_fetch, 123}; 124 125/** SMBIOS settings */ 126static struct settings smbios_settings = { 127 .refcnt = NULL, 128 .name = "smbios", 129 .tag_magic = SMBIOS_EMPTY_TAG, 130 .siblings = LIST_HEAD_INIT ( smbios_settings.siblings ), 131 .children = LIST_HEAD_INIT ( smbios_settings.children ), 132 .op = &smbios_settings_operations, 133}; 134 135/** Initialise SMBIOS settings */ 136static void smbios_init ( void ) { 137 int rc; 138 139 if ( ( rc = register_settings ( &smbios_settings, NULL ) ) != 0 ) { 140 DBG ( "SMBIOS could not register settings: %s\n", 141 strerror ( rc ) ); 142 return; 143 } 144} 145 146/** SMBIOS settings initialiser */ 147struct init_fn smbios_init_fn __init_fn ( INIT_NORMAL ) = { 148 .initialise = smbios_init, 149}; 150 151/** UUID setting obtained via SMBIOS */ 152struct setting uuid_setting __setting = { 153 .name = "uuid", 154 .description = "UUID", 155 .tag = SMBIOS_RAW_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, 156 struct smbios_system_information, uuid ), 157 .type = &setting_type_uuid, 158}; 159 160/** Other SMBIOS named settings */ 161struct setting smbios_named_settings[] __setting = { 162 { 163 .name = "manufacturer", 164 .description = "Manufacturer", 165 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, 166 struct smbios_system_information, 167 manufacturer ), 168 .type = &setting_type_string, 169 }, 170 { 171 .name = "product", 172 .description = "Product name", 173 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, 174 struct smbios_system_information, 175 product ), 176 .type = &setting_type_string, 177 }, 178 { 179 .name = "serial", 180 .description = "Serial number", 181 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_SYSTEM_INFORMATION, 182 struct smbios_system_information, 183 serial ), 184 .type = &setting_type_string, 185 }, 186 { 187 .name = "asset", 188 .description = "Asset tag", 189 .tag = SMBIOS_STRING_TAG ( SMBIOS_TYPE_ENCLOSURE_INFORMATION, 190 struct smbios_enclosure_information, 191 asset_tag ), 192 .type = &setting_type_string, 193 }, 194}; 195