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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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