10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
58638SVikram.Hegde@Sun.COM * Common Development and Distribution License (the "License").
68638SVikram.Hegde@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*13093SRoger.Faulkner@Oracle.COM
220Sstevel@tonic-gate /*
2313038Sanil.udupa@sun.com * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdarg.h>
310Sstevel@tonic-gate #include <stdlib.h>
320Sstevel@tonic-gate #include <unistd.h>
330Sstevel@tonic-gate #include <strings.h>
340Sstevel@tonic-gate #include <sys/systeminfo.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include "prtconf.h"
380Sstevel@tonic-gate
390Sstevel@tonic-gate struct prt_opts opts;
400Sstevel@tonic-gate struct prt_dbg dbg;
410Sstevel@tonic-gate static char new_path[MAXPATHLEN];
420Sstevel@tonic-gate
430Sstevel@tonic-gate #define INDENT_LENGTH 4
440Sstevel@tonic-gate
450Sstevel@tonic-gate #ifdef __x86
469074SJudy.Chen@Sun.COM static const char *usage = "%s [ -V | -x | -abcdvpPD ] [ <device_path > ]\n";
470Sstevel@tonic-gate #else
489074SJudy.Chen@Sun.COM static const char *usage =
499074SJudy.Chen@Sun.COM "%s [ -F | -V | -x | -abcdvpPD ][ <device_path > ]\n";
500Sstevel@tonic-gate #endif /* __x86 */
510Sstevel@tonic-gate
520Sstevel@tonic-gate static void
setpname(const char * name)53*13093SRoger.Faulkner@Oracle.COM setpname(const char *name)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate char *p;
560Sstevel@tonic-gate
570Sstevel@tonic-gate if (name == NULL)
580Sstevel@tonic-gate opts.o_progname = "prtconf";
590Sstevel@tonic-gate else if (p = strrchr(name, '/'))
600Sstevel@tonic-gate opts.o_progname = (const char *) p + 1;
610Sstevel@tonic-gate else
620Sstevel@tonic-gate opts.o_progname = name;
630Sstevel@tonic-gate }
640Sstevel@tonic-gate
650Sstevel@tonic-gate /*PRINTFLIKE1*/
660Sstevel@tonic-gate void
dprintf(const char * fmt,...)670Sstevel@tonic-gate dprintf(const char *fmt, ...)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate if (dbg.d_debug) {
700Sstevel@tonic-gate va_list ap;
710Sstevel@tonic-gate va_start(ap, fmt);
720Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap);
730Sstevel@tonic-gate va_end(ap);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate }
760Sstevel@tonic-gate
770Sstevel@tonic-gate void
indent_to_level(int ilev)780Sstevel@tonic-gate indent_to_level(int ilev)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate (void) printf("%*s", INDENT_LENGTH * ilev, "");
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate static void
cleanup_path(const char * input_path,char * path)840Sstevel@tonic-gate cleanup_path(const char *input_path, char *path)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate char *ptr, *ptr2;
870Sstevel@tonic-gate size_t len;
880Sstevel@tonic-gate
890Sstevel@tonic-gate if ((input_path == NULL) || (path == NULL))
900Sstevel@tonic-gate return;
910Sstevel@tonic-gate
920Sstevel@tonic-gate (void) strcpy(path, input_path);
930Sstevel@tonic-gate
940Sstevel@tonic-gate /*LINTED*/
950Sstevel@tonic-gate while (1) {
960Sstevel@tonic-gate len = strlen(path);
970Sstevel@tonic-gate if (len == 0)
980Sstevel@tonic-gate break;
990Sstevel@tonic-gate
1000Sstevel@tonic-gate /* change substring "//" into "/" */
1010Sstevel@tonic-gate if (ptr = strstr(path, "//")) {
1020Sstevel@tonic-gate len = strlen(ptr + 1);
1030Sstevel@tonic-gate (void) memmove(ptr, ptr + 1, len + 1);
1040Sstevel@tonic-gate continue;
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate /* change substring "/./" into "/" */
1070Sstevel@tonic-gate if (ptr = strstr(path, "/./")) {
1080Sstevel@tonic-gate len = strlen(ptr + 2);
1090Sstevel@tonic-gate (void) memmove(ptr, ptr + 2, len + 1);
1100Sstevel@tonic-gate continue;
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /* change substring "/<foo>/../" into "/" */
1140Sstevel@tonic-gate if (ptr = strstr(path, "/../")) {
1150Sstevel@tonic-gate len = strlen(ptr + 3);
1160Sstevel@tonic-gate *ptr = '\0';
1170Sstevel@tonic-gate ptr2 = strrchr(path, (int)'/');
1180Sstevel@tonic-gate if (ptr2 == NULL) {
1190Sstevel@tonic-gate /* path had a leading "/../" */
1200Sstevel@tonic-gate ptr2 = path;
1210Sstevel@tonic-gate }
1220Sstevel@tonic-gate (void) memmove(ptr2, ptr + 3, len + 1);
1230Sstevel@tonic-gate continue;
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate /* change trailing "/<foo>/.." into "/" */
1270Sstevel@tonic-gate if ((len >= 3) &&
1280Sstevel@tonic-gate (path[len - 3] == '/') &&
1290Sstevel@tonic-gate (path[len - 2] == '.') &&
1300Sstevel@tonic-gate (path[len - 1] == '.')) {
1310Sstevel@tonic-gate path[len - 3] = '\0';
1320Sstevel@tonic-gate ptr2 = strrchr(path, (int)'/');
1330Sstevel@tonic-gate if (ptr2 != NULL) {
1340Sstevel@tonic-gate ptr2[1] = '\0';
1350Sstevel@tonic-gate } else {
1360Sstevel@tonic-gate /* path was "/.." */
1370Sstevel@tonic-gate path[0] = '/';
1380Sstevel@tonic-gate path[1] = '\0';
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate continue;
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* change trailing "/." into "/" */
1440Sstevel@tonic-gate if ((len >= 2) &&
1450Sstevel@tonic-gate (path[len - 2] == '/') &&
1460Sstevel@tonic-gate (path[len - 1] == '.')) {
1470Sstevel@tonic-gate path[len - 1] = '\0';
1480Sstevel@tonic-gate continue;
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate /* remove trailing "/" unless it's the root */
1520Sstevel@tonic-gate if ((len > 1) && (path[len - 1] == '/')) {
1530Sstevel@tonic-gate path[len - 1] = '\0';
1540Sstevel@tonic-gate continue;
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate break;
1580Sstevel@tonic-gate }
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate * debug version has two more flags:
1640Sstevel@tonic-gate * -L force load driver
1650Sstevel@tonic-gate * -M: print per driver list
1660Sstevel@tonic-gate */
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate #ifdef DEBUG
1699074SJudy.Chen@Sun.COM static const char *optstring = "abcdDvVxpPFf:M:dLuC";
1700Sstevel@tonic-gate #else
1719074SJudy.Chen@Sun.COM static const char *optstring = "abcdDvVxpPFf:uC";
1720Sstevel@tonic-gate #endif /* DEBUG */
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate int
main(int argc,char * argv[])1750Sstevel@tonic-gate main(int argc, char *argv[])
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate long pagesize, npages;
1780Sstevel@tonic-gate int c, ret;
1790Sstevel@tonic-gate char hw_provider[SYS_NMLN];
1800Sstevel@tonic-gate
181*13093SRoger.Faulkner@Oracle.COM setpname(argv[0]);
1820Sstevel@tonic-gate opts.o_promdev = "/dev/openprom";
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate while ((c = getopt(argc, argv, optstring)) != -1) {
1850Sstevel@tonic-gate switch (c) {
1860Sstevel@tonic-gate case 'a':
1870Sstevel@tonic-gate ++opts.o_ancestors;
1880Sstevel@tonic-gate break;
1890Sstevel@tonic-gate case 'b':
1900Sstevel@tonic-gate ++opts.o_productinfo;
1910Sstevel@tonic-gate break;
1920Sstevel@tonic-gate case 'c':
1930Sstevel@tonic-gate ++opts.o_children;
1940Sstevel@tonic-gate break;
1959074SJudy.Chen@Sun.COM case 'd':
1969074SJudy.Chen@Sun.COM ++opts.o_pciid;
1979074SJudy.Chen@Sun.COM break;
1980Sstevel@tonic-gate case 'D':
1990Sstevel@tonic-gate ++opts.o_drv_name;
2000Sstevel@tonic-gate break;
2010Sstevel@tonic-gate case 'v':
2020Sstevel@tonic-gate ++opts.o_verbose;
2030Sstevel@tonic-gate break;
2040Sstevel@tonic-gate case 'p':
2050Sstevel@tonic-gate ++opts.o_prominfo;
2060Sstevel@tonic-gate break;
2070Sstevel@tonic-gate case 'f':
2080Sstevel@tonic-gate opts.o_promdev = optarg;
2090Sstevel@tonic-gate break;
2100Sstevel@tonic-gate case 'V':
2110Sstevel@tonic-gate ++opts.o_promversion;
2120Sstevel@tonic-gate break;
2130Sstevel@tonic-gate case 'x':
2140Sstevel@tonic-gate ++opts.o_prom_ready64;
2150Sstevel@tonic-gate break;
2160Sstevel@tonic-gate case 'F':
2170Sstevel@tonic-gate ++opts.o_fbname;
2180Sstevel@tonic-gate ++opts.o_noheader;
2190Sstevel@tonic-gate break;
2200Sstevel@tonic-gate case 'P':
2210Sstevel@tonic-gate ++opts.o_pseudodevs;
2220Sstevel@tonic-gate break;
2230Sstevel@tonic-gate case 'C':
2240Sstevel@tonic-gate ++opts.o_forcecache;
2250Sstevel@tonic-gate break;
2260Sstevel@tonic-gate #ifdef DEBUG
2270Sstevel@tonic-gate case 'M':
2280Sstevel@tonic-gate dbg.d_drivername = optarg;
2290Sstevel@tonic-gate ++dbg.d_bydriver;
2300Sstevel@tonic-gate break;
2310Sstevel@tonic-gate case 'L':
2320Sstevel@tonic-gate ++dbg.d_forceload;
2330Sstevel@tonic-gate break;
2340Sstevel@tonic-gate #endif /* DEBUG */
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate default:
2370Sstevel@tonic-gate (void) fprintf(stderr, usage, opts.o_progname);
2380Sstevel@tonic-gate return (1);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate (void) uname(&opts.o_uts);
2430Sstevel@tonic-gate
2440Sstevel@tonic-gate if (opts.o_fbname)
2450Sstevel@tonic-gate return (do_fbname());
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate if (opts.o_promversion)
2480Sstevel@tonic-gate return (do_promversion());
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate if (opts.o_prom_ready64)
2510Sstevel@tonic-gate return (do_prom_version64());
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate if (opts.o_productinfo)
2540Sstevel@tonic-gate return (do_productinfo());
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate opts.o_devices_path = NULL;
2570Sstevel@tonic-gate opts.o_devt = DDI_DEV_T_NONE;
2580Sstevel@tonic-gate opts.o_target = 0;
2590Sstevel@tonic-gate if (optind < argc) {
2600Sstevel@tonic-gate struct stat sinfo;
2610Sstevel@tonic-gate char *path = argv[optind];
2620Sstevel@tonic-gate int error;
2630Sstevel@tonic-gate
2648638SVikram.Hegde@Sun.COM if (opts.o_prominfo) {
2658638SVikram.Hegde@Sun.COM /* PROM tree cannot be used with path */
2668638SVikram.Hegde@Sun.COM (void) fprintf(stderr, "%s: path and -p option are "
2678638SVikram.Hegde@Sun.COM "mutually exclusive\n", opts.o_progname);
2688638SVikram.Hegde@Sun.COM return (1);
2698638SVikram.Hegde@Sun.COM }
2708638SVikram.Hegde@Sun.COM
2710Sstevel@tonic-gate if (strlen(path) >= MAXPATHLEN) {
2720Sstevel@tonic-gate (void) fprintf(stderr, "%s: "
2730Sstevel@tonic-gate "path specified is too long\n", opts.o_progname);
2740Sstevel@tonic-gate return (1);
2750Sstevel@tonic-gate }
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate if (error = stat(path, &sinfo)) {
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate /* an invalid path was specified */
2800Sstevel@tonic-gate (void) fprintf(stderr, "%s: invalid path specified\n",
2818638SVikram.Hegde@Sun.COM opts.o_progname);
2820Sstevel@tonic-gate return (1);
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate } else if (((sinfo.st_mode & S_IFMT) == S_IFCHR) ||
2858638SVikram.Hegde@Sun.COM ((sinfo.st_mode & S_IFMT) == S_IFBLK)) {
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate opts.o_devt = sinfo.st_rdev;
2880Sstevel@tonic-gate error = 0;
2890Sstevel@tonic-gate
2900Sstevel@tonic-gate } else if ((sinfo.st_mode & S_IFMT) == S_IFDIR) {
2910Sstevel@tonic-gate size_t len, plen;
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate /* clean up the path */
2940Sstevel@tonic-gate cleanup_path(path, new_path);
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate len = strlen(new_path);
2970Sstevel@tonic-gate plen = strlen("/devices");
2980Sstevel@tonic-gate if (len < plen) {
2990Sstevel@tonic-gate /* This is not a valid /devices path */
3000Sstevel@tonic-gate error = 1;
3010Sstevel@tonic-gate } else if ((len == plen) &&
3020Sstevel@tonic-gate (strcmp(new_path, "/devices") == 0)) {
3030Sstevel@tonic-gate /* /devices is the root nexus */
3040Sstevel@tonic-gate opts.o_devices_path = "/";
3050Sstevel@tonic-gate error = 0;
3060Sstevel@tonic-gate } else if (strncmp(new_path, "/devices/", plen + 1)) {
3070Sstevel@tonic-gate /* This is not a valid /devices path */
3080Sstevel@tonic-gate error = 1;
3090Sstevel@tonic-gate } else {
3100Sstevel@tonic-gate /* a /devices/ path was specified */
3110Sstevel@tonic-gate opts.o_devices_path = new_path + plen;
3120Sstevel@tonic-gate error = 0;
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate } else {
3160Sstevel@tonic-gate /* an invalid device path was specified */
3170Sstevel@tonic-gate error = 1;
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate
3200Sstevel@tonic-gate if (error) {
3210Sstevel@tonic-gate (void) fprintf(stderr, "%s: "
3220Sstevel@tonic-gate "invalid device path specified\n",
3230Sstevel@tonic-gate opts.o_progname);
3240Sstevel@tonic-gate return (1);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate opts.o_target = 1;
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate if ((opts.o_ancestors || opts.o_children) && (!opts.o_target)) {
3310Sstevel@tonic-gate (void) fprintf(stderr, "%s: options require a device path\n",
3320Sstevel@tonic-gate opts.o_progname);
3330Sstevel@tonic-gate return (1);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate if (opts.o_target) {
3370Sstevel@tonic-gate prtconf_devinfo();
3380Sstevel@tonic-gate return (0);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate ret = sysinfo(SI_HW_PROVIDER, hw_provider, sizeof (hw_provider));
3420Sstevel@tonic-gate /*
3430Sstevel@tonic-gate * If 0 bytes are returned (the system returns '1', for the \0),
3440Sstevel@tonic-gate * we're probably on x86, and there has been no si-hw-provider
34513038Sanil.udupa@sun.com * set in /etc/bootrc, default to Oracle.
3460Sstevel@tonic-gate */
3470Sstevel@tonic-gate if (ret <= 1) {
34813038Sanil.udupa@sun.com (void) strncpy(hw_provider, "Oracle Corporation",
3490Sstevel@tonic-gate sizeof (hw_provider));
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate (void) printf("System Configuration: %s %s\n", hw_provider,
3520Sstevel@tonic-gate opts.o_uts.machine);
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate pagesize = sysconf(_SC_PAGESIZE);
3550Sstevel@tonic-gate npages = sysconf(_SC_PHYS_PAGES);
3560Sstevel@tonic-gate (void) printf("Memory size: ");
3570Sstevel@tonic-gate if (pagesize == -1 || npages == -1)
3580Sstevel@tonic-gate (void) printf("unable to determine\n");
3590Sstevel@tonic-gate else {
3600Sstevel@tonic-gate const int64_t kbyte = 1024;
3610Sstevel@tonic-gate const int64_t mbyte = 1024 * 1024;
3620Sstevel@tonic-gate int64_t ii = (int64_t)pagesize * npages;
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate if (ii >= mbyte)
3650Sstevel@tonic-gate (void) printf("%ld Megabytes\n",
3668638SVikram.Hegde@Sun.COM (long)((ii+mbyte-1) / mbyte));
3670Sstevel@tonic-gate else
3680Sstevel@tonic-gate (void) printf("%ld Kilobytes\n",
3698638SVikram.Hegde@Sun.COM (long)((ii+kbyte-1) / kbyte));
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate if (opts.o_prominfo) {
3730Sstevel@tonic-gate (void) printf("System Peripherals (PROM Nodes):\n\n");
3740Sstevel@tonic-gate if (do_prominfo() == 0)
3750Sstevel@tonic-gate return (0);
3760Sstevel@tonic-gate (void) fprintf(stderr, "%s: Defaulting to non-PROM mode...\n",
3770Sstevel@tonic-gate opts.o_progname);
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate (void) printf("System Peripherals (Software Nodes):\n\n");
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate (void) prtconf_devinfo();
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate return (0);
3850Sstevel@tonic-gate }
386