2 * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
40 #include <machine/vmm.h>
44 #include "smbiostbl.h"
46 #define MB (1024*1024)
47 #define GB (1024ULL*1024*1024)
49 #define SMBIOS_BASE 0xF1000
51 /* BHYVE_ACPI_BASE - SMBIOS_BASE) */
52 #define SMBIOS_MAX_LENGTH (0xF2400 - 0xF1000)
54 #define SMBIOS_TYPE_BIOS 0
55 #define SMBIOS_TYPE_SYSTEM 1
56 #define SMBIOS_TYPE_CHASSIS 3
57 #define SMBIOS_TYPE_PROCESSOR 4
58 #define SMBIOS_TYPE_MEMARRAY 16
59 #define SMBIOS_TYPE_MEMDEVICE 17
60 #define SMBIOS_TYPE_MEMARRAYMAP 19
61 #define SMBIOS_TYPE_BOOT 32
62 #define SMBIOS_TYPE_EOT 127
64 struct smbios_structure {
70 typedef int (*initializer_func_t)(struct smbios_structure *template_entry,
71 const char **template_strings, char *curaddr, char **endaddr,
72 uint16_t *n, uint16_t *size);
74 struct smbios_template_entry {
75 struct smbios_structure *entry;
77 initializer_func_t initializer;
81 * SMBIOS Structure Table Entry Point
83 #define SMBIOS_ENTRY_EANCHOR "_SM_"
84 #define SMBIOS_ENTRY_EANCHORLEN 4
85 #define SMBIOS_ENTRY_IANCHOR "_DMI_"
86 #define SMBIOS_ENTRY_IANCHORLEN 5
88 struct smbios_entry_point {
89 char eanchor[4]; /* anchor tag */
90 uint8_t echecksum; /* checksum of entry point structure */
91 uint8_t eplen; /* length in bytes of entry point */
92 uint8_t major; /* major version of the SMBIOS spec */
93 uint8_t minor; /* minor version of the SMBIOS spec */
94 uint16_t maxssize; /* maximum size in bytes of a struct */
95 uint8_t revision; /* entry point structure revision */
96 uint8_t format[5]; /* entry point rev-specific data */
97 char ianchor[5]; /* intermediate anchor tag */
98 uint8_t ichecksum; /* intermediate checksum */
99 uint16_t stlen; /* len in bytes of structure table */
100 uint32_t staddr; /* physical addr of structure table */
101 uint16_t stnum; /* number of structure table entries */
102 uint8_t bcdrev; /* BCD value representing DMI ver */
108 #define SMBIOS_FL_ISA 0x00000010 /* ISA is supported */
109 #define SMBIOS_FL_PCI 0x00000080 /* PCI is supported */
110 #define SMBIOS_FL_SHADOW 0x00001000 /* BIOS shadowing is allowed */
111 #define SMBIOS_FL_CDBOOT 0x00008000 /* Boot from CD is supported */
112 #define SMBIOS_FL_SELBOOT 0x00010000 /* Selectable Boot supported */
113 #define SMBIOS_FL_EDD 0x00080000 /* EDD Spec is supported */
115 #define SMBIOS_XB1_FL_ACPI 0x00000001 /* ACPI is supported */
117 #define SMBIOS_XB2_FL_BBS 0x00000001 /* BIOS Boot Specification */
118 #define SMBIOS_XB2_FL_VM 0x00000010 /* Virtual Machine */
120 struct smbios_table_type0 {
121 struct smbios_structure header;
122 uint8_t vendor; /* vendor string */
123 uint8_t version; /* version string */
124 uint16_t segment; /* address segment location */
125 uint8_t rel_date; /* release date */
126 uint8_t size; /* rom size */
127 uint64_t cflags; /* characteristics */
128 uint8_t xc_bytes[2]; /* characteristics ext bytes */
129 uint8_t sb_major_rel; /* system bios version */
130 uint8_t sb_minor_rele;
131 uint8_t ecfw_major_rel; /* embedded ctrl fw version */
132 uint8_t ecfw_minor_rel;
138 #define SMBIOS_WAKEUP_SWITCH 0x06 /* power switch */
140 struct smbios_table_type1 {
141 struct smbios_structure header;
142 uint8_t manufacturer; /* manufacturer string */
143 uint8_t product; /* product name string */
144 uint8_t version; /* version string */
145 uint8_t serial; /* serial number string */
146 uint8_t uuid[16]; /* uuid byte array */
147 uint8_t wakeup; /* wake-up event */
148 uint8_t sku; /* sku number string */
149 uint8_t family; /* family name string */
153 * System Enclosure or Chassis
155 #define SMBIOS_CHT_UNKNOWN 0x02 /* unknown */
157 #define SMBIOS_CHST_SAFE 0x03 /* safe */
159 #define SMBIOS_CHSC_NONE 0x03 /* none */
161 struct smbios_table_type3 {
162 struct smbios_structure header;
163 uint8_t manufacturer; /* manufacturer string */
164 uint8_t type; /* type */
165 uint8_t version; /* version string */
166 uint8_t serial; /* serial number string */
167 uint8_t asset; /* asset tag string */
168 uint8_t bustate; /* boot-up state */
169 uint8_t psstate; /* power supply state */
170 uint8_t tstate; /* thermal state */
171 uint8_t security; /* security status */
172 uint8_t uheight; /* height in 'u's */
173 uint8_t cords; /* number of power cords */
174 uint8_t elems; /* number of element records */
175 uint8_t elemlen; /* length of records */
176 uint8_t sku; /* sku number string */
180 * Processor Information
182 #define SMBIOS_PRT_CENTRAL 0x03 /* central processor */
184 #define SMBIOS_PRF_OTHER 0x01 /* other */
186 #define SMBIOS_PRS_PRESENT 0x40 /* socket is populated */
187 #define SMBIOS_PRS_ENABLED 0x1 /* enabled */
189 #define SMBIOS_PRU_NONE 0x06 /* none */
191 #define SMBIOS_PFL_64B 0x04 /* 64-bit capable */
193 struct smbios_table_type4 {
194 struct smbios_structure header;
195 uint8_t socket; /* socket designation string */
196 uint8_t type; /* processor type */
197 uint8_t family; /* processor family */
198 uint8_t manufacturer; /* manufacturer string */
199 uint64_t cpuid; /* processor cpuid */
200 uint8_t version; /* version string */
201 uint8_t voltage; /* voltage */
202 uint16_t clkspeed; /* ext clock speed in mhz */
203 uint16_t maxspeed; /* maximum speed in mhz */
204 uint16_t curspeed; /* current speed in mhz */
205 uint8_t status; /* status */
206 uint8_t upgrade; /* upgrade */
207 uint16_t l1handle; /* l1 cache handle */
208 uint16_t l2handle; /* l2 cache handle */
209 uint16_t l3handle; /* l3 cache handle */
210 uint8_t serial; /* serial number string */
211 uint8_t asset; /* asset tag string */
212 uint8_t part; /* part number string */
213 uint8_t cores; /* cores per socket */
214 uint8_t ecores; /* enabled cores */
215 uint8_t threads; /* threads per socket */
216 uint16_t cflags; /* processor characteristics */
217 uint16_t family2; /* processor family 2 */
221 * Physical Memory Array
223 #define SMBIOS_MAL_SYSMB 0x03 /* system board or motherboard */
225 #define SMBIOS_MAU_SYSTEM 0x03 /* system memory */
227 #define SMBIOS_MAE_NONE 0x03 /* none */
229 struct smbios_table_type16 {
230 struct smbios_structure header;
231 uint8_t location; /* physical device location */
232 uint8_t use; /* device functional purpose */
233 uint8_t ecc; /* err detect/correct method */
234 uint32_t size; /* max mem capacity in kb */
235 uint16_t errhand; /* handle of error (if any) */
236 uint16_t ndevs; /* num of slots or sockets */
237 uint64_t xsize; /* max mem capacity in bytes */
243 #define SMBIOS_MDFF_UNKNOWN 0x02 /* unknown */
245 #define SMBIOS_MDT_UNKNOWN 0x02 /* unknown */
247 #define SMBIOS_MDF_UNKNOWN 0x0004 /* unknown */
249 struct smbios_table_type17 {
250 struct smbios_structure header;
251 uint16_t arrayhand; /* handle of physl mem array */
252 uint16_t errhand; /* handle of mem error data */
253 uint16_t twidth; /* total width in bits */
254 uint16_t dwidth; /* data width in bits */
255 uint16_t size; /* size in bytes */
256 uint8_t form; /* form factor */
257 uint8_t set; /* set */
258 uint8_t dloc; /* device locator string */
259 uint8_t bloc; /* phys bank locator string */
260 uint8_t type; /* memory type */
261 uint16_t flags; /* memory characteristics */
262 uint16_t maxspeed; /* maximum speed in mhz */
263 uint8_t manufacturer; /* manufacturer string */
264 uint8_t serial; /* serial number string */
265 uint8_t asset; /* asset tag string */
266 uint8_t part; /* part number string */
267 uint8_t attributes; /* attributes */
268 uint32_t xsize; /* extended size in mbs */
269 uint16_t curspeed; /* current speed in mhz */
270 uint16_t minvoltage; /* minimum voltage */
271 uint16_t maxvoltage; /* maximum voltage */
272 uint16_t curvoltage; /* configured voltage */
276 * Memory Array Mapped Address
278 struct smbios_table_type19 {
279 struct smbios_structure header;
280 uint32_t saddr; /* start phys addr in kb */
281 uint32_t eaddr; /* end phys addr in kb */
282 uint16_t arrayhand; /* physical mem array handle */
283 uint8_t width; /* num of dev in row */
284 uint64_t xsaddr; /* start phys addr in bytes */
285 uint64_t xeaddr; /* end phys addr in bytes */
289 * System Boot Information
291 #define SMBIOS_BOOT_NORMAL 0 /* no errors detected */
293 struct smbios_table_type32 {
294 struct smbios_structure header;
296 uint8_t status; /* boot status */
302 struct smbios_table_type127 {
303 struct smbios_structure header;
306 struct smbios_table_type0 smbios_type0_template = {
307 { SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 },
308 1, /* bios vendor string */
309 2, /* bios version string */
310 0xF000, /* bios address segment location */
311 3, /* bios release date */
312 0x0, /* bios size (64k * (n + 1) is the size in bytes) */
313 SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW |
314 SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD,
315 { SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM },
316 0x0, /* bios major release */
317 0x0, /* bios minor release */
318 0xff, /* embedded controller firmware major release */
319 0xff /* embedded controller firmware minor release */
322 const char *smbios_type0_strings[] = {
323 "BHYVE", /* vendor string */
324 "1.00", /* bios version string */
325 "03/14/2014", /* bios release date string */
329 struct smbios_table_type1 smbios_type1_template = {
330 { SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 },
331 1, /* manufacturer string */
332 2, /* product string */
333 3, /* version string */
334 4, /* serial number string */
336 SMBIOS_WAKEUP_SWITCH,
338 6 /* family string */
341 static int smbios_type1_initializer(struct smbios_structure *template_entry,
342 const char **template_strings, char *curaddr, char **endaddr,
343 uint16_t *n, uint16_t *size);
345 const char *smbios_type1_strings[] = {
346 " ", /* manufacturer string */
347 "BHYVE", /* product name string */
348 "1.0", /* version string */
349 "None", /* serial number string */
350 "None", /* sku string */
351 " ", /* family name string */
355 struct smbios_table_type3 smbios_type3_template = {
356 { SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 },
357 1, /* manufacturer string */
359 2, /* version string */
360 3, /* serial number string */
361 4, /* asset tag string */
366 0, /* height in 'u's (0=enclosure height unspecified) */
367 0, /* number of power cords (0=number unspecified) */
368 0, /* number of contained element records */
369 0, /* length of records */
370 5 /* sku number string */
373 const char *smbios_type3_strings[] = {
374 " ", /* manufacturer string */
375 "1.0", /* version string */
376 "None", /* serial number string */
377 "None", /* asset tag string */
378 "None", /* sku number string */
382 struct smbios_table_type4 smbios_type4_template = {
383 { SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 },
384 1, /* socket designation string */
387 2, /* manufacturer string */
389 3, /* version string */
391 0, /* external clock frequency in mhz (0=unknown) */
392 0, /* maximum frequency in mhz (0=unknown) */
393 0, /* current frequency in mhz (0=unknown) */
394 SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED,
396 -1, /* l1 cache handle */
397 -1, /* l2 cache handle */
398 -1, /* l3 cache handle */
399 4, /* serial number string */
400 5, /* asset tag string */
401 6, /* part number string */
402 0, /* cores per socket (0=unknown) */
403 0, /* enabled cores per socket (0=unknown) */
404 0, /* threads per socket (0=unknown) */
409 const char *smbios_type4_strings[] = {
410 " ", /* socket designation string */
411 " ", /* manufacturer string */
412 " ", /* version string */
413 "None", /* serial number string */
414 "None", /* asset tag string */
415 "None", /* part number string */
419 static int smbios_type4_initializer(struct smbios_structure *template_entry,
420 const char **template_strings, char *curaddr, char **endaddr,
421 uint16_t *n, uint16_t *size);
423 struct smbios_table_type16 smbios_type16_template = {
424 { SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16), 0 },
428 0x80000000, /* max mem capacity in kb (0x80000000=use extended) */
429 -1, /* handle of error (if any) */
430 0, /* number of slots or sockets (TBD) */
431 0 /* extended maximum memory capacity in bytes (TBD) */
434 static int smbios_type16_initializer(struct smbios_structure *template_entry,
435 const char **template_strings, char *curaddr, char **endaddr,
436 uint16_t *n, uint16_t *size);
438 struct smbios_table_type17 smbios_type17_template = {
439 { SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17), 0 },
440 -1, /* handle of physical memory array */
441 -1, /* handle of memory error data */
442 64, /* total width in bits including ecc */
443 64, /* data width in bits */
444 0x7fff, /* size in bytes (0x7fff=use extended)*/
446 0, /* set (0x00=none, 0xff=unknown) */
447 1, /* device locator string */
448 2, /* physical bank locator string */
451 0, /* maximum memory speed in mhz (0=unknown) */
452 3, /* manufacturer string */
453 4, /* serial number string */
454 5, /* asset tag string */
455 6, /* part number string */
456 0, /* attributes (0=unknown rank information) */
457 0, /* extended size in mb (TBD) */
458 0, /* current speed in mhz (0=unknown) */
459 0, /* minimum voltage in mv (0=unknown) */
460 0, /* maximum voltage in mv (0=unknown) */
461 0 /* configured voltage in mv (0=unknown) */
464 const char *smbios_type17_strings[] = {
465 " ", /* device locator string */
466 " ", /* physical bank locator string */
467 " ", /* manufacturer string */
468 "None", /* serial number string */
469 "None", /* asset tag string */
470 "None", /* part number string */
474 static int smbios_type17_initializer(struct smbios_structure *template_entry,
475 const char **template_strings, char *curaddr, char **endaddr,
476 uint16_t *n, uint16_t *size);
478 struct smbios_table_type19 smbios_type19_template = {
479 { SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19), 0 },
480 0xffffffff, /* starting phys addr in kb (0xffffffff=use ext) */
481 0xffffffff, /* ending phys addr in kb (0xffffffff=use ext) */
482 -1, /* physical memory array handle */
483 1, /* number of devices that form a row */
484 0, /* extended starting phys addr in bytes (TDB) */
485 0 /* extended ending phys addr in bytes (TDB) */
488 static int smbios_type19_initializer(struct smbios_structure *template_entry,
489 const char **template_strings, char *curaddr, char **endaddr,
490 uint16_t *n, uint16_t *size);
492 struct smbios_table_type32 smbios_type32_template = {
493 { SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32), 0 },
494 { 0, 0, 0, 0, 0, 0 },
498 struct smbios_table_type127 smbios_type127_template = {
499 { SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127), 0 }
502 static int smbios_generic_initializer(struct smbios_structure *template_entry,
503 const char **template_strings, char *curaddr, char **endaddr,
504 uint16_t *n, uint16_t *size);
506 static struct smbios_template_entry smbios_template[] = {
507 { (struct smbios_structure *)&smbios_type0_template,
508 smbios_type0_strings,
509 smbios_generic_initializer },
510 { (struct smbios_structure *)&smbios_type1_template,
511 smbios_type1_strings,
512 smbios_type1_initializer },
513 { (struct smbios_structure *)&smbios_type3_template,
514 smbios_type3_strings,
515 smbios_generic_initializer },
516 { (struct smbios_structure *)&smbios_type4_template,
517 smbios_type4_strings,
518 smbios_type4_initializer },
519 { (struct smbios_structure *)&smbios_type16_template,
521 smbios_type16_initializer },
522 { (struct smbios_structure *)&smbios_type17_template,
523 smbios_type17_strings,
524 smbios_type17_initializer },
525 { (struct smbios_structure *)&smbios_type19_template,
527 smbios_type19_initializer },
528 { (struct smbios_structure *)&smbios_type32_template,
530 smbios_generic_initializer },
531 { (struct smbios_structure *)&smbios_type127_template,
533 smbios_generic_initializer },
537 static uint64_t guest_lomem, guest_himem;
538 static uint16_t type16_handle;
541 smbios_generic_initializer(struct smbios_structure *template_entry,
542 const char **template_strings, char *curaddr, char **endaddr,
543 uint16_t *n, uint16_t *size)
545 struct smbios_structure *entry;
547 memcpy(curaddr, template_entry, template_entry->length);
548 entry = (struct smbios_structure *)curaddr;
549 entry->handle = *n + 1;
550 curaddr += entry->length;
551 if (template_strings != NULL) {
554 for (i = 0; template_strings[i] != NULL; i++) {
558 string = template_strings[i];
559 len = strlen(string) + 1;
560 memcpy(curaddr, string, len);
566 /* Minimum string section is double nul */
579 smbios_type1_initializer(struct smbios_structure *template_entry,
580 const char **template_strings, char *curaddr, char **endaddr,
581 uint16_t *n, uint16_t *size)
583 struct smbios_table_type1 *type1;
585 smbios_generic_initializer(template_entry, template_strings,
586 curaddr, endaddr, n, size);
587 type1 = (struct smbios_table_type1 *)curaddr;
589 if (guest_uuid_str != NULL) {
593 uuid_from_string(guest_uuid_str, &uuid, &status);
594 if (status != uuid_s_ok)
597 uuid_enc_le(&type1->uuid, &uuid);
601 char hostname[MAXHOSTNAMELEN];
604 * Universally unique and yet reproducible are an
605 * oxymoron, however reproducible is desirable in
608 if (gethostname(hostname, sizeof(hostname)))
612 MD5Update(&mdctx, vmname, strlen(vmname));
613 MD5Update(&mdctx, hostname, sizeof(hostname));
614 MD5Final(digest, &mdctx);
617 * Set the variant and version number.
620 digest[6] |= 0x30; /* version 3 */
624 memcpy(&type1->uuid, digest, sizeof (digest));
631 smbios_type4_initializer(struct smbios_structure *template_entry,
632 const char **template_strings, char *curaddr, char **endaddr,
633 uint16_t *n, uint16_t *size)
637 for (i = 0; i < guest_ncpus; i++) {
638 struct smbios_table_type4 *type4;
642 smbios_generic_initializer(template_entry, template_strings,
643 curaddr, endaddr, n, size);
644 type4 = (struct smbios_table_type4 *)curaddr;
645 p = curaddr + sizeof (struct smbios_table_type4);
647 while (p < *endaddr - 1) {
651 len = sprintf(*endaddr - 1, "CPU #%d", i) + 1;
655 type4->socket = nstrings + 1;
663 smbios_type16_initializer(struct smbios_structure *template_entry,
664 const char **template_strings, char *curaddr, char **endaddr,
665 uint16_t *n, uint16_t *size)
667 struct smbios_table_type16 *type16;
670 smbios_generic_initializer(template_entry, template_strings,
671 curaddr, endaddr, n, size);
672 type16 = (struct smbios_table_type16 *)curaddr;
673 type16->xsize = guest_lomem + guest_himem;
674 type16->ndevs = guest_himem > 0 ? 2 : 1;
680 smbios_type17_initializer(struct smbios_structure *template_entry,
681 const char **template_strings, char *curaddr, char **endaddr,
682 uint16_t *n, uint16_t *size)
684 struct smbios_table_type17 *type17;
686 smbios_generic_initializer(template_entry, template_strings,
687 curaddr, endaddr, n, size);
688 type17 = (struct smbios_table_type17 *)curaddr;
689 type17->arrayhand = type16_handle;
690 type17->xsize = guest_lomem;
692 if (guest_himem > 0) {
694 smbios_generic_initializer(template_entry, template_strings,
695 curaddr, endaddr, n, size);
696 type17 = (struct smbios_table_type17 *)curaddr;
697 type17->arrayhand = type16_handle;
698 type17->xsize = guest_himem;
705 smbios_type19_initializer(struct smbios_structure *template_entry,
706 const char **template_strings, char *curaddr, char **endaddr,
707 uint16_t *n, uint16_t *size)
709 struct smbios_table_type19 *type19;
711 smbios_generic_initializer(template_entry, template_strings,
712 curaddr, endaddr, n, size);
713 type19 = (struct smbios_table_type19 *)curaddr;
714 type19->arrayhand = type16_handle;
716 type19->xeaddr = guest_lomem;
718 if (guest_himem > 0) {
720 smbios_generic_initializer(template_entry, template_strings,
721 curaddr, endaddr, n, size);
722 type19 = (struct smbios_table_type19 *)curaddr;
723 type19->arrayhand = type16_handle;
724 type19->xsaddr = 4*GB;
725 type19->xeaddr = guest_himem;
732 smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
734 memset(smbios_ep, 0, sizeof(*smbios_ep));
735 memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR,
736 SMBIOS_ENTRY_EANCHORLEN);
737 smbios_ep->eplen = 0x1F;
738 assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen);
739 smbios_ep->major = 2;
740 smbios_ep->minor = 6;
741 smbios_ep->revision = 0;
742 memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
743 SMBIOS_ENTRY_IANCHORLEN);
744 smbios_ep->staddr = staddr;
745 smbios_ep->bcdrev = 0x24;
749 smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len,
750 uint16_t num, uint16_t maxssize)
755 smbios_ep->maxssize = maxssize;
756 smbios_ep->stlen = len;
757 smbios_ep->stnum = num;
760 for (i = 0x10; i < 0x1f; i++) {
761 checksum -= ((uint8_t *)smbios_ep)[i];
763 smbios_ep->ichecksum = checksum;
766 for (i = 0; i < 0x1f; i++) {
767 checksum -= ((uint8_t *)smbios_ep)[i];
769 smbios_ep->echecksum = checksum;
773 smbios_build(struct vmctx *ctx)
775 struct smbios_entry_point *smbios_ep;
778 char *curaddr, *startaddr, *ststartaddr;
782 guest_lomem = vm_get_lowmem_size(ctx);
783 guest_himem = vm_get_highmem_size(ctx);
785 startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
786 if (startaddr == NULL) {
787 fprintf(stderr, "smbios table requires mapped mem\n");
793 smbios_ep = (struct smbios_entry_point *)curaddr;
794 smbios_ep_initializer(smbios_ep, SMBIOS_BASE +
795 sizeof(struct smbios_entry_point));
796 curaddr += sizeof(struct smbios_entry_point);
797 ststartaddr = curaddr;
801 for (i = 0; smbios_template[i].entry != NULL; i++) {
802 struct smbios_structure *entry;
803 const char **strings;
804 initializer_func_t initializer;
808 entry = smbios_template[i].entry;
809 strings = smbios_template[i].strings;
810 initializer = smbios_template[i].initializer;
812 err = (*initializer)(entry, strings, curaddr, &endaddr,
823 assert(curaddr - startaddr < SMBIOS_MAX_LENGTH);
824 smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize);