~ubuntu-branches/ubuntu/saucy/qemu/saucy-proposed

« back to all changes in this revision

Viewing changes to hw/i386/smbios.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * SMBIOS Support
 
3
 *
 
4
 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
 
5
 *
 
6
 * Authors:
 
7
 *  Alex Williamson <alex.williamson@hp.com>
 
8
 *
 
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 
10
 * the COPYING file in the top-level directory.
 
11
 *
 
12
 * Contributions after 2012-01-13 are licensed under the terms of the
 
13
 * GNU GPL, version 2 or (at your option) any later version.
 
14
 */
 
15
 
 
16
#include "sysemu/sysemu.h"
 
17
#include "hw/i386/smbios.h"
 
18
#include "hw/loader.h"
 
19
 
 
20
/*
 
21
 * Structures shared with the BIOS
 
22
 */
 
23
struct smbios_header {
 
24
    uint16_t length;
 
25
    uint8_t type;
 
26
} QEMU_PACKED;
 
27
 
 
28
struct smbios_field {
 
29
    struct smbios_header header;
 
30
    uint8_t type;
 
31
    uint16_t offset;
 
32
    uint8_t data[];
 
33
} QEMU_PACKED;
 
34
 
 
35
struct smbios_table {
 
36
    struct smbios_header header;
 
37
    uint8_t data[];
 
38
} QEMU_PACKED;
 
39
 
 
40
#define SMBIOS_FIELD_ENTRY 0
 
41
#define SMBIOS_TABLE_ENTRY 1
 
42
 
 
43
 
 
44
static uint8_t *smbios_entries;
 
45
static size_t smbios_entries_len;
 
46
static int smbios_type4_count = 0;
 
47
 
 
48
static void smbios_validate_table(void)
 
49
{
 
50
    if (smbios_type4_count && smbios_type4_count != smp_cpus) {
 
51
         fprintf(stderr,
 
52
                 "Number of SMBIOS Type 4 tables must match cpu count.\n");
 
53
        exit(1);
 
54
    }
 
55
}
 
56
 
 
57
uint8_t *smbios_get_table(size_t *length)
 
58
{
 
59
    smbios_validate_table();
 
60
    *length = smbios_entries_len;
 
61
    return smbios_entries;
 
62
}
 
63
 
 
64
/*
 
65
 * To avoid unresolvable overlaps in data, don't allow both
 
66
 * tables and fields for the same smbios type.
 
67
 */
 
68
static void smbios_check_collision(int type, int entry)
 
69
{
 
70
    uint16_t *num_entries = (uint16_t *)smbios_entries;
 
71
    struct smbios_header *header;
 
72
    char *p;
 
73
    int i;
 
74
 
 
75
    if (!num_entries)
 
76
        return;
 
77
 
 
78
    p = (char *)(num_entries + 1);
 
79
 
 
80
    for (i = 0; i < *num_entries; i++) {
 
81
        header = (struct smbios_header *)p;
 
82
        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
 
83
            struct smbios_field *field = (void *)header;
 
84
            if (type == field->type) {
 
85
                fprintf(stderr, "SMBIOS type %d field already defined, "
 
86
                                "cannot add table\n", type);
 
87
                exit(1);
 
88
            }
 
89
        } else if (entry == SMBIOS_FIELD_ENTRY &&
 
90
                   header->type == SMBIOS_TABLE_ENTRY) {
 
91
            struct smbios_structure_header *table = (void *)(header + 1);
 
92
            if (type == table->type) {
 
93
                fprintf(stderr, "SMBIOS type %d table already defined, "
 
94
                                "cannot add field\n", type);
 
95
                exit(1);
 
96
            }
 
97
        }
 
98
        p += le16_to_cpu(header->length);
 
99
    }
 
100
}
 
101
 
 
102
void smbios_add_field(int type, int offset, int len, void *data)
 
103
{
 
104
    struct smbios_field *field;
 
105
 
 
106
    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
 
107
 
 
108
    if (!smbios_entries) {
 
109
        smbios_entries_len = sizeof(uint16_t);
 
110
        smbios_entries = g_malloc0(smbios_entries_len);
 
111
    }
 
112
    smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
 
113
                                                  sizeof(*field) + len);
 
114
    field = (struct smbios_field *)(smbios_entries + smbios_entries_len);
 
115
    field->header.type = SMBIOS_FIELD_ENTRY;
 
116
    field->header.length = cpu_to_le16(sizeof(*field) + len);
 
117
 
 
118
    field->type = type;
 
119
    field->offset = cpu_to_le16(offset);
 
120
    memcpy(field->data, data, len);
 
121
 
 
122
    smbios_entries_len += sizeof(*field) + len;
 
123
    (*(uint16_t *)smbios_entries) =
 
124
            cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 
125
}
 
126
 
 
127
static void smbios_build_type_0_fields(const char *t)
 
