16edddafdSRobert Mustacchi /*
26edddafdSRobert Mustacchi * This file and its contents are supplied under the terms of the
36edddafdSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
46edddafdSRobert Mustacchi * You may only use this file in accordance with the terms of version
56edddafdSRobert Mustacchi * 1.0 of the CDDL.
66edddafdSRobert Mustacchi *
76edddafdSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
86edddafdSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
96edddafdSRobert Mustacchi * http://www.illumos.org/license/CDDL.
106edddafdSRobert Mustacchi */
116edddafdSRobert Mustacchi
126edddafdSRobert Mustacchi /*
136edddafdSRobert Mustacchi * Copyright 2020 Oxide Computer Company
146edddafdSRobert Mustacchi */
156edddafdSRobert Mustacchi
166edddafdSRobert Mustacchi #include <sys/types.h>
176edddafdSRobert Mustacchi #include <sys/stat.h>
186edddafdSRobert Mustacchi #include <fcntl.h>
196edddafdSRobert Mustacchi #include <errno.h>
206edddafdSRobert Mustacchi #include <sys/mdb_modapi.h>
216edddafdSRobert Mustacchi #include <sys/smbios_impl.h>
226edddafdSRobert Mustacchi #include <unistd.h>
236edddafdSRobert Mustacchi
246edddafdSRobert Mustacchi /*
256edddafdSRobert Mustacchi * Unfortunately, we're in a bit of a bind. Because of the situation we're in,
266edddafdSRobert Mustacchi * we cannot use string.h directly as it declares ffs() which is also declared
276edddafdSRobert Mustacchi * in sys/systm.h. sys/systm.h is being pulled in because mdb is building with
286edddafdSRobert Mustacchi * _KERNEL. Therefore we have to manually declare an extern delaration for
296edddafdSRobert Mustacchi * strerror().
306edddafdSRobert Mustacchi */
31*8ad93a82SRobert Mustacchi extern char *strerror(int);
326edddafdSRobert Mustacchi
336edddafdSRobert Mustacchi /*
346edddafdSRobert Mustacchi * Take an existing smbios_hdl_t from a dump and slurp out its memory so we can
356edddafdSRobert Mustacchi * open up a new smbios handle to perform operations on.
366edddafdSRobert Mustacchi */
376edddafdSRobert Mustacchi static int
smbios_mdb_write(const char * path,uintptr_t addr)386edddafdSRobert Mustacchi smbios_mdb_write(const char *path, uintptr_t addr)
396edddafdSRobert Mustacchi {
406edddafdSRobert Mustacchi smbios_hdl_t shp, *hdl;
416edddafdSRobert Mustacchi void *buf;
426edddafdSRobert Mustacchi int err, fd = -1;
436edddafdSRobert Mustacchi int ret = DCMD_ERR;
446edddafdSRobert Mustacchi
456edddafdSRobert Mustacchi if (mdb_vread(&shp, sizeof (shp), addr) != sizeof (shp)) {
466edddafdSRobert Mustacchi mdb_warn("failed to read smbios_hdl_t at %p", addr);
476edddafdSRobert Mustacchi return (DCMD_ERR);
486edddafdSRobert Mustacchi }
496edddafdSRobert Mustacchi
506edddafdSRobert Mustacchi buf = mdb_alloc(shp.sh_buflen, UM_NOSLEEP | UM_GC);
516edddafdSRobert Mustacchi if (buf == NULL) {
526edddafdSRobert Mustacchi mdb_warn("failed to allocate %zu bytes for the smbios "
536edddafdSRobert Mustacchi "data buffer", shp.sh_buflen);
546edddafdSRobert Mustacchi return (DCMD_ERR);
556edddafdSRobert Mustacchi }
566edddafdSRobert Mustacchi
576edddafdSRobert Mustacchi if (mdb_vread(buf, shp.sh_buflen, (uintptr_t)shp.sh_buf) !=
586edddafdSRobert Mustacchi shp.sh_buflen) {
596edddafdSRobert Mustacchi mdb_warn("failed to copy smbios data at %p", shp.sh_buf);
606edddafdSRobert Mustacchi return (DCMD_ERR);
616edddafdSRobert Mustacchi }
626edddafdSRobert Mustacchi
636edddafdSRobert Mustacchi hdl = smbios_bufopen(&shp.sh_ent, buf, shp.sh_buflen, SMB_VERSION, 0,
646edddafdSRobert Mustacchi &err);
656edddafdSRobert Mustacchi if (hdl == NULL) {
666edddafdSRobert Mustacchi mdb_warn("failed to load smbios data: %s\n",
676edddafdSRobert Mustacchi smbios_errmsg(err));
686edddafdSRobert Mustacchi return (DCMD_ERR);
696edddafdSRobert Mustacchi }
706edddafdSRobert Mustacchi
716edddafdSRobert Mustacchi if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
726edddafdSRobert Mustacchi mdb_warn("failed to open output file %s: %s\n", path,
736edddafdSRobert Mustacchi strerror(errno));
746edddafdSRobert Mustacchi goto out;
756edddafdSRobert Mustacchi }
766edddafdSRobert Mustacchi
776edddafdSRobert Mustacchi if (smbios_write(hdl, fd) != 0) {
786edddafdSRobert Mustacchi mdb_warn("failed to write smbios data to %s: %s\n", path,
796edddafdSRobert Mustacchi smbios_errmsg(smbios_errno(hdl)));
806edddafdSRobert Mustacchi ret = DCMD_ERR;
816edddafdSRobert Mustacchi } else {
826edddafdSRobert Mustacchi ret = DCMD_OK;
836edddafdSRobert Mustacchi }
846edddafdSRobert Mustacchi out:
856edddafdSRobert Mustacchi if (fd != -1) {
866edddafdSRobert Mustacchi (void) close(fd);
876edddafdSRobert Mustacchi }
886edddafdSRobert Mustacchi smbios_close(hdl);
896edddafdSRobert Mustacchi return (ret);
906edddafdSRobert Mustacchi }
916edddafdSRobert Mustacchi
926edddafdSRobert Mustacchi static int
smbios_mdb_smbios(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)936edddafdSRobert Mustacchi smbios_mdb_smbios(uintptr_t addr, uint_t flags, int argc,
946edddafdSRobert Mustacchi const mdb_arg_t *argv)
956edddafdSRobert Mustacchi {
966edddafdSRobert Mustacchi const char *wpath = NULL;
976edddafdSRobert Mustacchi
986edddafdSRobert Mustacchi if (!(flags & DCMD_ADDRSPEC)) {
996edddafdSRobert Mustacchi mdb_warn("missing required smbios_hdl_t\n");
1006edddafdSRobert Mustacchi return (DCMD_USAGE);
1016edddafdSRobert Mustacchi }
1026edddafdSRobert Mustacchi
1036edddafdSRobert Mustacchi if (mdb_getopts(argc, argv, 'w', MDB_OPT_STR, &wpath, NULL) != argc) {
1046edddafdSRobert Mustacchi return (DCMD_USAGE);
1056edddafdSRobert Mustacchi }
1066edddafdSRobert Mustacchi
1076edddafdSRobert Mustacchi if (wpath != NULL) {
1086edddafdSRobert Mustacchi return (smbios_mdb_write(wpath, addr));
1096edddafdSRobert Mustacchi }
1106edddafdSRobert Mustacchi
1116edddafdSRobert Mustacchi return (DCMD_USAGE);
1126edddafdSRobert Mustacchi }
1136edddafdSRobert Mustacchi
1146edddafdSRobert Mustacchi static void
smbios_mdb_help(void)1156edddafdSRobert Mustacchi smbios_mdb_help(void)
1166edddafdSRobert Mustacchi {
1176edddafdSRobert Mustacchi mdb_printf("Given a pointer to an smbios_hdl_t take the following "
1186edddafdSRobert Mustacchi "actions:\n\n"
1196edddafdSRobert Mustacchi "\t-w path\t\tWrite SMBIOS data out to path\n");
1206edddafdSRobert Mustacchi }
1216edddafdSRobert Mustacchi
1226edddafdSRobert Mustacchi static const mdb_dcmd_t smbios_dcmds[] = {
1236edddafdSRobert Mustacchi { "smbios", ":[-w path]", "Manipulate an smbios handle",
1246edddafdSRobert Mustacchi smbios_mdb_smbios, smbios_mdb_help },
1256edddafdSRobert Mustacchi { NULL }
1266edddafdSRobert Mustacchi };
1276edddafdSRobert Mustacchi
1286edddafdSRobert Mustacchi static const mdb_modinfo_t smbios_modinfo = {
1296edddafdSRobert Mustacchi MDB_API_VERSION, smbios_dcmds, NULL
1306edddafdSRobert Mustacchi };
1316edddafdSRobert Mustacchi
1326edddafdSRobert Mustacchi const mdb_modinfo_t *
_mdb_init(void)1336edddafdSRobert Mustacchi _mdb_init(void)
1346edddafdSRobert Mustacchi {
1356edddafdSRobert Mustacchi return (&smbios_modinfo);
1366edddafdSRobert Mustacchi }
137