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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 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 /* 30 * PICL Cherrystone platform plug-in to remove environment tree nodes 31 * if corresponding physical device is not present. For creating 32 * the picltree nodes, see: 33 * usr/src/cmd/picl/plugins/sun4u/psvc/psvcplugin/psvcplugin.c 34 */ 35 #define _POSIX_PRIORITY_SCHEDULING 1 36 37 #include <picl.h> 38 #include <picltree.h> 39 #include <stdio.h> 40 #include <time.h> 41 #include <fcntl.h> 42 #include <unistd.h> 43 #include <stdlib.h> 44 #include <stdio.h> 45 #include <libintl.h> 46 #include <limits.h> 47 #include <ctype.h> 48 #include <errno.h> 49 #include <semaphore.h> 50 #include <syslog.h> 51 #include <string.h> 52 #include <sys/types.h> 53 #include <sys/systeminfo.h> 54 #include <psvc_objects.h> 55 56 static psvc_opaque_t hdlp; 57 58 #define PSVC_PLUGIN_VERSION PICLD_PLUGIN_VERSION_1 59 60 #pragma init(psvc_psr_plugin_register) /* place in .init section */ 61 62 typedef struct { 63 char name[32]; 64 picl_nodehdl_t node; 65 } picl_psvc_t; 66 67 extern struct handle { 68 uint32_t obj_count; 69 picl_psvc_t *objects; 70 FILE *fp; 71 } psvc_hdl; 72 73 void psvc_psr_plugin_init(void); 74 void psvc_psr_plugin_fini(void); 75 76 picld_plugin_reg_t psvc_psr_reg = { 77 PSVC_PLUGIN_VERSION, 78 PICLD_PLUGIN_CRITICAL, 79 "PSVC_PSR", 80 psvc_psr_plugin_init, 81 psvc_psr_plugin_fini 82 }; 83 84 #define PSVC_INIT_ERR gettext("%s: Error in psvc_init(): %s\n") 85 #define PTREE_DELETE_NODE_ERR gettext("%s: ptree_delete_node() failed: %s\n") 86 #define PTREE_GET_NODE_ERR \ 87 gettext("%s: ptree_get_node_by_path() failed: %s\n") 88 89 extern int ptree_get_node_by_path(const char *, picl_nodehdl_t *); 90 91 /* ======================================== */ 92 struct node_file { 93 char path[256]; 94 char file[256]; 95 } dev_pr_info[] = { 96 /* Search for memory */ 97 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A0_0", 98 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a0:fru"}, 99 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A2_0", 100 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a2:fru"}, 101 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A4_0", 102 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a4:fru"}, 103 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A6_0", 104 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a6:fru"}, 105 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A8_0", 106 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,a8:fru"}, 107 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_AA_0", 108 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,aa:fru"}, 109 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_AC_0", 110 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ac:fru"}, 111 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_AE_0", 112 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@0,ae:fru"}, 113 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A0_1", 114 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a0:fru"}, 115 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A2_1", 116 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a2:fru"}, 117 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A4_1", 118 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a4:fru"}, 119 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A6_1", 120 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a6:fru"}, 121 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A8_1", 122 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,a8:fru"}, 123 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_AA_1", 124 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,aa:fru"}, 125 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_AC_1", 126 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ac:fru"}, 127 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_AE_1", 128 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@1,ae:fru"}, 129 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A0_2", 130 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a0:fru"}, 131 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A2_2", 132 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a2:fru"}, 133 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A4_2", 134 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a4:fru"}, 135 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A6_2", 136 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a6:fru"}, 137 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_A8_2", 138 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,a8:fru"}, 139 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_AA_2", 140 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,aa:fru"}, 141 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_AC_2", 142 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ac:fru"}, 143 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C02_AE_2", 144 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@2,ae:fru"}, 145 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A0_3", 146 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a0:fru"}, 147 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A2_3", 148 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a2:fru"}, 149 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A4_3", 150 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a4:fru"}, 151 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A6_3", 152 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a6:fru"}, 153 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_A8_3", 154 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,a8:fru"}, 155 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_AA_3", 156 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,aa:fru"}, 157 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_AC_3", 158 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ac:fru"}, 159 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C02_AE_3", 160 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@3,ae:fru"}, 161 /* Search for 64Kbit SPD */ 162 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD/24C64_A0_4", 163 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a0:fru"}, 164 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD/24C64_A2_4", 165 "/devices/pci@9,700000/ebus@1/i2c@1,2e/fru@4,a2:fru"}, 166 167 /* 168 * Search for CPU Module cards. We check one cpu's die temperature 169 * sensor If not present, then we remove the entire node since module 170 * cards come with two cpus in them, each cpu having a die temperature 171 * sensor 172 */ 173 174 {"/SYSTEM/MOTHERBOARD/CPU_0_2_MOD_SLOT/CPU_0_2_MOD_CARD", 175 "/devices/pci@9,700000/ebus@1/i2c@1,30/temperature@0,30:die_temp"}, 176 {"/SYSTEM/MOTHERBOARD/CPU_1_3_MOD_SLOT/CPU_1_3_MOD_CARD", 177 "/devices/pci@9,700000/ebus@1/i2c@1,30/temperature@0,52:die_temp"}, 178 {"/SYSTEM/SIB_BOARD", 179 "/devices/pci@9,700000/ebus@1/i2c@1,30/temperature@0,98:die_temp"}, 180 /* 181 * Check to see if RSC Card FRU is present. If it is not present, 182 * then RSC Card is not present, and so we remove those nodes from 183 * picl tree as well. 184 */ 185 {"/SYSTEM/RSC_SLOT/RSC_CARD/24C64_A6_5", 186 "/devices/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6:fru"}, 187 {"/SYSTEM/RSC_SLOT/RSC_CARD", 188 "/devices/pci@9,700000/ebus@1/i2c@1,30/fru@0,a6:fru"} 189 }; 190 191 #define DEV_PR_COUNT (sizeof (dev_pr_info) / sizeof (struct node_file)) 192 193 static void init_err(char *fmt, char *arg1, char *arg2) 194 { 195 char msg[256]; 196 197 sprintf(msg, fmt, arg1, arg2); 198 syslog(LOG_ERR, msg); 199 } 200 201 void 202 psvc_psr_plugin_init(void) 203 { 204 char *funcname = "psvc_plugin_psr_init"; 205 int32_t i; 206 int err; 207 boolean_t present; 208 /* 209 * So the volatile read/write routines can retrieve data from 210 * psvc or picl 211 */ 212 err = psvc_init(&hdlp); 213 if (err != 0) { 214 init_err(PSVC_INIT_ERR, funcname, strerror(errno)); 215 216 } 217 218 /* 219 * Remove nodes whose devices aren't present from the picl tree. 220 */ 221 for (i = 0; i < psvc_hdl.obj_count; ++i) { 222 picl_psvc_t *objp; 223 uint64_t features; 224 objp = &psvc_hdl.objects[i]; 225 226 err = psvc_get_attr(hdlp, objp->name, PSVC_PRESENCE_ATTR, 227 &present); 228 if (err != PSVC_SUCCESS) 229 continue; 230 err = psvc_get_attr(hdlp, objp->name, PSVC_FEATURES_ATTR, 231 &features); 232 if (err != PSVC_SUCCESS) 233 continue; 234 if ((features & (PSVC_DEV_HOTPLUG | PSVC_DEV_OPTION)) && 235 (present == PSVC_ABSENT)) { 236 err = ptree_delete_node(objp->node); 237 if (err != 0) { 238 init_err(PTREE_DELETE_NODE_ERR, funcname, 239 picl_strerror(err)); 240 return; 241 } 242 } 243 } 244 245 /* 246 * Remove PICL device nodes if their /devices file isn't present or 247 * if the device file is present but the open returns ENXIO 248 * which indicates that the node file doesn't represent a device 249 * tree node and is probably a relic from some previous boot config 250 */ 251 for (i = 0; i < DEV_PR_COUNT; ++i) { 252 picl_nodehdl_t dev_pr_node; 253 int fd; 254 fd = open(dev_pr_info[i].file, O_RDONLY); 255 if (fd != -1) { 256 close(fd); 257 continue; 258 } 259 if ((errno != ENOENT) && (errno != ENXIO)) 260 continue; 261 262 err = ptree_get_node_by_path(dev_pr_info[i].path, &dev_pr_node); 263 if (err != 0) { 264 syslog(LOG_ERR, "Bad path: %s", dev_pr_info[i].path); 265 init_err(PTREE_GET_NODE_ERR, funcname, 266 picl_strerror(err)); 267 return; 268 } 269 270 err = ptree_delete_node(dev_pr_node); 271 if (err != 0) { 272 init_err(PTREE_DELETE_NODE_ERR, funcname, 273 picl_strerror(err)); 274 return; 275 } 276 } 277 free(psvc_hdl.objects); 278 } 279 280 void 281 psvc_psr_plugin_fini(void) 282 { 283 psvc_fini(hdlp); 284 hdlp = NULL; 285 } 286 287 void 288 psvc_psr_plugin_register(void) 289 { 290 picld_plugin_register(&psvc_psr_reg); 291 } 292