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 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <strings.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <errno.h>
33#include <stdio.h>
34#include <locale.h>
35
36#include <nsctl.h>
37#define	__NSC_GEN__
38#include <sys/nsctl/nsc_gen.h>
39#include <sys/nsctl/nsc_mem.h>
40
41
42/*
43 * Private functions from libsd.
44 */
45extern int nsc_nvclean(int);
46extern int nsc_gmem_data(char *);
47extern int nsc_gmem_sizes(int *);
48
49/*
50 * Local functions.
51 */
52static int _nsc_gmem(void);
53static void show_maps(char *, int);
54
55
56static void
57usage(void)
58{
59	(void) fprintf(stderr, gettext("usage: nscadm [-h] command\n"));
60	(void) fprintf(stderr, gettext("valid commands:\n"));
61	(void) fprintf(stderr, gettext("	freeze <device>\n"));
62	(void) fprintf(stderr, gettext("	unfreeze <device>\n"));
63	(void) fprintf(stderr, gettext("	isfrozen <device>\n"));
64}
65
66static void
67is_chr_dev(char *dev, char *op)
68{
69	struct stat sbuf;
70	if (stat(dev, &sbuf) < 0) {
71		(void) fprintf(stderr, gettext("nscadm: "));
72		perror(op);
73		exit(255);
74	}
75	if (!S_ISCHR(sbuf.st_mode)) {
76		(void) fprintf(stderr, gettext("nscadm: %s: not a valid device "
77		    "<%s>\n"), op, dev);
78		exit(255);
79	}
80}
81
82int
83main(int argc, char *argv[])
84{
85	extern int optind, opterr;
86	int opt, rc;
87
88	(void) setlocale(LC_ALL, "");
89	(void) textdomain("nscadm");
90
91	rc = 0;
92	opterr = 0;
93
94	while ((opt = getopt(argc, argv, "h")) != -1) {
95		switch (opt) {
96		case 'h':
97			usage();
98			exit(0);
99			break;
100		default:
101			usage();
102			exit(255);
103			break;
104		}
105	}
106
107	if (optind == argc) {
108		usage();
109		exit(255);
110	}
111
112	if (strcoll(argv[optind], gettext("freeze")) == 0 ||
113	    strcmp(argv[optind], "freeze") == 0) {
114		if (argc - optind != 2) {
115			usage();
116			exit(255);
117		}
118
119		is_chr_dev(argv[optind+1], "freeze");
120		rc = nsc_isfrozen(argv[optind+1]);
121		if (rc < 0) {
122			perror(gettext("nscadm: freeze"));
123			exit(255);
124		} else if (rc != 0) {
125			rc = nsc_freeze(argv[optind+1]);
126			if (rc < 0) {
127				perror(gettext("nscadm: freeze"));
128				exit(255);
129			}
130		} else {
131			(void) fprintf(stderr, gettext("nscadm: device <%s> is "
132			    "already frozen\n"), argv[optind+1]);
133			exit(255);
134		}
135
136		(void) printf(gettext("nscadm: device <%s> frozen\n"),
137		    argv[optind+1]);
138	} else if (strcoll(argv[optind], gettext("unfreeze")) == 0 ||
139	    strcmp(argv[optind], "unfreeze") == 0) {
140		if (argc - optind != 2) {
141			usage();
142			exit(255);
143		}
144
145		is_chr_dev(argv[optind+1], "unfreeze");
146		rc = nsc_isfrozen(argv[optind+1]);
147		if (rc < 0) {
148			perror(gettext("nscadm: unfreeze"));
149			exit(255);
150		} else if (rc == 0) {
151			rc = nsc_unfreeze(argv[optind+1]);
152			if (rc < 0) {
153				perror(gettext("nscadm: unfreeze"));
154				exit(255);
155			}
156		} else {
157			(void) fprintf(stderr,
158			    gettext("nscadm: device <%s> is not "
159			    "frozen\n"), argv[optind+1]);
160			exit(255);
161		}
162
163		(void) printf(gettext("nscadm: device <%s> unfrozen\n"),
164		    argv[optind+1]);
165	} else if (strcoll(argv[optind], gettext("isfrozen")) == 0 ||
166	    strcmp(argv[optind], "isfrozen") == 0) {
167		if (argc - optind != 2) {
168			usage();
169			exit(255);
170		}
171
172		is_chr_dev(argv[optind+1], "isfrozen");
173		rc = nsc_isfrozen(argv[optind+1]);
174		if (rc < 0) {
175			perror(gettext("nscadm: isfrozen"));
176			exit(255);
177		}
178
179		(void) printf(gettext("nscadm: device <%s> is %sfrozen\n"),
180		    argv[optind+1], rc ? gettext("not ") : "");
181#ifdef DEBUG
182	} else if (strcoll(argv[optind], gettext("nvclean")) == 0 ||
183	    strcmp(argv[optind], "nvclean") == 0) {
184		rc = nsc_nvclean(0);
185		if (rc < 0) {
186			perror(gettext("nscadm: nvclean"));
187			exit(255);
188		}
189	} else if (strcoll(argv[optind], gettext("nvclean_force")) == 0 ||
190	    strcmp(argv[optind], "nvclean_force") == 0) {
191		rc = nsc_nvclean(1);
192		if (rc < 0) {
193			perror(gettext("nscadm: nvclean_force"));
194			exit(255);
195		}
196#endif /* DEBUG */
197	} else if (strcoll(argv[optind], gettext("gmem")) == 0 ||
198	    strcmp(argv[optind], "gmem") == 0) {
199		rc = _nsc_gmem();
200		if (rc < 0) {
201			perror(gettext("nscadm: gmem"));
202			exit(255);
203		}
204	} else {
205		usage();
206		exit(255);
207	}
208
209	return (rc);
210}
211
212
213static int
214_nsc_gmem(void)
215{
216	char *addr;
217	int size;
218	int rc = 0;
219
220	rc = nsc_gmem_sizes(&size);
221
222	if (rc < 0)
223		return (rc);
224
225	(void) printf(gettext("size %d\n"), size);
226
227	if ((addr = (char *)malloc(size * 2)) == NULL) {
228		errno = ENOMEM;
229		return (-1);
230	}
231
232	rc = nsc_gmem_data(addr);
233
234	if (rc < 0) {
235		free(addr);
236		return (rc);
237	}
238
239	(void) printf(gettext("Global map entries:\n"));
240	show_maps(addr, size);
241
242	(void) printf(gettext("\nGlobal NVMEM map entries:\n"));
243	show_maps(addr + size, size);
244
245	free(addr);
246	return (0);
247}
248
249
250static void
251show_maps(char *addr, int len)
252{
253	/* LINTED alignment of cast ok */
254	nsc_rmhdr_t *rhp = (nsc_rmhdr_t *)addr;
255	nsc_rmmap_t *rmap;
256	char tname[_NSC_MAXNAME + 1];
257	int i;
258
259	(void) printf(
260	    gettext("magic 0x%x ver %d size %d dirty (nvmem systems): %d\n"),
261	    rhp->magic, rhp->ver, rhp->size, rhp->rh_dirty);
262
263	for (i = 0, rmap = rhp->map;
264		/* LINTED alignment of cast ok */
265	    rmap < (nsc_rmmap_t *)(addr + len); ++i, ++rmap) {
266		if (!rmap->name[0])
267			continue;
268		(void) strncpy(tname, rmap->name, _NSC_MAXNAME);
269		(void) strcpy(&tname[strlen(tname)], "                     ");
270		tname[_NSC_MAXNAME] = '\0';
271		(void) printf(gettext(
272		    "%d:\tname %s\toffset 0x%x size 0x%x inuse 0x%x\n"),
273		    i, tname, rmap->offset, rmap->size, rmap->inuse);
274	}
275}
276