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