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 /* 28 * PICL Littleneck platform plug-in to create environment tree nodes. 29 */ 30 #define _POSIX_PRIORITY_SCHEDULING 1 31 32 #include <picl.h> 33 #include <picltree.h> 34 #include <stdio.h> 35 #include <time.h> 36 #include <fcntl.h> 37 #include <unistd.h> 38 #include <stdlib.h> 39 #include <stdio.h> 40 #include <libintl.h> 41 #include <limits.h> 42 #include <ctype.h> 43 #include <errno.h> 44 #include <semaphore.h> 45 #include <syslog.h> 46 #include <string.h> 47 #include <sys/types.h> 48 #include <sys/systeminfo.h> 49 #include <psvc_objects.h> 50 51 static psvc_opaque_t hdlp; 52 53 #define PSVC_PLUGIN_VERSION PICLD_PLUGIN_VERSION_1 54 55 #pragma init(psvc_psr_plugin_register) /* place in .init section */ 56 57 typedef struct { 58 char name[32]; 59 picl_nodehdl_t node; 60 } picl_psvc_t; 61 62 extern struct handle { 63 uint32_t obj_count; 64 picl_psvc_t *objects; 65 FILE *fp; 66 } psvc_hdl; 67 68 void psvc_psr_plugin_init(void); 69 void psvc_psr_plugin_fini(void); 70 71 picld_plugin_reg_t psvc_psr_reg = { 72 PSVC_PLUGIN_VERSION, 73 PICLD_PLUGIN_CRITICAL, 74 "PSVC_PSR", 75 psvc_psr_plugin_init, 76 psvc_psr_plugin_fini 77 }; 78 79 #define PSVC_INIT_ERR gettext("%s: Error in psvc_init(): %s\n") 80 #define PTREE_DELETE_NODE_ERR gettext("%s: ptree_delete_node() failed: %s\n") 81 #define PTREE_GET_NODE_ERR \ 82 gettext("%s: ptree_get_node_by_path() failed: %s\n") 83 84 extern int ptree_get_node_by_path(const char *, picl_nodehdl_t *); 85 86 struct node_file { 87 char path[256]; 88 char file[256]; 89 } dev_pr_info[] = { 90 {"/SYSTEM/CPU0_MOD_CARD", 91 "/devices/pci@8,700000/ebus@5/i2c@1,30/temperature@0,30:die_temp"}, 92 {"/SYSTEM/CPU1_MOD_CARD", 93 "/devices/pci@8,700000/ebus@5/i2c@1,30/temperature@0,98:die_temp"}, 94 {"/SYSTEM/AT24C64_A0_1", 95 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,a0:dimm"}, 96 {"/SYSTEM/AT24C64_A2_1", 97 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,a2:dimm"}, 98 {"/SYSTEM/AT24C64_A4_1", 99 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,a4:dimm"}, 100 {"/SYSTEM/AT24C64_A6_1", 101 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,a6:dimm"}, 102 {"/SYSTEM/AT24C64_A8_1", 103 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,a8:dimm"}, 104 {"/SYSTEM/AT24C64_AA_1", 105 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,aa:dimm"}, 106 {"/SYSTEM/AT24C64_AC_1", 107 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,ac:dimm"}, 108 {"/SYSTEM/AT24C64_AE_1", 109 "/devices/pci@8,700000/ebus@5/i2c@1,2e/dimm@1,ae:dimm"} 110 }; 111 #define DEV_PR_COUNT (sizeof (dev_pr_info) / sizeof (struct node_file)) 112 113 static void init_err(char *fmt, char *arg1, char *arg2) 114 { 115 char msg[256]; 116 117 sprintf(msg, fmt, arg1, arg2); 118 syslog(LOG_ERR, msg); 119 } 120 121 void 122 psvc_psr_plugin_init(void) 123 { 124 char *funcname = "psvc_plugin_init"; 125 int32_t i; 126 int err; 127 boolean_t present; 128 /* 129 * So the volatile read/write routines can retrieve data from 130 * psvc or picl 131 */ 132 err = psvc_init(&hdlp); 133 if (err != 0) { 134 init_err(PSVC_INIT_ERR, funcname, strerror(errno)); 135 136 } 137 138 /* 139 * Remove nodes whose devices aren't present from the picl tree. 140 */ 141 for (i = 0; i < psvc_hdl.obj_count; ++i) { 142 picl_psvc_t *objp; 143 uint64_t features; 144 objp = &psvc_hdl.objects[i]; 145 146 err = psvc_get_attr(hdlp, objp->name, PSVC_PRESENCE_ATTR, 147 &present); 148 if (err != PSVC_SUCCESS) 149 continue; 150 err = psvc_get_attr(hdlp, objp->name, PSVC_FEATURES_ATTR, 151 &features); 152 if (err != PSVC_SUCCESS) 153 continue; 154 if ((features & (PSVC_DEV_HOTPLUG | PSVC_DEV_OPTION)) && 155 (present == PSVC_ABSENT)) { 156 err = ptree_delete_node(objp->node); 157 if (err != 0) { 158 init_err(PTREE_DELETE_NODE_ERR, funcname, 159 picl_strerror(err)); 160 return; 161 } 162 } 163 } 164 165 /* 166 * Remove PICL device nodes if their /devices file isn't present or 167 * if the device file is present but the open returns ENXIO 168 * which indicates that the node file doesn't represent a device 169 * tree node and is probably a relic from some previous boot config 170 */ 171 for (i = 0; i < DEV_PR_COUNT; ++i) { 172 picl_nodehdl_t dev_pr_node; 173 int fd; 174 fd = open(dev_pr_info[i].file, O_RDONLY); 175 if (fd != -1) { 176 close(fd); 177 continue; 178 } 179 if ((errno != ENOENT) && (errno != ENXIO)) 180 continue; 181 182 err = ptree_get_node_by_path(dev_pr_info[i].path, &dev_pr_node); 183 if (err != 0) { 184 init_err(PTREE_GET_NODE_ERR, funcname, 185 picl_strerror(err)); 186 return; 187 } 188 189 err = ptree_delete_node(dev_pr_node); 190 if (err != 0) { 191 init_err(PTREE_DELETE_NODE_ERR, funcname, 192 picl_strerror(err)); 193 return; 194 } 195 } 196 free(psvc_hdl.objects); 197 } 198 199 void 200 psvc_psr_plugin_fini(void) 201 { 202 psvc_fini(hdlp); 203 } 204 205 void 206 psvc_psr_plugin_register(void) 207 { 208 picld_plugin_register(&psvc_psr_reg); 209 } 210