Adding upstream version 4.00~pre54+dfsg.
[syslinux-debian/hramrach.git] / com32 / sysdump / dmi.c
blobbe4cce4668d3efb83db787a8434ba72e76ad0e6d
1 /*
2 * Dump DMI information in a way hopefully compatible with dmidecode
3 */
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include "sysdump.h"
9 #include "backend.h"
11 struct dmi_header {
12 char signature[5];
13 uint8_t csum;
14 uint16_t tbllen;
15 uint32_t tbladdr;
16 uint16_t nstruc;
17 uint8_t revision;
18 uint8_t reserved;
21 struct smbios_header {
22 char signature[4];
23 uint8_t csum;
24 uint8_t len;
25 uint8_t major;
26 uint8_t minor;
27 uint16_t maxsize;
28 uint8_t revision;
29 uint8_t fmt[5];
31 struct dmi_header dmi;
34 static uint8_t checksum(const void *buf, size_t len)
36 const uint8_t *p = buf;
37 uint8_t csum = 0;
39 while (len--)
40 csum += *p++;
42 return csum;
45 static bool is_old_dmi(size_t dptr)
47 const struct dmi_header *dmi = (void *)dptr;
49 return !memcmp(dmi->signature, "_DMI_", 5) &&
50 !checksum(dmi, 0x0f);
51 return false;
54 static bool is_smbios(size_t dptr)
56 const struct smbios_header *smb = (void *)dptr;
58 return !memcmp(smb->signature, "_SM_", 4) &&
59 !checksum(smb, smb->len) &&
60 is_old_dmi(dptr+16);
63 static void dump_smbios(struct backend *be, size_t dptr)
65 const struct smbios_header *smb = (void *)dptr;
66 struct smbios_header smx = *smb;
67 char filename[32];
69 snprintf(filename, sizeof filename, "dmi/%05x.%08x",
70 dptr, smb->dmi.tbladdr);
71 cpio_hdr(be, MODE_FILE, smb->dmi.tbllen + 32, filename);
74 * Adjust the address of the smbios table to be 32, to
75 * make dmidecode happy. The checksum on the smbios table is unchanged,
76 * since it includes the checksum on the dmi table.
78 smx.dmi.tbladdr = sizeof smx;
79 smx.dmi.csum -= checksum(&smx.dmi, 0x0f);
81 write_data(be, &smx, sizeof smx);
82 write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen);
85 static void dump_old_dmi(struct backend *be, size_t dptr)
87 const struct dmi_header *dmi = (void *)dptr;
88 struct fake {
89 struct dmi_header dmi;
90 char pad[16];
91 } fake;
92 char filename[32];
94 snprintf(filename, sizeof filename, "dmi/%05x.%08x",
95 dptr, dmi->tbladdr);
96 cpio_hdr(be, MODE_FILE, dmi->tbllen + 32, filename);
99 * Adjust the address of the smbios table to be 32, to
100 * make dmidecode happy.
102 fake.dmi = *dmi;
103 memset(&fake.pad, 0, sizeof fake.pad);
104 fake.dmi.tbladdr = sizeof fake;
105 fake.dmi.csum -= checksum(&fake.dmi, 0x0f);
107 write_data(be, &fake, sizeof fake);
108 write_data(be, (const void *)dmi->tbladdr, dmi->tbllen);
111 void dump_dmi(struct backend *be)
113 size_t dptr;
115 cpio_mkdir(be, "dmi");
117 /* Search for _SM_ or _DMI_ structure */
118 for (dptr = 0xf0000 ; dptr < 0x100000 ; dptr += 16) {
119 if (is_smbios(dptr)) {
120 dump_smbios(be, dptr);
121 dptr += 16; /* Skip the subsequent DMI header */
122 } else if (is_old_dmi(dptr)) {
123 dump_old_dmi(be, dptr);