2 * Dump DMI information in a way hopefully compatible with dmidecode
21 struct smbios_header
{
31 struct dmi_header dmi
;
34 static uint8_t checksum(const void *buf
, size_t len
)
36 const uint8_t *p
= buf
;
45 static bool is_old_dmi(size_t dptr
)
47 const struct dmi_header
*dmi
= (void *)dptr
;
49 return !memcmp(dmi
->signature
, "_DMI_", 5) &&
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
) &&
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
;
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
;
89 struct dmi_header dmi
;
94 snprintf(filename
, sizeof filename
, "dmi/%05x.%08x",
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.
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
)
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
);