hvctl_status_t
res_network_device_parse(bin_md_t *mdp, hvctl_res_error_t *fail_codep,
			md_element_t **failnodepp, int *fail_res_idp)
{
	md_element_t	*mdep, *net_nodep, *rootnodep;
	uint64_t	arc_token;
	uint64_t	name_token;

	mdp = (bin_md_t *)config.parse_hvmd;

	rootnodep = md_find_node(mdp, NULL, MDNAME(root));
	if (rootnodep == NULL) {
		DBG(c_printf("Missing root node in HVMD\n"));
		goto fail;
	}
	DBGNET(c_printf("Network configuration:\n"));

	arc_token = MDARC(MDNAME(fwd));
	name_token = MDNODE(MDNAME(devices));

	if (md_find_node_by_arc(mdp, rootnodep, arc_token, name_token,
	    &mdep) == NULL) {
		DBGNET(c_printf("Missing devices node in HVMD\n"));
fail:;
		*failnodepp = NULL;
		*fail_res_idp = 0;
		return (HVctl_st_badmd);
	}

	DBGNET(md_dump_node(mdp, mdep));

	name_token = MDNODE(MDNAME(network_device));

	while (NULL != (mdep = md_find_node_by_arc(mdp, mdep,
	    arc_token, name_token, &net_nodep))) {
		hvctl_status_t status;

		status = res_network_device_parse_1(mdp, net_nodep, fail_codep,
		    fail_res_idp);
		if (status != HVctl_st_ok) {
			*failnodepp = net_nodep;
			return (status);
		}
	}
	return (HVctl_st_ok);
}
hvctl_status_t
res_console_parse(bin_md_t *mdp, hvctl_res_error_t *fail_codep,
			md_element_t **failnodepp, int *fail_res_idp)
{
	md_element_t	*mdep;
	uint64_t	arc_token;
	uint64_t	node_token;
	md_element_t	*cons_nodep;

	mdp = (bin_md_t *)config.parse_hvmd;

	DBG(c_printf("\nConsole configuration:\n"));

	mdep = md_find_node(mdp, NULL, MDNAME(consoles));
	if (mdep == NULL) {
		DBG(c_printf("Missing consoles node in HVMD\n"));
		*failnodepp = NULL;
		*fail_res_idp = 0;
		return (HVctl_st_badmd);
	}

	arc_token = MDARC(MDNAME(fwd));
	node_token = MDNODE(MDNAME(console));

	while (NULL != (mdep = md_find_node_by_arc(mdp, mdep, arc_token,
	    node_token, &cons_nodep))) {
		hvctl_status_t status;
		status = res_console_parse_1(mdp, cons_nodep, fail_codep,
		    fail_res_idp);
		if (status != HVctl_st_ok) {
			*failnodepp = cons_nodep;
			return (status);
		}
	}
	DBG(c_printf("\nConsole configuration: OK \n"));
	return (HVctl_st_ok);
}
hvctl_status_t
res_console_parse_1(bin_md_t *mdp, md_element_t *cons_nodep,
		hvctl_res_error_t *fail_codep, int *fail_res_idp)
{
	uint64_t	resource_id, guest_id, channel_id, ino;
	guest_t		*guestp;
	md_element_t	*guest_nodep, *ldc_nodep, *mdep;

	DBG(md_dump_node(mdp, cons_nodep));

	if (!md_node_get_val(mdp, cons_nodep, MDNAME(resource_id),
	    &resource_id)) {
		DBG(c_printf("Missing resource_id in console node\n"));
		*fail_codep = HVctl_e_cons_missing_id;
		*fail_res_idp = 0;
		return (HVctl_st_badmd);
	}

	*fail_res_idp = resource_id;

		/*
		 * This console node needs to point back to the guest
		 * that owns it.
		 */

	mdep = md_find_node_by_arc(mdp, cons_nodep, MDARC(MDNAME(back)),
	    MDNODE(MDNAME(guest)), &guest_nodep);
	if (mdep == NULL) {
		DBG(c_printf("Missing guest for console 0x%x", resource_id));
		*fail_codep = HVctl_e_cons_missing_guest;
		goto fail;
	}

	if (!md_node_get_val(mdp, guest_nodep, MDNAME(resource_id),
	    &guest_id)) {
		DBG(c_printf("Missing resource_id in console's guest node\n"));
		*fail_codep = HVctl_e_cons_missing_guest_id;
		*fail_res_idp = 0;
		return (HVctl_st_badmd);
	}
	if (guest_id >= NGUESTS) {
		DBG(c_printf("Invalid resource_id in console's guest node\n"));
		*fail_codep = HVctl_e_cons_invalid_guest_id;
		*fail_res_idp = 0;
		return (HVctl_st_badmd);
	}

	guestp = config.guests;
	guestp = &(guestp[guest_id]);

	DBG(c_printf("\tconsole 0x%x for guest 0x%x @ 0x%x\n",
	    resource_id, guest_id, (uint64_t)guestp));

		/*
		 * This console node points fwd to the LDC node
		 * that it needs. Failing that there should be a
		 * UART address in the node for this specific
		 * console.
		 */

	mdep = md_find_node_by_arc(mdp, cons_nodep, MDARC(MDNAME(fwd)),
	    MDNODE(MDNAME(ldc_endpoint)), &ldc_nodep);
	if (mdep == NULL) {
#ifdef CONFIG_CN_UART /* { */
		uint64_t uartbase;
		if (!md_node_get_val(mdp, cons_nodep, MDNAME(uartbase),
		    &uartbase)) {
			DBG(c_printf("Missing ldc arc or uartbase in console"
			    " node\n"));
			*fail_codep = HVctl_e_cons_missing_uartbase;
			goto fail;
		}
		guestp->console.pip.type = CONS_TYPE_UART;
		guestp->console.pip.uartbase = uartbase;
		DBG(c_printf("UART specified for console\n"));
#else /* } { */
		DBG(c_printf("No ldc endpoint specified for console\n"));
		*fail_codep = HVctl_e_cons_missing_ldc_id;
		goto fail;
#endif /* } */
	} else {

		/*
		 * FIXME: LDC errors shouldn't really be possible here
		 * we should have already parsed all the LDC endpoints
		 * so if properties were wrong or missing by this point
		 * we would already have found out.
		 * We leave the checks in here for sanity for now.
		 */

		if (!md_node_get_val(mdp, ldc_nodep, MDNAME(channel),
		    &channel_id)) {
			DBG(c_printf("Missing channel_id in console's"
			    " ldc node\n"));
			*fail_codep = HVctl_e_cons_missing_ldc_id;
			*fail_res_idp = 0;
			goto fail;
		}
		if (channel_id >= MAX_LDC_CHANNELS) {
			DBG(c_printf("Invalid channel id in console's ldc"
			    " node\n"));
			*fail_codep = HVctl_e_cons_invalid_ldc_id;
			*fail_res_idp = 0;
			goto fail;
		}

		DBG(c_printf("\tconsole 0x%x for guest 0x%x [@ 0x%x]"
		    " uses LDC channel 0x%x\n",
		    resource_id, guest_id, (uint64_t)guestp, channel_id));

		guestp->console.pip.type = CONS_TYPE_LDC;
		guestp->console.pip.ldc_channel = channel_id;
	}


		/* Determine the interrupt the console is bound to */
	if (!md_node_get_val(mdp, cons_nodep, MDNAME(ino), &ino)) {
		DBG(c_printf("Missing ino in console node\n"));
		*fail_codep = HVctl_e_cons_missing_ino;
		goto fail;
	}
	if (ino >= NINOSPERDEV) {
		DBG(c_printf("Invalid ino in console node\n"));
		*fail_codep = HVctl_e_cons_invalid_ino;
		goto fail;
	}
	guestp->console.pip.ino = ino;

	/*
	 * Now we go and figureout what we need to do to the
	 * guest console to update or configure its state.
	 */
	if (guestp->console.type == CONS_TYPE_UNCONFIG) {
		DBG(c_printf("\t\tElected to config console of "
		    "guest 0x%x\n", guest_id));
		guestp->console.pip.res.flags = RESF_Config;
	} else {
/* BEGIN CSTYLED */
		if (guestp->console.type != guestp->console.pip.type ||
			(guestp->console.type == CONS_TYPE_LDC &&
			guestp->console.endpt !=
				guestp->console.pip.ldc_channel) ||
			(guestp->console.vintr_mapreg->ino !=
				guestp->console.pip.ino)
#ifdef CONFIG_CN_UART /* { */
			|| ((guestp->console.type == CONS_TYPE_UART) &&
			(guestp->console.uartbase !=
				guestp->console.pip.uartbase))
#endif /* } */
			) {

			DBG(c_printf("\t\tElected to modify console of "
				"guest 0x%x\n", guest_id));
			guestp->console.pip.res.flags = RESF_Modify;
		} else {
			DBG(c_printf("\t\tElected to ignore console of "
				"guest 0x%x\n", guest_id));
			guestp->console.pip.res.flags = RESF_Noop;
		}
/* END CSTYLED */
	}

	return (HVctl_st_ok);

fail:;
	return (HVctl_st_badmd);
}
hvctl_status_t
res_network_device_parse_1(bin_md_t *mdp, md_element_t *net_nodep,
		hvctl_res_error_t *fail_codep, int *fail_res_idp)
{
	network_device_t	*netp;
	uint64_t	id;
	uint64_t	guestid;
	uint64_t	cfg_handle;
	md_element_t	*guestnodep;

	DBGNET(c_printf("Parse network node\n"));

	DBGNET(md_dump_node(mdp, net_nodep));

	if (!md_node_get_val(mdp, net_nodep, MDNAME(resource_id), &id)) {
		DBGNET(c_printf("Missing id in network node\n"));
		*fail_res_idp = 0;
		*fail_codep = HVctl_e_network_missing_prop;
		return (HVctl_st_badmd);
	}
	if (!md_node_get_val(mdp, net_nodep, MDNAME(cfghandle), &cfg_handle)) {
		DBGNET(c_printf("Missing cfg-handle in network node\n"));
		*fail_res_idp = 0;
		*fail_codep = HVctl_e_network_missing_prop;
		return (HVctl_st_badmd);
	}

	if (id >= NUM_NETWORK_DEVICES) {
		DBGNET(c_printf("Invalid id 0x%x in network node\n", id));
		*fail_res_idp = 0;
ill_prop:
		*fail_codep = HVctl_e_network_illegal_prop;
		return (HVctl_st_badmd);
	}

	DBGNET(c_printf("\tNetwork device 0x%x :\n", id));

	if (NULL == md_find_node_by_arc(mdp, net_nodep,
	    MDARC(MDNAME(back)), MDNODE(MDNAME(guest)), &guestnodep)) {
		DBGNET(c_printf("Missing back arc to guest node in "
		"network node\n"));
		*fail_codep = HVctl_e_network_missing_guest;
		goto ill_prop;
	}
	if (!md_node_get_val(mdp, guestnodep, MDNAME(resource_id), &guestid)) {
		DBGNET(c_printf("Missing resource_id in guest node\n"));
		*fail_codep = HVctl_e_guest_missing_id;
		goto ill_prop;
	}
	if (guestid >= NGUESTS) {
		DBGNET(c_printf("Invalid resource_id %d in guest node\n",
		    guestid));
		*fail_codep = HVctl_e_guest_invalid_id;
		goto ill_prop;
	}

	netp = config.network_devices;
	netp = &(netp[id]);
	netp->cfg_handle = cfg_handle;
	netp->id = id;

	/* Possible sanity checks on guest validity */
	if (netp->guestp == NULL) {
		netp->pip.res.flags = RESF_Config;
		netp->pip.guestid = guestid;
		DBGNET(c_printf("\tElected to config network device\n"));
	} else {
		guest_t	*guestp;

		guestp = config.guests;
		if (&(guestp[guestid]) != netp->guestp) {
			DBGNET(c_printf(
			    "Cannot rebind/modify a network device\n"));
			*fail_codep = HVctl_e_network_rebind_na;
			return (HVctl_st_eillegal);
		}
		DBGNET(c_printf("Elected to ignore network device\n"));
		netp->pip.res.flags = RESF_Noop;
	}

	return (HVctl_st_ok);
}
hvctl_status_t
res_pcie_bus_parse_1(bin_md_t *mdp, md_element_t *pcie_nodep,
		hvctl_res_error_t *fail_codep, int *fail_res_idp)
{
	pcie_device_t	*pciep;
	uint64_t	id;
	uint64_t	guestid;
	uint64_t	cfg_handle;
	md_element_t	*guestnodep;
	bool_t		allow_bypass;
	uint64_t	dummy;

	DBGPE(c_printf("Parse PCIE node\n"));

	DBG(md_dump_node(mdp, pcie_nodep));

	if (!md_node_get_val(mdp, pcie_nodep, MDNAME(resource_id), &id)) {
		DBGPE(c_printf("Missing id in PCIE node\n"));
		*fail_res_idp = 0;
		*fail_codep = HVctl_e_pcie_missing_prop;
		return (HVctl_st_badmd);
	}
	if (!md_node_get_val(mdp, pcie_nodep, MDNAME(cfghandle), &cfg_handle)) {
		DBGPE(c_printf("Missing cfg-handle in PCIE node\n"));
		*fail_res_idp = 0;
		*fail_codep = HVctl_e_pcie_missing_prop;
		return (HVctl_st_badmd);
	}

	if (id >= NUM_PCIE_BUSSES) {
		DBGPE(c_printf("Invalid PCIE id 0x%x in PCIE node\n", id));
		*fail_res_idp = 0;
ill_prop:
		*fail_codep = HVctl_e_pcie_illegal_prop;
		return (HVctl_st_badmd);
	}

	DBGPE(c_printf("\tPCIE bus 0x%x :\n", id));

	allow_bypass = false;
	if (md_node_get_val(mdp, pcie_nodep, MDNAME(allow_bypass), &dummy) &&
	    dummy == 1LL)
		allow_bypass = true;

	if (NULL == md_find_node_by_arc(mdp, pcie_nodep, MDARC(MDNAME(back)),
	    MDNODE(MDNAME(guest)), &guestnodep)) {
		DBG(c_printf("Missing back arc to guest node in "
		    "pcie_bus node\n"));
		*fail_codep = HVctl_e_pcie_missing_guest;
		goto ill_prop;
	}
	if (!md_node_get_val(mdp, guestnodep, MDNAME(resource_id), &guestid)) {
		DBG(c_printf("Missing resource_id in guest node\n"));
		*fail_codep = HVctl_e_guest_missing_id;
		goto ill_prop;
	}
	if (guestid >= NGUESTS) {
		DBG(c_printf("Invalid resource_id %d in guest node\n",
		    guestid));
		*fail_codep = HVctl_e_guest_invalid_id;
		goto ill_prop;
	}

	pciep = config.pcie_busses;
	pciep = &(pciep[id]);
	pciep->cfg_handle = cfg_handle;
	pciep->id = id;

	/* Possible sanity checks on guest validity */
	if (pciep->guestp == NULL) {
		pciep->pip.res.flags = RESF_Config;
		pciep->pip.guestid = guestid;
		pciep->pip.allow_bypass = allow_bypass;
		DBGPE(c_printf("\tElected to config PCIE bus\n"));
	} else {
		guest_t	*guestp;

		guestp = config.guests;
		if (&(guestp[guestid]) != pciep->guestp ||
		    pciep->allow_bypass != allow_bypass) {
			DBGPE(c_printf("Cannot rebind/modify a PCIE device\n"));
			*fail_codep = HVctl_e_pcie_rebind_na;
			return (HVctl_st_eillegal);
		}
		DBGPE(c_printf("Elected to ignore PCIE bus\n"));
		pciep->pip.res.flags = RESF_Noop;
	}

	return (HVctl_st_ok);
}
#include <fcntl.h>
#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#define	CONCAT(x,y)	__CONCAT(x,y)
#define	MDNAME(x)	CONCAT(MDALGORITHM,x)

char *
MDNAME(End)(MDNAME(_CTX) *ctx, char *buf)
{
	int i;
	unsigned char digest[16];
	static const char hex[]="0123456789abcdef";

	_DIAGASSERT(ctx != 0);

	if (buf == NULL)
		buf = malloc(33);
	if (buf == NULL)
		return (NULL);

	MDNAME(Final)(digest, ctx);

	for (i = 0; i < 16; i++) {