1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
* Copyright 2020 Oxide Computer Company
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mdb_modapi.h>
#include <sys/smbios_impl.h>
#include <unistd.h>
/*
* Unfortunately, we're in a bit of a bind. Because of the situation we're in,
* we cannot use string.h directly as it declares ffs() which is also declared
* in sys/systm.h. sys/systm.h is being pulled in because mdb is building with
* _KERNEL. Therefore we have to manually declare an extern delaration for
* strerror().
*/
extern char *strerror(int);
/*
* Take an existing smbios_hdl_t from a dump and slurp out its memory so we can
* open up a new smbios handle to perform operations on.
*/
static int
smbios_mdb_write(const char *path, uintptr_t addr)
{
smbios_hdl_t shp, *hdl;
void *buf;
int err, fd = -1;
int ret = DCMD_ERR;
if (mdb_vread(&shp, sizeof (shp), addr) != sizeof (shp)) {
mdb_warn("failed to read smbios_hdl_t at %p", addr);
return (DCMD_ERR);
}
buf = mdb_alloc(shp.sh_buflen, UM_NOSLEEP | UM_GC);
if (buf == NULL) {
mdb_warn("failed to allocate %zu bytes for the smbios "
"data buffer", shp.sh_buflen);
return (DCMD_ERR);
}
if (mdb_vread(buf, shp.sh_buflen, (uintptr_t)shp.sh_buf) !=
shp.sh_buflen) {
mdb_warn("failed to copy smbios data at %p", shp.sh_buf);
return (DCMD_ERR);
}
hdl = smbios_bufopen(&shp.sh_ent, buf, shp.sh_buflen, SMB_VERSION, 0,
&err);
if (hdl == NULL) {
mdb_warn("failed to load smbios data: %s\n",
smbios_errmsg(err));
return (DCMD_ERR);
}
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
mdb_warn("failed to open output file %s: %s\n", path,
strerror(errno));
goto out;
}
if (smbios_write(hdl, fd) != 0) {
mdb_warn("failed to write smbios data to %s: %s\n", path,
smbios_errmsg(smbios_errno(hdl)));
ret = DCMD_ERR;
} else {
ret = DCMD_OK;
}
out:
if (fd != -1) {
(void) close(fd);
}
smbios_close(hdl);
return (ret);
}
static int
smbios_mdb_smbios(uintptr_t addr, uint_t flags, int argc,
const mdb_arg_t *argv)
{
const char *wpath = NULL;
if (!(flags & DCMD_ADDRSPEC)) {
mdb_warn("missing required smbios_hdl_t\n");
return (DCMD_USAGE);
}
if (mdb_getopts(argc, argv, 'w', MDB_OPT_STR, &wpath, NULL) != argc) {
return (DCMD_USAGE);
}
if (wpath != NULL) {
return (smbios_mdb_write(wpath, addr));
}
return (DCMD_USAGE);
}
static void
smbios_mdb_help(void)
{
mdb_printf("Given a pointer to an smbios_hdl_t take the following "
"actions:\n\n"
"\t-w path\t\tWrite SMBIOS data out to path\n");
}
static const mdb_dcmd_t smbios_dcmds[] = {
{ "smbios", ":[-w path]", "Manipulate an smbios handle",
smbios_mdb_smbios, smbios_mdb_help },
{ NULL }
};
static const mdb_modinfo_t smbios_modinfo = {
MDB_API_VERSION, smbios_dcmds, NULL
};
const mdb_modinfo_t *
_mdb_init(void)
{
return (&smbios_modinfo);
}
|