1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <limits.h> 30 #include <string.h> 31 #include <sys/param.h> 32 #include <topo_error.h> 33 #include <topo_tree.h> 34 #include <topo_subr.h> 35 #include <topo_file.h> 36 37 /* 38 * topo_file.c 39 * 40 * This file hides the details of any file manipulation to 41 * establish topology for a given scheme. It has two outward 42 * facing interfaces topo_file_load() and topo_file_unload(). 43 */ 44 45 #define TOPO_DEFAULT_FILE "%s-topology.xml" 46 #define PLATFORM_TOPO_PATH "%susr/platform/%s/lib/fm/topo/%s" 47 #define COMMON_TOPO_PATH "%susr/lib/fm/topo/%s" 48 49 static char _topo_file[MAXNAMELEN * 2]; 50 static char _topo_path[PATH_MAX]; 51 52 static int 53 xml_read(topo_hdl_t *hp, ttree_t *tp) 54 { 55 topo_file_t *tfp; 56 char *pplat, *pmach; 57 int err, e; 58 59 tfp = (topo_file_t *)tp->tt_file; 60 61 (void) snprintf(_topo_file, 62 2 * MAXNAMELEN, TOPO_DEFAULT_FILE, tp->tt_scheme); 63 64 /* 65 * Look for a platform-specific topology file first 66 */ 67 e = topo_prop_get_string(tp->tt_root, TOPO_PGROUP_SYSTEM, 68 TOPO_PROP_PLATFORM, &pplat, &err); 69 if (e < 0) 70 return (topo_hdl_seterrno(hp, err)); 71 (void) snprintf(_topo_path, PATH_MAX, PLATFORM_TOPO_PATH, 72 hp->th_rootdir, pplat, _topo_file); 73 74 tfp->tf_fileinfo = 75 topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme); 76 if (tfp->tf_fileinfo != NULL) { 77 topo_hdl_strfree(hp, pplat); 78 return (0); 79 } 80 81 topo_dprintf(TOPO_DBG_MOD, "failed to load topology file %s: %s\n", 82 _topo_path, topo_strerror(topo_hdl_errno(hp))); 83 84 /* 85 * No luck with the platform-specific file, how about a 86 * machine-specific one? 87 */ 88 e = topo_prop_get_string(tp->tt_root, TOPO_PGROUP_SYSTEM, 89 TOPO_PROP_MACHINE, &pmach, &err); 90 if (e < 0) { 91 topo_hdl_strfree(hp, pplat); 92 return (topo_hdl_seterrno(hp, err)); 93 } 94 /* 95 * Don't waste time trying to open the same file twice in the 96 * cases where the platform name is identical to the machine 97 * name 98 */ 99 if (strcmp(pplat, pmach) != 0) { 100 (void) snprintf(_topo_path, PATH_MAX, PLATFORM_TOPO_PATH, 101 hp->th_rootdir, pmach, _topo_file); 102 tfp->tf_fileinfo = 103 topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme); 104 } 105 if (tfp->tf_fileinfo != NULL) { 106 topo_hdl_strfree(hp, pplat); 107 topo_hdl_strfree(hp, pmach); 108 return (0); 109 } else { 110 topo_dprintf(TOPO_DBG_MOD, 111 "failed to load topology file %s: %s\n", 112 _topo_path, topo_strerror(topo_hdl_errno(hp))); 113 } 114 topo_hdl_strfree(hp, pplat); 115 topo_hdl_strfree(hp, pmach); 116 (void) snprintf(_topo_path, PATH_MAX, COMMON_TOPO_PATH, 117 hp->th_rootdir, _topo_file); 118 tfp->tf_fileinfo = 119 topo_xml_read(tfp->tf_mod, _topo_path, tp->tt_scheme); 120 if (tfp->tf_fileinfo == NULL) { 121 topo_dprintf(TOPO_DBG_MOD, 122 "failed to load topology file %s: %s\n", 123 _topo_path, topo_strerror(topo_hdl_errno(hp))); 124 return (topo_hdl_seterrno(hp, ETOPO_FILE_NOENT)); 125 } 126 return (0); 127 } 128 129 int 130 topo_file_load(topo_hdl_t *thp, topo_mod_t *mod, ttree_t *tp) 131 { 132 topo_file_t *tfp; 133 134 if ((tfp = topo_hdl_zalloc(thp, sizeof (topo_file_t))) == NULL) 135 return (topo_hdl_seterrno(thp, ETOPO_NOMEM)); 136 137 tp->tt_file = tfp; 138 139 tfp->tf_mod = mod; 140 141 if (xml_read(thp, tp) < 0) { 142 topo_file_unload(thp, tp); 143 return (-1); 144 } 145 146 if (topo_xml_enum(tfp->tf_mod, tfp->tf_fileinfo, tp->tt_root) < 0) { 147 topo_dprintf(TOPO_DBG_ERR, 148 "Failed to enumerate topology: %s\n", 149 topo_strerror(topo_hdl_errno(thp))); 150 topo_file_unload(thp, tp); 151 return (-1); 152 } 153 return (0); 154 } 155 156 void 157 topo_file_unload(topo_hdl_t *thp, ttree_t *tp) 158 { 159 topo_file_t *tfp = tp->tt_file; 160 161 if (tfp == NULL) 162 return; 163 164 if (tfp->tf_fileinfo != NULL) 165 tf_info_free(tfp->tf_mod, tfp->tf_fileinfo); 166 167 topo_hdl_free(thp, tfp, sizeof (topo_file_t)); 168 tp->tt_file = NULL; 169 } 170