182629e30SMike Christensen /*
282629e30SMike Christensen * CDDL HEADER START
382629e30SMike Christensen *
482629e30SMike Christensen * The contents of this file are subject to the terms of the
582629e30SMike Christensen * Common Development and Distribution License (the "License").
682629e30SMike Christensen * You may not use this file except in compliance with the License.
782629e30SMike Christensen *
882629e30SMike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
982629e30SMike Christensen * or http://www.opensolaris.org/os/licensing.
1082629e30SMike Christensen * See the License for the specific language governing permissions
1182629e30SMike Christensen * and limitations under the License.
1282629e30SMike Christensen *
1382629e30SMike Christensen * When distributing Covered Code, include this CDDL HEADER in each
1482629e30SMike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1582629e30SMike Christensen * If applicable, add the following below this CDDL HEADER, with the
1682629e30SMike Christensen * fields enclosed by brackets "[]" replaced with your own identifying
1782629e30SMike Christensen * information: Portions Copyright [yyyy] [name of copyright owner]
1882629e30SMike Christensen *
1982629e30SMike Christensen * CDDL HEADER END
2082629e30SMike Christensen */
2182629e30SMike Christensen /*
22*1a024a48SMike Christensen * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2382629e30SMike Christensen */
2482629e30SMike Christensen
2582629e30SMike Christensen #include <dlfcn.h>
2682629e30SMike Christensen #include <errno.h>
2782629e30SMike Christensen #include <fcntl.h>
2882629e30SMike Christensen #include <stdio.h>
2982629e30SMike Christensen #include <stdlib.h>
3082629e30SMike Christensen #include <strings.h>
3182629e30SMike Christensen #include <synch.h>
3282629e30SMike Christensen #include <thread.h>
3382629e30SMike Christensen #include <unistd.h>
3482629e30SMike Christensen #include <utility.h>
3582629e30SMike Christensen #include <sys/mdesc.h>
3682629e30SMike Christensen #include <sys/mdesc_impl.h>
3782629e30SMike Christensen #include <sys/debug.h>
3882629e30SMike Christensen #include <sys/stat.h>
3982629e30SMike Christensen #include <sys/types.h>
4082629e30SMike Christensen #include <sys/utsname.h>
4182629e30SMike Christensen
4282629e30SMike Christensen #include "ldma.h"
4382629e30SMike Christensen #include "libds.h"
4482629e30SMike Christensen #include "libv12n.h"
4582629e30SMike Christensen
4682629e30SMike Christensen /*
4782629e30SMike Christensen * sun4 support for libv12n.
4882629e30SMike Christensen *
4982629e30SMike Christensen * Non-sun4v support is minimal. The v12n_capabilities() function will
5082629e30SMike Christensen * only return 0 (not supported, not enabled, no implementation).
5182629e30SMike Christensen *
5282629e30SMike Christensen * For sun4v the support for v12n_capabilities(), v12n_domain_roles(),
5382629e30SMike Christensen * v12n_domain_name() and v12n_domain_uuid() are supported by scanning the
5482629e30SMike Christensen * MD from /dev/mdesc for specific properties. For v12n_ctrl_domain() and
5582629e30SMike Christensen * v12n_chassis_serialno(), the ldoms agent daemon (ldmad) on the control
5682629e30SMike Christensen * domain supplies the required information via the "agent-system" domain
5782629e30SMike Christensen * service.
5882629e30SMike Christensen */
5982629e30SMike Christensen
6082629e30SMike Christensen /* libds statics */
6182629e30SMike Christensen static void *v12n_ds_dlhdl = NULL;
6282629e30SMike Christensen static int (*v12n_ds_send_msg)(ds_hdl_t, void *, size_t) = NULL;
6382629e30SMike Christensen static int (*v12n_ds_clnt_reg)(ds_capability_t *, ds_ops_t *);
6482629e30SMike Christensen static int (*v12n_ds_unreg_svc)(char *, boolean_t);
6582629e30SMike Christensen
6682629e30SMike Christensen /*
6782629e30SMike Christensen * Defines to support the 'agent-system' domain service.
6882629e30SMike Christensen */
6982629e30SMike Christensen
7082629e30SMike Christensen #define LDMA_SYSTEM_NVERS \
7182629e30SMike Christensen (sizeof (v12n_ldma_system_vers) / sizeof (ds_ver_t))
7282629e30SMike Christensen static ds_ver_t v12n_ldma_system_vers[] = { { 1, 0} };
7382629e30SMike Christensen
7482629e30SMike Christensen static ds_capability_t v12n_ldma_cap = {
7582629e30SMike Christensen LDMA_NAME_SYSTEM, /* svc_id */
7682629e30SMike Christensen v12n_ldma_system_vers, /* vers */
7782629e30SMike Christensen LDMA_SYSTEM_NVERS /* nvers */
7882629e30SMike Christensen };
7982629e30SMike Christensen
8082629e30SMike Christensen static void v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg,
8182629e30SMike Christensen ds_ver_t *ver, ds_domain_hdl_t dhdl);
8282629e30SMike Christensen static void v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
8382629e30SMike Christensen size_t buflen);
8482629e30SMike Christensen
8582629e30SMike Christensen static ds_ops_t v12n_ldma_ops = {
8682629e30SMike Christensen v12n_ldma_register_handler, /* ds_reg_cb */
8782629e30SMike Christensen NULL, /* ds_unreg_cb */
8882629e30SMike Christensen v12n_ldma_data_handler, /* ds_data_cb */
8982629e30SMike Christensen NULL /* ds_cb_arg */
9082629e30SMike Christensen };
9182629e30SMike Christensen
9282629e30SMike Christensen /* v12n_ldma_cv_state values */
9382629e30SMike Christensen #define V12N_LDMA_CVINVALID -1 /* invalid value for cv_state */
9482629e30SMike Christensen #define V12N_LDMA_REGWAITING 0 /* waiting for ctrl domain reg */
9582629e30SMike Christensen #define V12N_LDMA_REGRECEIVED 1 /* received ctrl domain reg */
9682629e30SMike Christensen #define V12N_LDMA_MSGWAITING 2 /* waiting for message response */
9782629e30SMike Christensen #define V12N_LDMA_MSGRECEIVED 3 /* received message response */
9882629e30SMike Christensen #define V12N_LDMA_MSGERROR 4 /* received a bad message */
9982629e30SMike Christensen
10082629e30SMike Christensen /* 'agent-system' data used in async registration/data message handlers */
10182629e30SMike Christensen static ds_hdl_t v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
10282629e30SMike Christensen static int v12n_ldma_msgtype;
10382629e30SMike Christensen static char *v12n_ldma_msgstr;
10482629e30SMike Christensen static mutex_t v12n_ldma_lock = DEFAULTMUTEX;
10582629e30SMike Christensen static cond_t v12n_ldma_cv = DEFAULTCV;
10682629e30SMike Christensen static int v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
10782629e30SMike Christensen static mutex_t v12n_ldma_cv_lock = DEFAULTMUTEX;
10882629e30SMike Christensen
10982629e30SMike Christensen /* 'agent-system' timeout values in seconds */
11082629e30SMike Christensen static int v12n_ldma_timeout = 15;
11182629e30SMike Christensen static int v12n_ldma_sleeptime = 1;
11282629e30SMike Christensen
11382629e30SMike Christensen
11482629e30SMike Christensen #define V12N_LDOMS_SUPPORTED (V12N_CAP_SUPPORTED | V12N_CAP_ENABLED | \
11582629e30SMike Christensen V12N_CAP_IMPL_LDOMS)
11682629e30SMike Christensen
11782629e30SMike Christensen #define MD_DEVICE "/dev/mdesc"
11882629e30SMike Christensen
11982629e30SMike Christensen /*
12082629e30SMike Christensen * libv12n routines to support /dev/mdesc.
12182629e30SMike Christensen */
12282629e30SMike Christensen
12382629e30SMike Christensen /*
12482629e30SMike Christensen * Wrapper for MD free: need unused size argument.
12582629e30SMike Christensen */
12682629e30SMike Christensen /* ARGSUSED */
12782629e30SMike Christensen static void
v12n_md_free(void * buf,size_t n)12882629e30SMike Christensen v12n_md_free(void *buf, size_t n)
12982629e30SMike Christensen {
13082629e30SMike Christensen free(buf);
13182629e30SMike Christensen }
13282629e30SMike Christensen
13382629e30SMike Christensen /*
13482629e30SMike Christensen * Wrapper for MD init: read MD and invoke md_init_intern.
13582629e30SMike Christensen */
13682629e30SMike Christensen static md_t *
v12n_md_init()13782629e30SMike Christensen v12n_md_init()
13882629e30SMike Christensen {
13982629e30SMike Christensen md_t *mdp;
14082629e30SMike Christensen char *buf = NULL;
14182629e30SMike Christensen md_header_t mdh;
14282629e30SMike Christensen int md_size;
14382629e30SMike Christensen int fd;
14482629e30SMike Christensen
14582629e30SMike Christensen /*
14682629e30SMike Christensen * Open the Machine Description (MD)
14782629e30SMike Christensen */
14882629e30SMike Christensen fd = open(MD_DEVICE, O_RDONLY);
14982629e30SMike Christensen if (fd == -1) {
15082629e30SMike Christensen return (NULL);
15182629e30SMike Christensen }
15282629e30SMike Christensen
15382629e30SMike Christensen if (read(fd, &mdh, sizeof (md_header_t)) != sizeof (md_header_t))
15482629e30SMike Christensen goto errdone;
15582629e30SMike Christensen
15682629e30SMike Christensen md_size = sizeof (md_header_t) + mdh.node_blk_sz + mdh.name_blk_sz +
15782629e30SMike Christensen mdh.data_blk_sz;
15882629e30SMike Christensen
15982629e30SMike Christensen if ((buf = malloc(md_size)) == NULL)
16082629e30SMike Christensen goto errdone;
16182629e30SMike Christensen
16282629e30SMike Christensen (void) memcpy(buf, &mdh, sizeof (md_header_t));
16382629e30SMike Christensen if (read(fd, buf + sizeof (md_header_t),
16482629e30SMike Christensen md_size - sizeof (md_header_t)) != md_size - sizeof (md_header_t)) {
16582629e30SMike Christensen goto errdone;
16682629e30SMike Christensen }
16782629e30SMike Christensen
16882629e30SMike Christensen mdp = md_init_intern((uint64_t *)((void *)buf), malloc, v12n_md_free);
16982629e30SMike Christensen
17082629e30SMike Christensen (void) close(fd);
17182629e30SMike Christensen
17282629e30SMike Christensen return (mdp);
17382629e30SMike Christensen
17482629e30SMike Christensen errdone:
17582629e30SMike Christensen (void) close(fd);
17682629e30SMike Christensen free(buf);
17782629e30SMike Christensen
17882629e30SMike Christensen return (NULL);
17982629e30SMike Christensen }
18082629e30SMike Christensen
18182629e30SMike Christensen /*
18282629e30SMike Christensen * Wrapper for md_fini. Allow NULL md ptr and free MD buffer.
18382629e30SMike Christensen */
18482629e30SMike Christensen static void
v12n_md_fini(void * md)18582629e30SMike Christensen v12n_md_fini(void *md)
18682629e30SMike Christensen {
18782629e30SMike Christensen md_impl_t *mdp = (md_impl_t *)md;
18882629e30SMike Christensen
18982629e30SMike Christensen if (mdp) {
19082629e30SMike Christensen free(mdp->caddr);
19182629e30SMike Christensen (void) md_fini(md);
19282629e30SMike Christensen }
19382629e30SMike Christensen }
19482629e30SMike Christensen
19582629e30SMike Christensen /*
19682629e30SMike Christensen * See if LDoms domaining is enabled, returns 1 if enabled.
19782629e30SMike Christensen * Get the value of the 'domaining-enabled' property under the
19882629e30SMike Christensen * 'platform' node. Value of 1 => domaining is enabled.
19982629e30SMike Christensen */
20082629e30SMike Christensen static int
v12n_domaining_enabled()20182629e30SMike Christensen v12n_domaining_enabled()
20282629e30SMike Christensen {
20382629e30SMike Christensen mde_cookie_t *nodes, rootnode;
20482629e30SMike Christensen int nnodes;
20582629e30SMike Christensen uint64_t prop_val = 0;
20682629e30SMike Christensen md_t *mdp;
20782629e30SMike Christensen
20882629e30SMike Christensen if ((mdp = v12n_md_init()) == NULL) {
20982629e30SMike Christensen return (0);
21082629e30SMike Christensen }
21182629e30SMike Christensen
21282629e30SMike Christensen nnodes = md_node_count(mdp);
21382629e30SMike Christensen nodes = malloc(nnodes * sizeof (mde_cookie_t));
21482629e30SMike Christensen if (nodes == NULL) {
21582629e30SMike Christensen v12n_md_fini(mdp);
21682629e30SMike Christensen return (0);
21782629e30SMike Christensen }
21882629e30SMike Christensen
21982629e30SMike Christensen rootnode = md_root_node(mdp);
22082629e30SMike Christensen
22182629e30SMike Christensen nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
22282629e30SMike Christensen md_find_name(mdp, "fwd"), nodes);
22382629e30SMike Christensen
22482629e30SMike Christensen if (nnodes >= 1) {
22582629e30SMike Christensen (void) md_get_prop_val(mdp, nodes[0], "domaining-enabled",
22682629e30SMike Christensen &prop_val);
22782629e30SMike Christensen }
22882629e30SMike Christensen
22982629e30SMike Christensen v12n_md_fini(mdp);
23082629e30SMike Christensen free(nodes);
23182629e30SMike Christensen return (prop_val == 1);
23282629e30SMike Christensen }
23382629e30SMike Christensen
23482629e30SMike Christensen int
v12n_capabilities()23582629e30SMike Christensen v12n_capabilities()
23682629e30SMike Christensen {
23782629e30SMike Christensen struct utsname uinfo;
23882629e30SMike Christensen struct stat st;
23982629e30SMike Christensen int cap;
24082629e30SMike Christensen
24182629e30SMike Christensen /*
24282629e30SMike Christensen * Check if this is an LDoms system. When using LDoms each
24382629e30SMike Christensen * domain should have a /dev/mdesc device providing access to
24482629e30SMike Christensen * the Machine Description (MD) of the domain. If this device
24582629e30SMike Christensen * does not exist then this is not an LDoms system.
24682629e30SMike Christensen */
24782629e30SMike Christensen if (uname(&uinfo) == -1 || strcmp(uinfo.machine, "sun4v")) {
24882629e30SMike Christensen /*
24982629e30SMike Christensen * Not sun4v -> LDoms not supported
25082629e30SMike Christensen */
25182629e30SMike Christensen cap = 0;
25282629e30SMike Christensen } else if (stat(MD_DEVICE, &st) == 0) {
25382629e30SMike Christensen /*
25482629e30SMike Christensen * sun4v + /dev/mdesc exists -> Check if LDoms enabled
25582629e30SMike Christensen * via the 'domaining-enabled' property.
25682629e30SMike Christensen */
25782629e30SMike Christensen cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS |
25882629e30SMike Christensen (v12n_domaining_enabled() ? V12N_CAP_ENABLED : 0));
25982629e30SMike Christensen } else if (errno == ENOENT) {
26082629e30SMike Christensen /*
26182629e30SMike Christensen * sun4v + /dev/mdesc does not exist -> LDoms supported
26282629e30SMike Christensen * but not enabled.
26382629e30SMike Christensen */
26482629e30SMike Christensen cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS);
26582629e30SMike Christensen }
26682629e30SMike Christensen
26782629e30SMike Christensen return (cap);
26882629e30SMike Christensen }
26982629e30SMike Christensen
27082629e30SMike Christensen /*
27182629e30SMike Christensen * Routines to support v12n_domain_roles.
27282629e30SMike Christensen */
27382629e30SMike Christensen static int
v12n_scan_md_nodes(md_t * mdp,char * node_name,char * node_str_prop,char ** props)27482629e30SMike Christensen v12n_scan_md_nodes(md_t *mdp, char *node_name, char *node_str_prop,
27582629e30SMike Christensen char **props)
27682629e30SMike Christensen {
27782629e30SMike Christensen mde_cookie_t *nodes, rootnode;
27882629e30SMike Christensen int nnodes, i, j;
27982629e30SMike Christensen char *prop_str;
28082629e30SMike Christensen
28182629e30SMike Christensen nnodes = md_node_count(mdp);
28282629e30SMike Christensen nodes = malloc(nnodes * sizeof (mde_cookie_t));
28382629e30SMike Christensen if (nodes == NULL) {
28482629e30SMike Christensen return (0);
28582629e30SMike Christensen }
28682629e30SMike Christensen
28782629e30SMike Christensen rootnode = md_root_node(mdp);
28882629e30SMike Christensen
28982629e30SMike Christensen nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, node_name),
29082629e30SMike Christensen md_find_name(mdp, "fwd"), nodes);
29182629e30SMike Christensen
29282629e30SMike Christensen if (node_str_prop == NULL)
29382629e30SMike Christensen return (nnodes > 0);
29482629e30SMike Christensen
29582629e30SMike Christensen for (i = 0; i < nnodes; i++) {
29682629e30SMike Christensen if (md_get_prop_str(mdp, nodes[i], node_str_prop, &prop_str))
29782629e30SMike Christensen continue;
29882629e30SMike Christensen for (j = 0; props[j] != NULL; j++) {
29982629e30SMike Christensen if (strcmp(prop_str, props[j]) == 0) {
30082629e30SMike Christensen free(nodes);
30182629e30SMike Christensen return (1);
30282629e30SMike Christensen }
30382629e30SMike Christensen }
30482629e30SMike Christensen }
30582629e30SMike Christensen free(nodes);
30682629e30SMike Christensen return (0);
30782629e30SMike Christensen }
30882629e30SMike Christensen
30982629e30SMike Christensen /*
31082629e30SMike Christensen * Check if MD has a hypervisor access point, returns 1 if true.
31182629e30SMike Christensen * Check the MD for a 'virtual-device-port' node whose 'vldc-svc-name' is
31282629e30SMike Christensen * 'hvctl'.
31382629e30SMike Christensen */
31482629e30SMike Christensen static int
v12n_check_hv_access(md_t * mdp)31582629e30SMike Christensen v12n_check_hv_access(md_t *mdp)
31682629e30SMike Christensen {
31782629e30SMike Christensen static char *hvctl_str[] = {
31882629e30SMike Christensen "hvctl",
31982629e30SMike Christensen NULL
32082629e30SMike Christensen };
32182629e30SMike Christensen
32282629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "virtual-device-port", "vldc-svc-name",
32382629e30SMike Christensen hvctl_str));
32482629e30SMike Christensen }
32582629e30SMike Christensen
32682629e30SMike Christensen /*
32782629e30SMike Christensen * Check if MD has a virtual device service (vcc, vsw, vds), returns 1 if true.
32882629e30SMike Christensen * Need to check all the MD 'virtual-device' nodes for a 'device-type' property
32982629e30SMike Christensen * of 'vcc', 'vsw' or 'vds'.
33082629e30SMike Christensen */
33182629e30SMike Christensen static int
v12n_check_virtual_service(md_t * mdp)33282629e30SMike Christensen v12n_check_virtual_service(md_t *mdp)
33382629e30SMike Christensen {
33482629e30SMike Christensen static char *vdevs[] = {
33582629e30SMike Christensen "vcc",
33682629e30SMike Christensen "vsw",
33782629e30SMike Christensen "vds",
33882629e30SMike Christensen NULL
33982629e30SMike Christensen };
34082629e30SMike Christensen
34182629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "virtual-device", "device-type",
34282629e30SMike Christensen vdevs));
34382629e30SMike Christensen }
34482629e30SMike Christensen
34582629e30SMike Christensen /*
34682629e30SMike Christensen * Check if MD has an physical I/O device node, returns 1 if true.
34782629e30SMike Christensen */
34882629e30SMike Christensen static int
v12n_check_io_service(md_t * mdp)34982629e30SMike Christensen v12n_check_io_service(md_t *mdp)
35082629e30SMike Christensen {
35182629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "iodevice", NULL, NULL));
35282629e30SMike Christensen }
35382629e30SMike Christensen
35482629e30SMike Christensen /*
35582629e30SMike Christensen * Check if a MD node is root PCI device, returns 1 if true.
35682629e30SMike Christensen * Need to check all the MD 'iodevice' nodes for a 'device-type' property
35782629e30SMike Christensen * of 'pciex'.
35882629e30SMike Christensen */
35982629e30SMike Christensen static int
v12n_check_root(md_t * mdp)36082629e30SMike Christensen v12n_check_root(md_t *mdp)
36182629e30SMike Christensen {
36282629e30SMike Christensen static char *pciex[] = {
36382629e30SMike Christensen "pciex",
36482629e30SMike Christensen NULL
36582629e30SMike Christensen };
36682629e30SMike Christensen
36782629e30SMike Christensen return (v12n_scan_md_nodes(mdp, "iodevice", "device-type", pciex));
36882629e30SMike Christensen }
36982629e30SMike Christensen
37082629e30SMike Christensen /*
37182629e30SMike Christensen * Get the domain roles for the domain.
37282629e30SMike Christensen */
37382629e30SMike Christensen int
v12n_domain_roles()37482629e30SMike Christensen v12n_domain_roles()
37582629e30SMike Christensen {
37682629e30SMike Christensen md_t *mdp;
37782629e30SMike Christensen int roles = 0;
37882629e30SMike Christensen
37982629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
38082629e30SMike Christensen errno = ENOTSUP;
38182629e30SMike Christensen return (-1);
38282629e30SMike Christensen }
38382629e30SMike Christensen
38482629e30SMike Christensen if ((mdp = v12n_md_init()) == NULL) {
38582629e30SMike Christensen errno = EACCES;
38682629e30SMike Christensen return (-1);
38782629e30SMike Christensen }
38882629e30SMike Christensen
38982629e30SMike Christensen if (v12n_check_hv_access(mdp))
39082629e30SMike Christensen roles |= V12N_ROLE_CONTROL;
39182629e30SMike Christensen
39282629e30SMike Christensen if (v12n_check_virtual_service(mdp))
39382629e30SMike Christensen roles |= V12N_ROLE_SERVICE;
39482629e30SMike Christensen
39582629e30SMike Christensen if (v12n_check_io_service(mdp))
39682629e30SMike Christensen roles |= V12N_ROLE_IO;
39782629e30SMike Christensen
39882629e30SMike Christensen if (v12n_check_root(mdp))
39982629e30SMike Christensen roles |= V12N_ROLE_ROOT;
40082629e30SMike Christensen
40182629e30SMike Christensen v12n_md_fini(mdp);
40282629e30SMike Christensen
40382629e30SMike Christensen return (roles);
40482629e30SMike Christensen }
40582629e30SMike Christensen
40682629e30SMike Christensen /*
40782629e30SMike Christensen * Get domain name from MD's virtual domain service node, returns 1 on success.
40882629e30SMike Christensen * The domain name is a string property 'vlds-domain-name' under the
40982629e30SMike Christensen * 'virtual-device' device node whose name is 'virtual-domain-service'.
41082629e30SMike Christensen */
41182629e30SMike Christensen static int
v12n_get_md_domain_name(md_t * mdp,char ** vds_dnamep)41282629e30SMike Christensen v12n_get_md_domain_name(md_t *mdp, char **vds_dnamep)
41382629e30SMike Christensen {
41482629e30SMike Christensen mde_cookie_t *vdev_nodes, rootnode;
41582629e30SMike Christensen int list_size, nvdevs, num_nodes, i, rv;
41682629e30SMike Christensen char *vldc_name;
41782629e30SMike Christensen
41882629e30SMike Christensen num_nodes = md_node_count(mdp);
41982629e30SMike Christensen list_size = num_nodes * sizeof (mde_cookie_t);
42082629e30SMike Christensen vdev_nodes = malloc(list_size);
42182629e30SMike Christensen if (vdev_nodes == NULL) {
42282629e30SMike Christensen return (0);
42382629e30SMike Christensen }
42482629e30SMike Christensen
42582629e30SMike Christensen rootnode = md_root_node(mdp);
42682629e30SMike Christensen
42782629e30SMike Christensen nvdevs = md_scan_dag(mdp, rootnode, md_find_name(mdp, "virtual-device"),
42882629e30SMike Christensen md_find_name(mdp, "fwd"), vdev_nodes);
42982629e30SMike Christensen
43082629e30SMike Christensen rv = 0;
43182629e30SMike Christensen for (i = 0; i < nvdevs; i++) {
43282629e30SMike Christensen if (md_get_prop_str(mdp, vdev_nodes[i], "name", &vldc_name))
43382629e30SMike Christensen continue;
43482629e30SMike Christensen if (strcmp(vldc_name, "virtual-domain-service") == 0) {
43582629e30SMike Christensen rv = (md_get_prop_str(mdp, vdev_nodes[i],
43682629e30SMike Christensen "vlds-domain-name", vds_dnamep) == 0);
43782629e30SMike Christensen break;
43882629e30SMike Christensen }
43982629e30SMike Christensen }
44082629e30SMike Christensen free(vdev_nodes);
44182629e30SMike Christensen return (rv);
44282629e30SMike Christensen }
44382629e30SMike Christensen
44482629e30SMike Christensen /*
44582629e30SMike Christensen * String copyout utility.
44682629e30SMike Christensen */
44782629e30SMike Christensen static size_t
v12n_string_copyout(char * sout,char * sfrom,size_t count)44882629e30SMike Christensen v12n_string_copyout(char *sout, char *sfrom, size_t count)
44982629e30SMike Christensen {
45082629e30SMike Christensen size_t ret = strlen(sfrom) + 1;
45182629e30SMike Christensen
45282629e30SMike Christensen if (sout != NULL && count > 0) {
45382629e30SMike Christensen count = MIN(ret, count);
45482629e30SMike Christensen (void) memcpy(sout, sfrom, count);
45582629e30SMike Christensen }
45682629e30SMike Christensen return (ret);
45782629e30SMike Christensen }
45882629e30SMike Christensen
45982629e30SMike Christensen /*
46082629e30SMike Christensen * Get the domain name of this domain.
46182629e30SMike Christensen */
46282629e30SMike Christensen size_t
v12n_domain_name(char * buf,size_t count)46382629e30SMike Christensen v12n_domain_name(char *buf, size_t count)
46482629e30SMike Christensen {
46582629e30SMike Christensen md_t *mdp = NULL;
46682629e30SMike Christensen char *ldmname;
46782629e30SMike Christensen int rv = -1;
46882629e30SMike Christensen
46982629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
47082629e30SMike Christensen errno = ENOTSUP;
47182629e30SMike Christensen } else if ((mdp = v12n_md_init()) == NULL) {
47282629e30SMike Christensen errno = EACCES;
47382629e30SMike Christensen } else if (!v12n_get_md_domain_name(mdp, &ldmname)) {
47482629e30SMike Christensen errno = ESRCH;
47582629e30SMike Christensen } else {
47682629e30SMike Christensen rv = v12n_string_copyout(buf, ldmname, count);
47782629e30SMike Christensen }
47882629e30SMike Christensen
47982629e30SMike Christensen v12n_md_fini(mdp);
48082629e30SMike Christensen return (rv);
48182629e30SMike Christensen }
48282629e30SMike Christensen
48382629e30SMike Christensen /*
48482629e30SMike Christensen * Get UUID string from MD, returns 1 on success.
48582629e30SMike Christensen * The UUID is a string property 'uuid' under the 'platform' node of the MD.
48682629e30SMike Christensen */
48782629e30SMike Christensen static int
v12n_get_md_uuid_str(md_t * mdp,char ** uuid_strp)48882629e30SMike Christensen v12n_get_md_uuid_str(md_t *mdp, char **uuid_strp)
48982629e30SMike Christensen {
49082629e30SMike Christensen mde_cookie_t *plat_nodes, rootnode;
49182629e30SMike Christensen int list_size, npnodes, num_nodes, rv;
49282629e30SMike Christensen
49382629e30SMike Christensen num_nodes = md_node_count(mdp);
49482629e30SMike Christensen list_size = num_nodes * sizeof (mde_cookie_t);
49582629e30SMike Christensen plat_nodes = malloc(list_size);
49682629e30SMike Christensen if (plat_nodes == NULL) {
49782629e30SMike Christensen return (0);
49882629e30SMike Christensen }
49982629e30SMike Christensen
50082629e30SMike Christensen rootnode = md_root_node(mdp);
50182629e30SMike Christensen
50282629e30SMike Christensen npnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
50382629e30SMike Christensen md_find_name(mdp, "fwd"), plat_nodes);
50482629e30SMike Christensen
50582629e30SMike Christensen if (npnodes >= 1)
50682629e30SMike Christensen rv = !md_get_prop_str(mdp, plat_nodes[0], "uuid", uuid_strp);
50782629e30SMike Christensen else
50882629e30SMike Christensen rv = 0;
50982629e30SMike Christensen
51082629e30SMike Christensen free(plat_nodes);
51182629e30SMike Christensen return (rv);
51282629e30SMike Christensen }
51382629e30SMike Christensen
51482629e30SMike Christensen /*
51582629e30SMike Christensen * Get the domain UUID.
51682629e30SMike Christensen */
51782629e30SMike Christensen int
v12n_domain_uuid(uuid_t uuid)51882629e30SMike Christensen v12n_domain_uuid(uuid_t uuid)
51982629e30SMike Christensen {
52082629e30SMike Christensen md_t *mdp = NULL;
52182629e30SMike Christensen char *uuid_str;
52282629e30SMike Christensen int rv = -1;
52382629e30SMike Christensen
52482629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
52582629e30SMike Christensen errno = ENOTSUP;
52682629e30SMike Christensen } else if ((mdp = v12n_md_init()) == NULL) {
52782629e30SMike Christensen errno = EACCES;
52882629e30SMike Christensen } else if (!v12n_get_md_uuid_str(mdp, &uuid_str)) {
52982629e30SMike Christensen errno = ESRCH;
53082629e30SMike Christensen } else {
53182629e30SMike Christensen rv = uuid_parse(uuid_str, uuid);
53282629e30SMike Christensen }
53382629e30SMike Christensen
53482629e30SMike Christensen v12n_md_fini(mdp);
53582629e30SMike Christensen
53682629e30SMike Christensen return (rv);
53782629e30SMike Christensen }
53882629e30SMike Christensen
53982629e30SMike Christensen /*
54082629e30SMike Christensen * Send 'agent-sytem' request message.
54182629e30SMike Christensen */
54282629e30SMike Christensen static int
v12n_ldma_send_request()54382629e30SMike Christensen v12n_ldma_send_request()
54482629e30SMike Christensen {
54582629e30SMike Christensen ldma_message_header_t ldmamsg;
54682629e30SMike Christensen
54782629e30SMike Christensen if (v12n_ds_send_msg == NULL || v12n_ldma_ctrl_hdl == DS_INVALID_HDL)
54882629e30SMike Christensen return (ENOENT);
54982629e30SMike Christensen
55082629e30SMike Christensen ldmamsg.msg_num = 0;
55182629e30SMike Christensen ldmamsg.msg_type = v12n_ldma_msgtype;
55282629e30SMike Christensen ldmamsg.msg_info = 0;
55382629e30SMike Christensen return (v12n_ds_send_msg(v12n_ldma_ctrl_hdl, (char *)&ldmamsg,
55482629e30SMike Christensen sizeof (ldmamsg)));
55582629e30SMike Christensen }
55682629e30SMike Christensen
55782629e30SMike Christensen /*
55882629e30SMike Christensen * 'agent-system' registration handler.
55982629e30SMike Christensen * If we get a registration from the control domain (domain 0), then send
56082629e30SMike Christensen * the requested message. Otherwise, ignore the registration.
56182629e30SMike Christensen */
56282629e30SMike Christensen /* ARGSUSED */
56382629e30SMike Christensen static void
v12n_ldma_register_handler(ds_hdl_t hdl,ds_cb_arg_t arg,ds_ver_t * ver,ds_domain_hdl_t dhdl)56482629e30SMike Christensen v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
56582629e30SMike Christensen ds_domain_hdl_t dhdl)
56682629e30SMike Christensen {
56782629e30SMike Christensen
56882629e30SMike Christensen /* got registration from control domain */
56982629e30SMike Christensen if (dhdl == 0) {
57082629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock);
57182629e30SMike Christensen if (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
57282629e30SMike Christensen v12n_ldma_ctrl_hdl = hdl;
57382629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_REGRECEIVED;
57482629e30SMike Christensen (void) cond_signal(&v12n_ldma_cv);
57582629e30SMike Christensen }
57682629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
57782629e30SMike Christensen }
57882629e30SMike Christensen }
57982629e30SMike Christensen
58082629e30SMike Christensen /*
58182629e30SMike Christensen * 'agent-system' data handler.
58282629e30SMike Christensen */
58382629e30SMike Christensen /* ARGSUSED */
58482629e30SMike Christensen static void
v12n_ldma_data_handler(ds_hdl_t hdl,ds_cb_arg_t arg,void * buf,size_t buflen)58582629e30SMike Christensen v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
58682629e30SMike Christensen size_t buflen)
58782629e30SMike Christensen {
58882629e30SMike Christensen char *data;
58982629e30SMike Christensen ldma_message_header_t *ldmp;
59082629e30SMike Christensen int n;
59182629e30SMike Christensen int cv_state = V12N_LDMA_MSGERROR;
59282629e30SMike Christensen
59382629e30SMike Christensen /*
59482629e30SMike Christensen * Ignore any message not from the control domain.
59582629e30SMike Christensen */
59682629e30SMike Christensen if (v12n_ldma_ctrl_hdl != hdl)
59782629e30SMike Christensen return;
59882629e30SMike Christensen
59982629e30SMike Christensen /*
60082629e30SMike Christensen * Ignore any unexpected message.
60182629e30SMike Christensen */
60282629e30SMike Christensen if (buflen < LDMA_MESSAGE_HEADER_SIZE)
60382629e30SMike Christensen return;
60482629e30SMike Christensen
60582629e30SMike Christensen /*
60682629e30SMike Christensen * Ignore message with unexpected msgnum.
60782629e30SMike Christensen */
60882629e30SMike Christensen ldmp = (ldma_message_header_t *)buf;
60982629e30SMike Christensen if (ldmp->msg_num != 0)
61082629e30SMike Christensen return;
61182629e30SMike Christensen
61282629e30SMike Christensen switch (ldmp->msg_type) {
61382629e30SMike Christensen
61482629e30SMike Christensen case LDMA_MSG_RESULT:
61582629e30SMike Christensen if (ldmp->msg_info == 0 ||
61682629e30SMike Christensen ldmp->msg_info > LDMA_MESSAGE_DLEN(buflen)) {
61782629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR;
61882629e30SMike Christensen break;
61982629e30SMike Christensen }
62082629e30SMike Christensen data = LDMA_HDR2DATA(buf);
62182629e30SMike Christensen
62282629e30SMike Christensen /* ensure that data ends with a '\0' */
62382629e30SMike Christensen data[ldmp->msg_info - 1] = '\0';
62482629e30SMike Christensen switch (v12n_ldma_msgtype) {
62582629e30SMike Christensen
62682629e30SMike Christensen case LDMA_MSGSYS_GET_SYSINFO:
62782629e30SMike Christensen /*
62882629e30SMike Christensen * Control domain nodename is second string in the
62982629e30SMike Christensen * message. Make sure there is enough data in the msg
63082629e30SMike Christensen * to have a second string.
63182629e30SMike Christensen */
63282629e30SMike Christensen n = strlen(data);
63382629e30SMike Christensen if (LDMA_MESSAGE_DLEN(buflen) <= n + 3) {
63482629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR;
63582629e30SMike Christensen break;
63682629e30SMike Christensen }
63782629e30SMike Christensen data += n + 1;
63882629e30SMike Christensen if ((v12n_ldma_msgstr = strdup(data)) == NULL)
63982629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR;
64082629e30SMike Christensen else
64182629e30SMike Christensen cv_state = V12N_LDMA_MSGRECEIVED;
64282629e30SMike Christensen break;
64382629e30SMike Christensen
64482629e30SMike Christensen case LDMA_MSGSYS_GET_CHASSISNO:
64582629e30SMike Christensen if ((v12n_ldma_msgstr = strdup(data)) == NULL)
64682629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR;
64782629e30SMike Christensen else
64882629e30SMike Christensen cv_state = V12N_LDMA_MSGRECEIVED;
64982629e30SMike Christensen break;
65082629e30SMike Christensen
65182629e30SMike Christensen default:
65282629e30SMike Christensen /* v12n_ldma_msgtype must be valid */
65382629e30SMike Christensen ASSERT(0);
65482629e30SMike Christensen }
65582629e30SMike Christensen break;
65682629e30SMike Christensen
65782629e30SMike Christensen case LDMA_MSG_ERROR:
65882629e30SMike Christensen cv_state = V12N_LDMA_MSGERROR;
65982629e30SMike Christensen break;
66082629e30SMike Christensen
66182629e30SMike Christensen default:
66282629e30SMike Christensen /* unexpected message, ignored */
66382629e30SMike Christensen return;
66482629e30SMike Christensen }
66582629e30SMike Christensen
66682629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock);
66782629e30SMike Christensen v12n_ldma_cv_state = cv_state;
66882629e30SMike Christensen (void) cond_signal(&v12n_ldma_cv);
66982629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
67082629e30SMike Christensen }
67182629e30SMike Christensen
67282629e30SMike Christensen
67382629e30SMike Christensen /*
67482629e30SMike Christensen * libds doesn't exist on non-sun4v, dynamically load it and get the
67582629e30SMike Christensen * function pointers to the needed lib functions.
67682629e30SMike Christensen */
67782629e30SMike Christensen static int
v12n_libds_init(void)67882629e30SMike Christensen v12n_libds_init(void)
67982629e30SMike Christensen {
68082629e30SMike Christensen if (v12n_ds_dlhdl != NULL) {
68182629e30SMike Christensen if (v12n_ds_clnt_reg == NULL || v12n_ds_send_msg == NULL ||
68282629e30SMike Christensen v12n_ds_unreg_svc == NULL)
68382629e30SMike Christensen return (ENOENT);
68482629e30SMike Christensen return (0);
68582629e30SMike Christensen }
68682629e30SMike Christensen
68782629e30SMike Christensen if ((v12n_ds_dlhdl = dlopen("libds.so.1",
68882629e30SMike Christensen RTLD_NOW | RTLD_GLOBAL)) == NULL)
68982629e30SMike Christensen return (ENOENT);
69082629e30SMike Christensen
69182629e30SMike Christensen if ((v12n_ds_clnt_reg = (int (*)(ds_capability_t *, ds_ops_t *))
69282629e30SMike Christensen dlsym(v12n_ds_dlhdl, "ds_clnt_reg")) == NULL)
69382629e30SMike Christensen return (ENOENT);
69482629e30SMike Christensen
69582629e30SMike Christensen if ((v12n_ds_send_msg = (int (*)(ds_hdl_t, void *, size_t))
69682629e30SMike Christensen dlsym(v12n_ds_dlhdl, "ds_send_msg")) == NULL)
69782629e30SMike Christensen return (ENOENT);
69882629e30SMike Christensen
69982629e30SMike Christensen if ((v12n_ds_unreg_svc = (int (*)(char *, boolean_t))
70082629e30SMike Christensen dlsym(v12n_ds_dlhdl, "ds_unreg_svc")) == NULL)
70182629e30SMike Christensen return (ENOENT);
70282629e30SMike Christensen
70382629e30SMike Christensen return (0);
70482629e30SMike Christensen }
70582629e30SMike Christensen
70682629e30SMike Christensen /*
70782629e30SMike Christensen * Initiate and wait for an ldmad 'agent-system' domain service.
70882629e30SMike Christensen * Dynamically load libds, register the client 'agent-system' service
70982629e30SMike Christensen * and wait for a specified amount of time for the 'agent-system'
71082629e30SMike Christensen * service on the control domain to respond to the request.
71182629e30SMike Christensen */
71282629e30SMike Christensen static int
v12n_get_ldma_system_msg(int msgtype,char ** strp)71382629e30SMike Christensen v12n_get_ldma_system_msg(int msgtype, char **strp)
71482629e30SMike Christensen {
71582629e30SMike Christensen int tout;
71682629e30SMike Christensen int err = 0;
71782629e30SMike Christensen timestruc_t timeout;
71882629e30SMike Christensen
71982629e30SMike Christensen /*
72082629e30SMike Christensen * Ensure that there's only one thread trying to do a
72182629e30SMike Christensen * 'agent-system' client registration/message at a time.
72282629e30SMike Christensen */
72382629e30SMike Christensen (void) mutex_lock(&v12n_ldma_lock);
724*1a024a48SMike Christensen if ((err = v12n_libds_init()) != 0) {
725*1a024a48SMike Christensen (void) mutex_unlock(&v12n_ldma_lock);
726*1a024a48SMike Christensen return (err);
727*1a024a48SMike Christensen }
72882629e30SMike Christensen
72982629e30SMike Christensen v12n_ldma_msgtype = msgtype;
73082629e30SMike Christensen v12n_ldma_msgstr = NULL;
73182629e30SMike Christensen
73282629e30SMike Christensen /* initialize v12n_ldma_cv_state variable before registering service */
73382629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock);
73482629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_REGWAITING;
73582629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
73682629e30SMike Christensen
73782629e30SMike Christensen /*
73882629e30SMike Christensen * Other instances may be trying to load the "agent-system" service.
73982629e30SMike Christensen * If a collision happens (EBUSY error), wait and try again.
74082629e30SMike Christensen */
74182629e30SMike Christensen for (tout = 0; tout < v12n_ldma_timeout; tout += v12n_ldma_sleeptime) {
74282629e30SMike Christensen if ((err = v12n_ds_clnt_reg(&v12n_ldma_cap,
74382629e30SMike Christensen &v12n_ldma_ops)) == 0)
74482629e30SMike Christensen break;
74582629e30SMike Christensen if (err != EALREADY) {
74682629e30SMike Christensen goto done;
74782629e30SMike Christensen }
74882629e30SMike Christensen (void) sleep(v12n_ldma_sleeptime);
74982629e30SMike Christensen }
75082629e30SMike Christensen
75182629e30SMike Christensen if (tout >= v12n_ldma_timeout) {
75282629e30SMike Christensen err = EBUSY;
75382629e30SMike Christensen goto done;
75482629e30SMike Christensen }
75582629e30SMike Christensen
75682629e30SMike Christensen /*
75782629e30SMike Christensen * Wait for control domain registration.
75882629e30SMike Christensen */
75982629e30SMike Christensen timeout.tv_sec = v12n_ldma_timeout;
76082629e30SMike Christensen timeout.tv_nsec = 0;
76182629e30SMike Christensen
76282629e30SMike Christensen (void) mutex_lock(&v12n_ldma_cv_lock);
76382629e30SMike Christensen while (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
76482629e30SMike Christensen if ((err = cond_reltimedwait(&v12n_ldma_cv,
76582629e30SMike Christensen &v12n_ldma_cv_lock, &timeout)) != EINTR)
76682629e30SMike Christensen break;
76782629e30SMike Christensen }
76882629e30SMike Christensen
76982629e30SMike Christensen /*
77082629e30SMike Christensen * Check for timeout or an error.
77182629e30SMike Christensen */
77282629e30SMike Christensen if (v12n_ldma_cv_state != V12N_LDMA_REGRECEIVED) {
77382629e30SMike Christensen if (err == 0)
77482629e30SMike Christensen err = EPROTO;
77582629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
77682629e30SMike Christensen goto done;
77782629e30SMike Christensen }
77882629e30SMike Christensen
77982629e30SMike Christensen /*
78082629e30SMike Christensen * Received a registration request, send the request message.
78182629e30SMike Christensen */
78282629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_MSGWAITING;
78382629e30SMike Christensen if ((err = v12n_ldma_send_request()) != 0) {
78482629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
78582629e30SMike Christensen goto done;
78682629e30SMike Christensen }
78782629e30SMike Christensen
78882629e30SMike Christensen while (v12n_ldma_cv_state == V12N_LDMA_MSGWAITING) {
78982629e30SMike Christensen if ((err = cond_reltimedwait(&v12n_ldma_cv,
79082629e30SMike Christensen &v12n_ldma_cv_lock, &timeout)) != EINTR)
79182629e30SMike Christensen break;
79282629e30SMike Christensen }
79382629e30SMike Christensen
79482629e30SMike Christensen if (v12n_ldma_cv_state != V12N_LDMA_MSGRECEIVED) {
79582629e30SMike Christensen if (err == 0)
79682629e30SMike Christensen err = EPROTO;
79782629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
79882629e30SMike Christensen goto done;
79982629e30SMike Christensen }
80082629e30SMike Christensen
80182629e30SMike Christensen v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
80282629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_cv_lock);
80382629e30SMike Christensen
80482629e30SMike Christensen /*
80582629e30SMike Christensen * If v12n_ldma_msgstr is set, a valid data response was seen.
80682629e30SMike Christensen */
80782629e30SMike Christensen if (v12n_ldma_msgstr == NULL)
80882629e30SMike Christensen err = ENODATA;
80982629e30SMike Christensen else {
81082629e30SMike Christensen if (*v12n_ldma_msgstr == '\0' ||
81182629e30SMike Christensen (*strp = strdup(v12n_ldma_msgstr)) == NULL)
81282629e30SMike Christensen err = ENODATA;
81382629e30SMike Christensen free(v12n_ldma_msgstr);
81482629e30SMike Christensen v12n_ldma_msgstr = NULL;
81582629e30SMike Christensen }
81682629e30SMike Christensen
81782629e30SMike Christensen done:
81882629e30SMike Christensen v12n_ds_unreg_svc(LDMA_NAME_SYSTEM, B_TRUE);
81982629e30SMike Christensen v12n_ldma_msgtype = -1;
82082629e30SMike Christensen v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
82182629e30SMike Christensen (void) mutex_unlock(&v12n_ldma_lock);
82282629e30SMike Christensen
82382629e30SMike Christensen return (err);
82482629e30SMike Christensen }
82582629e30SMike Christensen
82682629e30SMike Christensen /*
82782629e30SMike Christensen * Get the nodename of the control domain. Returns the equivalent
82882629e30SMike Christensen * of 'uname -n' on the control domain.
82982629e30SMike Christensen * This is obtained via the 'agent-system' domain service provided
83082629e30SMike Christensen * by ldmad.
83182629e30SMike Christensen */
83282629e30SMike Christensen size_t
v12n_ctrl_domain(char * buf,size_t count)83382629e30SMike Christensen v12n_ctrl_domain(char *buf, size_t count)
83482629e30SMike Christensen {
83582629e30SMike Christensen char *str;
83682629e30SMike Christensen int err;
83782629e30SMike Christensen size_t rv = (size_t)(-1);
83882629e30SMike Christensen
83982629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
84082629e30SMike Christensen errno = ENOTSUP;
84182629e30SMike Christensen } else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_SYSINFO,
84282629e30SMike Christensen &str)) != 0) {
84382629e30SMike Christensen errno = err;
84482629e30SMike Christensen } else {
84582629e30SMike Christensen rv = v12n_string_copyout(buf, str, count);
84682629e30SMike Christensen }
84782629e30SMike Christensen return (rv);
84882629e30SMike Christensen }
84982629e30SMike Christensen
85082629e30SMike Christensen /*
85182629e30SMike Christensen * Get the Chassis serial number from the Control Domain.
85282629e30SMike Christensen * This is obtained via the 'agent-system' domain service provided
85382629e30SMike Christensen * by ldmad.
85482629e30SMike Christensen */
85582629e30SMike Christensen size_t
v12n_chassis_serialno(char * buf,size_t count)85682629e30SMike Christensen v12n_chassis_serialno(char *buf, size_t count)
85782629e30SMike Christensen {
85882629e30SMike Christensen char *str;
85982629e30SMike Christensen int err;
86082629e30SMike Christensen size_t rv = (size_t)(-1);
86182629e30SMike Christensen
86282629e30SMike Christensen if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
86382629e30SMike Christensen errno = ENOTSUP;
86482629e30SMike Christensen } else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_CHASSISNO,
86582629e30SMike Christensen &str)) != 0) {
86682629e30SMike Christensen errno = err;
86782629e30SMike Christensen } else {
86882629e30SMike Christensen rv = v12n_string_copyout(buf, str, count);
86982629e30SMike Christensen }
87082629e30SMike Christensen return (rv);
87182629e30SMike Christensen }
872