128
{
 
129
    char buf[1024];
 
130
 
 
131
    if (get_param_value(buf, sizeof(buf), "vendor", t))
 
132
        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
 
133
                         strlen(buf) + 1, buf);
 
134
    if (get_param_value(buf, sizeof(buf), "version", t))
 
135
        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
 
136
                         strlen(buf) + 1, buf);
 
137
    if (get_param_value(buf, sizeof(buf), "date", t))
 
138
        smbios_add_field(0, offsetof(struct smbios_type_0,
 
139
                                     bios_release_date_str),
 
140
                                     strlen(buf) + 1, buf);
 
141
    if (get_param_value(buf, sizeof(buf), "release", t)) {
 
142
        int major, minor;
 
143
        sscanf(buf, "%d.%d", &major, &minor);
 
144
        smbios_add_field(0, offsetof(struct smbios_type_0,
 
145
                                     system_bios_major_release), 1, &major);
 
146
        smbios_add_field(0, offsetof(struct smbios_type_0,
 
147
                                     system_bios_minor_release), 1, &minor);
 
148
    }
 
149
}
 
150
 
 
151
static void smbios_build_type_1_fields(const char *t)
 
152
{
 
153
    char buf[1024];
 
154
 
 
155
    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
 
156
        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
 
157
                         strlen(buf) + 1, buf);
 
158
    if (get_param_value(buf, sizeof(buf), "product", t))
 
159
        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
 
160
                         strlen(buf) + 1, buf);
 
161
    if (get_param_value(buf, sizeof(buf), "version", t))
 
162
        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
 
163
                         strlen(buf) + 1, buf);
 
164
    if (get_param_value(buf, sizeof(buf), "serial", t))
 
165
        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
 
166
                         strlen(buf) + 1, buf);
 
167
    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
 
168
        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
 
169
            fprintf(stderr, "Invalid SMBIOS UUID string\n");
 
170
            exit(1);
 
171
        }
 
172
    }
 
173
    if (get_param_value(buf, sizeof(buf), "sku", t))
 
174
        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
 
175
                         strlen(buf) + 1, buf);
 
176
    if (get_param_value(buf, sizeof(buf), "family", t))
 
177
        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
 
178
                         strlen(buf) + 1, buf);
 
179
}
 
180
 
 
181
int smbios_entry_add(const char *t)
 
182
{
 
183
    char buf[1024];
 
184
 
 
185
    if (get_param_value(buf, sizeof(buf), "file", t)) {
 
186
        struct smbios_structure_header *header;
 
187
        struct smbios_table *table;
 
188
        int size = get_image_size(buf);
 
189
 
 
190
        if (size == -1 || size < sizeof(struct smbios_structure_header)) {
 
191
            fprintf(stderr, "Cannot read smbios file %s\n", buf);
 
192
            exit(1);
 
193
        }
 
194
 
 
195
        if (!smbios_entries) {
 
196
            smbios_entries_len = sizeof(uint16_t);
 
197
            smbios_entries = g_malloc0(smbios_entries_len);
 
198
        }
 
199
 
 
200
        smbios_entries = g_realloc(smbios_entries, smbios_entries_len +
 
201
                                                      sizeof(*table) + size);
 
202
        table = (struct smbios_table *)(smbios_entries + smbios_entries_len);
 
203
        table->header.type = SMBIOS_TABLE_ENTRY;
 
204
        table->header.length = cpu_to_le16(sizeof(*table) + size);
 
205
 
 
206
        if (load_image(buf, table->data) != size) {
 
207
            fprintf(stderr, "Failed to load smbios file %s", buf);
 
208
            exit(1);
 
209
        }
 
210
 
 
211
        header = (struct smbios_structure_header *)(table->data);
 
212
        smbios_check_collision(header->type, SMBIOS_TABLE_ENTRY);
 
213
        if (header->type == 4) {
 
214
            smbios_type4_count++;
 
215
        }
 
216
 
 
217
        smbios_entries_len += sizeof(*table) + size;
 
218
        (*(uint16_t *)smbios_entries) =
 
219
                cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 
220
        return 0;
 
221
    }
 
222
 
 
223
    if (get_param_value(buf, sizeof(buf), "type", t)) {
 
224
        unsigned long type = strtoul(buf, NULL, 0);
 
225
        switch (type) {
 
226
        case 0:
 
227
            smbios_build_type_0_fields(t);
 
228
            return 0;
 
229
        case 1:
 
230
            smbios_build_type_1_fields(t);
 
231
            return 0;
 
232
        default:
 
233
            fprintf(stderr, "Don't know how to build fields for SMBIOS type "
 
234
                    "%ld\n", type);
 
235
            exit(1);
 
236
        }
 
237
    }
 
238
 
 
239
    fprintf(stderr, "smbios: must specify type= or file=\n");
 
240
    return -1;
 
241
}