1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 8638 Vikram * Common Development and Distribution License (the "License"). 6 8638 Vikram * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8638 Vikram * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 0 stevel /* All Rights Reserved */ 28 0 stevel 29 0 stevel 30 0 stevel #include <stdio.h> 31 0 stevel #include <stdarg.h> 32 0 stevel #include <stdlib.h> 33 0 stevel #include <unistd.h> 34 0 stevel #include <strings.h> 35 0 stevel #include <sys/systeminfo.h> 36 0 stevel #include <sys/types.h> 37 0 stevel #include <sys/stat.h> 38 0 stevel #include "prtconf.h" 39 0 stevel 40 0 stevel struct prt_opts opts; 41 0 stevel struct prt_dbg dbg; 42 0 stevel static char new_path[MAXPATHLEN]; 43 0 stevel 44 0 stevel #define INDENT_LENGTH 4 45 0 stevel 46 0 stevel #ifdef __x86 47 9074 Judy static const char *usage = "%s [ -V | -x | -abcdvpPD ] [ <device_path > ]\n"; 48 0 stevel #else 49 9074 Judy static const char *usage = 50 9074 Judy "%s [ -F | -V | -x | -abcdvpPD ][ <device_path > ]\n"; 51 0 stevel #endif /* __x86 */ 52 0 stevel 53 0 stevel static void 54 0 stevel setprogname(const char *name) 55 0 stevel { 56 0 stevel char *p; 57 0 stevel 58 0 stevel if (name == NULL) 59 0 stevel opts.o_progname = "prtconf"; 60 0 stevel else if (p = strrchr(name, '/')) 61 0 stevel opts.o_progname = (const char *) p + 1; 62 0 stevel else 63 0 stevel opts.o_progname = name; 64 0 stevel } 65 0 stevel 66 0 stevel /*PRINTFLIKE1*/ 67 0 stevel void 68 0 stevel dprintf(const char *fmt, ...) 69 0 stevel { 70 0 stevel if (dbg.d_debug) { 71 0 stevel va_list ap; 72 0 stevel va_start(ap, fmt); 73 0 stevel (void) vfprintf(stderr, fmt, ap); 74 0 stevel va_end(ap); 75 0 stevel } 76 0 stevel } 77 0 stevel 78 0 stevel void 79 0 stevel indent_to_level(int ilev) 80 0 stevel { 81 0 stevel (void) printf("%*s", INDENT_LENGTH * ilev, ""); 82 0 stevel } 83 0 stevel 84 0 stevel static void 85 0 stevel cleanup_path(const char *input_path, char *path) 86 0 stevel { 87 0 stevel char *ptr, *ptr2; 88 0 stevel size_t len; 89 0 stevel 90 0 stevel if ((input_path == NULL) || (path == NULL)) 91 0 stevel return; 92 0 stevel 93 0 stevel (void) strcpy(path, input_path); 94 0 stevel 95 0 stevel /*LINTED*/ 96 0 stevel while (1) { 97 0 stevel len = strlen(path); 98 0 stevel if (len == 0) 99 0 stevel break; 100 0 stevel 101 0 stevel /* change substring "//" into "/" */ 102 0 stevel if (ptr = strstr(path, "//")) { 103 0 stevel len = strlen(ptr + 1); 104 0 stevel (void) memmove(ptr, ptr + 1, len + 1); 105 0 stevel continue; 106 0 stevel } 107 0 stevel /* change substring "/./" into "/" */ 108 0 stevel if (ptr = strstr(path, "/./")) { 109 0 stevel len = strlen(ptr + 2); 110 0 stevel (void) memmove(ptr, ptr + 2, len + 1); 111 0 stevel continue; 112 0 stevel } 113 0 stevel 114 0 stevel /* change substring "/<foo>/../" into "/" */ 115 0 stevel if (ptr = strstr(path, "/../")) { 116 0 stevel len = strlen(ptr + 3); 117 0 stevel *ptr = '\0'; 118 0 stevel ptr2 = strrchr(path, (int)'/'); 119 0 stevel if (ptr2 == NULL) { 120 0 stevel /* path had a leading "/../" */ 121 0 stevel ptr2 = path; 122 0 stevel } 123 0 stevel (void) memmove(ptr2, ptr + 3, len + 1); 124 0 stevel continue; 125 0 stevel } 126 0 stevel 127 0 stevel /* change trailing "/<foo>/.." into "/" */ 128 0 stevel if ((len >= 3) && 129 0 stevel (path[len - 3] == '/') && 130 0 stevel (path[len - 2] == '.') && 131 0 stevel (path[len - 1] == '.')) { 132 0 stevel path[len - 3] = '\0'; 133 0 stevel ptr2 = strrchr(path, (int)'/'); 134 0 stevel if (ptr2 != NULL) { 135 0 stevel ptr2[1] = '\0'; 136 0 stevel } else { 137 0 stevel /* path was "/.." */ 138 0 stevel path[0] = '/'; 139 0 stevel path[1] = '\0'; 140 0 stevel } 141 0 stevel continue; 142 0 stevel } 143 0 stevel 144 0 stevel /* change trailing "/." into "/" */ 145 0 stevel if ((len >= 2) && 146 0 stevel (path[len - 2] == '/') && 147 0 stevel (path[len - 1] == '.')) { 148 0 stevel path[len - 1] = '\0'; 149 0 stevel continue; 150 0 stevel } 151 0 stevel 152 0 stevel /* remove trailing "/" unless it's the root */ 153 0 stevel if ((len > 1) && (path[len - 1] == '/')) { 154 0 stevel path[len - 1] = '\0'; 155 0 stevel continue; 156 0 stevel } 157 0 stevel 158 0 stevel break; 159 0 stevel } 160 0 stevel } 161 0 stevel 162 0 stevel 163 0 stevel /* 164 0 stevel * debug version has two more flags: 165 0 stevel * -L force load driver 166 0 stevel * -M: print per driver list 167 0 stevel */ 168 0 stevel 169 0 stevel #ifdef DEBUG 170 9074 Judy static const char *optstring = "abcdDvVxpPFf:M:dLuC"; 171 0 stevel #else 172 9074 Judy static const char *optstring = "abcdDvVxpPFf:uC"; 173 0 stevel #endif /* DEBUG */ 174 0 stevel 175 0 stevel int 176 0 stevel main(int argc, char *argv[]) 177 0 stevel { 178 0 stevel long pagesize, npages; 179 0 stevel int c, ret; 180 0 stevel char hw_provider[SYS_NMLN]; 181 0 stevel 182 0 stevel setprogname(argv[0]); 183 0 stevel opts.o_promdev = "/dev/openprom"; 184 0 stevel 185 0 stevel while ((c = getopt(argc, argv, optstring)) != -1) { 186 0 stevel switch (c) { 187 0 stevel case 'a': 188 0 stevel ++opts.o_ancestors; 189 0 stevel break; 190 0 stevel case 'b': 191 0 stevel ++opts.o_productinfo; 192 0 stevel break; 193 0 stevel case 'c': 194 0 stevel ++opts.o_children; 195 9074 Judy break; 196 9074 Judy case 'd': 197 9074 Judy ++opts.o_pciid; 198 0 stevel break; 199 0 stevel case 'D': 200 0 stevel ++opts.o_drv_name; 201 0 stevel break; 202 0 stevel case 'v': 203 0 stevel ++opts.o_verbose; 204 0 stevel break; 205 0 stevel case 'p': 206 0 stevel ++opts.o_prominfo; 207 0 stevel break; 208 0 stevel case 'f': 209 0 stevel opts.o_promdev = optarg; 210 0 stevel break; 211 0 stevel case 'V': 212 0 stevel ++opts.o_promversion; 213 0 stevel break; 214 0 stevel case 'x': 215 0 stevel ++opts.o_prom_ready64; 216 0 stevel break; 217 0 stevel case 'F': 218 0 stevel ++opts.o_fbname; 219 0 stevel ++opts.o_noheader; 220 0 stevel break; 221 0 stevel case 'P': 222 0 stevel ++opts.o_pseudodevs; 223 0 stevel break; 224 0 stevel case 'C': 225 0 stevel ++opts.o_forcecache; 226 0 stevel break; 227 0 stevel #ifdef DEBUG 228 0 stevel case 'M': 229 0 stevel dbg.d_drivername = optarg; 230 0 stevel ++dbg.d_bydriver; 231 0 stevel break; 232 0 stevel case 'L': 233 0 stevel ++dbg.d_forceload; 234 0 stevel break; 235 0 stevel #endif /* DEBUG */ 236 0 stevel 237 0 stevel default: 238 0 stevel (void) fprintf(stderr, usage, opts.o_progname); 239 0 stevel return (1); 240 0 stevel } 241 0 stevel } 242 0 stevel 243 0 stevel (void) uname(&opts.o_uts); 244 0 stevel 245 0 stevel if (opts.o_fbname) 246 0 stevel return (do_fbname()); 247 0 stevel 248 0 stevel if (opts.o_promversion) 249 0 stevel return (do_promversion()); 250 0 stevel 251 0 stevel if (opts.o_prom_ready64) 252 0 stevel return (do_prom_version64()); 253 0 stevel 254 0 stevel if (opts.o_productinfo) 255 0 stevel return (do_productinfo()); 256 0 stevel 257 0 stevel opts.o_devices_path = NULL; 258 0 stevel opts.o_devt = DDI_DEV_T_NONE; 259 0 stevel opts.o_target = 0; 260 0 stevel if (optind < argc) { 261 0 stevel struct stat sinfo; 262 0 stevel char *path = argv[optind]; 263 0 stevel int error; 264 0 stevel 265 8638 Vikram if (opts.o_prominfo) { 266 8638 Vikram /* PROM tree cannot be used with path */ 267 8638 Vikram (void) fprintf(stderr, "%s: path and -p option are " 268 8638 Vikram "mutually exclusive\n", opts.o_progname); 269 8638 Vikram return (1); 270 8638 Vikram } 271 8638 Vikram 272 0 stevel if (strlen(path) >= MAXPATHLEN) { 273 0 stevel (void) fprintf(stderr, "%s: " 274 0 stevel "path specified is too long\n", opts.o_progname); 275 0 stevel return (1); 276 0 stevel } 277 0 stevel 278 0 stevel if (error = stat(path, &sinfo)) { 279 0 stevel 280 0 stevel /* an invalid path was specified */ 281 0 stevel (void) fprintf(stderr, "%s: invalid path specified\n", 282 8638 Vikram opts.o_progname); 283 0 stevel return (1); 284 0 stevel 285 0 stevel } else if (((sinfo.st_mode & S_IFMT) == S_IFCHR) || 286 8638 Vikram ((sinfo.st_mode & S_IFMT) == S_IFBLK)) { 287 0 stevel 288 0 stevel opts.o_devt = sinfo.st_rdev; 289 0 stevel error = 0; 290 0 stevel 291 0 stevel } else if ((sinfo.st_mode & S_IFMT) == S_IFDIR) { 292 0 stevel size_t len, plen; 293 0 stevel 294 0 stevel /* clean up the path */ 295 0 stevel cleanup_path(path, new_path); 296 0 stevel 297 0 stevel len = strlen(new_path); 298 0 stevel plen = strlen("/devices"); 299 0 stevel if (len < plen) { 300 0 stevel /* This is not a valid /devices path */ 301 0 stevel error = 1; 302 0 stevel } else if ((len == plen) && 303 0 stevel (strcmp(new_path, "/devices") == 0)) { 304 0 stevel /* /devices is the root nexus */ 305 0 stevel opts.o_devices_path = "/"; 306 0 stevel error = 0; 307 0 stevel } else if (strncmp(new_path, "/devices/", plen + 1)) { 308 0 stevel /* This is not a valid /devices path */ 309 0 stevel error = 1; 310 0 stevel } else { 311 0 stevel /* a /devices/ path was specified */ 312 0 stevel opts.o_devices_path = new_path + plen; 313 0 stevel error = 0; 314 0 stevel } 315 0 stevel 316 0 stevel } else { 317 0 stevel /* an invalid device path was specified */ 318 0 stevel error = 1; 319 0 stevel } 320 0 stevel 321 0 stevel if (error) { 322 0 stevel (void) fprintf(stderr, "%s: " 323 0 stevel "invalid device path specified\n", 324 0 stevel opts.o_progname); 325 0 stevel return (1); 326 0 stevel } 327 0 stevel 328 0 stevel opts.o_target = 1; 329 0 stevel } 330 0 stevel 331 0 stevel if ((opts.o_ancestors || opts.o_children) && (!opts.o_target)) { 332 0 stevel (void) fprintf(stderr, "%s: options require a device path\n", 333 0 stevel opts.o_progname); 334 0 stevel return (1); 335 0 stevel } 336 0 stevel 337 0 stevel if (opts.o_target) { 338 0 stevel prtconf_devinfo(); 339 0 stevel return (0); 340 0 stevel } 341 0 stevel 342 0 stevel ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider)); 343 0 stevel /* 344 0 stevel * If 0 bytes are returned (the system returns '1', for the \0), 345 0 stevel * we're probably on x86, and there has been no si-hw-provider 346 0 stevel * set in /etc/bootrc, so just default to Sun. 347 0 stevel */ 348 0 stevel if (ret <= 1) { 349 0 stevel (void) strncpy(hw_provider, "Sun Microsystems", 350 0 stevel sizeof (hw_provider)); 351 0 stevel } else { 352 0 stevel /* 353 0 stevel * Provide backward compatibility by stripping out the _. 354 0 stevel */ 355 0 stevel if (strcmp(hw_provider, "Sun_Microsystems") == 0) 356 0 stevel hw_provider[3] = ' '; 357 0 stevel } 358 0 stevel (void) printf("System Configuration: %s %s\n", hw_provider, 359 0 stevel opts.o_uts.machine); 360 0 stevel 361 0 stevel pagesize = sysconf(_SC_PAGESIZE); 362 0 stevel npages = sysconf(_SC_PHYS_PAGES); 363 0 stevel (void) printf("Memory size: "); 364 0 stevel if (pagesize == -1 || npages == -1) 365 0 stevel (void) printf("unable to determine\n"); 366 0 stevel else { 367 0 stevel const int64_t kbyte = 1024; 368 0 stevel const int64_t mbyte = 1024 * 1024; 369 0 stevel int64_t ii = (int64_t)pagesize * npages; 370 0 stevel 371 0 stevel if (ii >= mbyte) 372 0 stevel (void) printf("%ld Megabytes\n", 373 8638 Vikram (long)((ii+mbyte-1) / mbyte)); 374 0 stevel else 375 0 stevel (void) printf("%ld Kilobytes\n", 376 8638 Vikram (long)((ii+kbyte-1) / kbyte)); 377 0 stevel } 378 0 stevel 379 0 stevel if (opts.o_prominfo) { 380 0 stevel (void) printf("System Peripherals (PROM Nodes):\n\n"); 381 0 stevel if (do_prominfo() == 0) 382 0 stevel return (0); 383 0 stevel (void) fprintf(stderr, "%s: Defaulting to non-PROM mode...\n", 384 0 stevel opts.o_progname); 385 0 stevel } 386 0 stevel 387 0 stevel (void) printf("System Peripherals (Software Nodes):\n\n"); 388 0 stevel 389 0 stevel (void) prtconf_devinfo(); 390 0 stevel 391 0 stevel return (0); 392 0 stevel } 393