1*e71ca95cSGerald Jelinek /*
2*e71ca95cSGerald Jelinek  * CDDL HEADER START
3*e71ca95cSGerald Jelinek  *
4*e71ca95cSGerald Jelinek  * The contents of this file are subject to the terms of the
5*e71ca95cSGerald Jelinek  * Common Development and Distribution License (the "License").
6*e71ca95cSGerald Jelinek  * You may not use this file except in compliance with the License.
7*e71ca95cSGerald Jelinek  *
8*e71ca95cSGerald Jelinek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*e71ca95cSGerald Jelinek  * or http://www.opensolaris.org/os/licensing.
10*e71ca95cSGerald Jelinek  * See the License for the specific language governing permissions
11*e71ca95cSGerald Jelinek  * and limitations under the License.
12*e71ca95cSGerald Jelinek  *
13*e71ca95cSGerald Jelinek  * When distributing Covered Code, include this CDDL HEADER in each
14*e71ca95cSGerald Jelinek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*e71ca95cSGerald Jelinek  * If applicable, add the following below this CDDL HEADER, with the
16*e71ca95cSGerald Jelinek  * fields enclosed by brackets "[]" replaced with your own identifying
17*e71ca95cSGerald Jelinek  * information: Portions Copyright [yyyy] [name of copyright owner]
18*e71ca95cSGerald Jelinek  *
19*e71ca95cSGerald Jelinek  * CDDL HEADER END
20*e71ca95cSGerald Jelinek  */
21*e71ca95cSGerald Jelinek /*
22*e71ca95cSGerald Jelinek  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*e71ca95cSGerald Jelinek  * Use is subject to license terms.
24*e71ca95cSGerald Jelinek  */
25*e71ca95cSGerald Jelinek 
26*e71ca95cSGerald Jelinek /*
27*e71ca95cSGerald Jelinek  * s10_support is a small cli utility used to perform some brand-specific
28*e71ca95cSGerald Jelinek  * tasks when verifying a zone.  This utility is not intended to be called
29*e71ca95cSGerald Jelinek  * by users - it is intended to be invoked by the zones utilities.
30*e71ca95cSGerald Jelinek  */
31*e71ca95cSGerald Jelinek 
32*e71ca95cSGerald Jelinek #include <ctype.h>
33*e71ca95cSGerald Jelinek #include <errno.h>
34*e71ca95cSGerald Jelinek #include <fcntl.h>
35*e71ca95cSGerald Jelinek #include <libgen.h>
36*e71ca95cSGerald Jelinek #include <limits.h>
37*e71ca95cSGerald Jelinek #include <s10_brand.h>
38*e71ca95cSGerald Jelinek #include <stdarg.h>
39*e71ca95cSGerald Jelinek #include <stdio.h>
40*e71ca95cSGerald Jelinek #include <stdlib.h>
41*e71ca95cSGerald Jelinek #include <string.h>
42*e71ca95cSGerald Jelinek #include <strings.h>
43*e71ca95cSGerald Jelinek #include <stropts.h>
44*e71ca95cSGerald Jelinek #include <sys/stat.h>
45*e71ca95cSGerald Jelinek #include <sys/types.h>
46*e71ca95cSGerald Jelinek #include <sys/utsname.h>
47*e71ca95cSGerald Jelinek #include <sys/varargs.h>
48*e71ca95cSGerald Jelinek #include <unistd.h>
49*e71ca95cSGerald Jelinek #include <libintl.h>
50*e71ca95cSGerald Jelinek #include <locale.h>
51*e71ca95cSGerald Jelinek #include <dirent.h>
52*e71ca95cSGerald Jelinek #include <sys/systeminfo.h>
53*e71ca95cSGerald Jelinek 
54*e71ca95cSGerald Jelinek #include <libzonecfg.h>
55*e71ca95cSGerald Jelinek 
56*e71ca95cSGerald Jelinek static void s10_err(char *msg, ...) __NORETURN;
57*e71ca95cSGerald Jelinek static void usage(void) __NORETURN;
58*e71ca95cSGerald Jelinek 
59*e71ca95cSGerald Jelinek /*
60*e71ca95cSGerald Jelinek  * XXX This is a temporary flag for the initial release to enable the
61*e71ca95cSGerald Jelinek  * use of features which are not yet tested or fully implemented.
62*e71ca95cSGerald Jelinek  */
63*e71ca95cSGerald Jelinek static boolean_t override = B_FALSE;
64*e71ca95cSGerald Jelinek 
65*e71ca95cSGerald Jelinek static char *bname = NULL;
66*e71ca95cSGerald Jelinek 
67*e71ca95cSGerald Jelinek #define	PKGINFO_RD_LEN	128
68*e71ca95cSGerald Jelinek #define	PATCHLIST	"PATCHLIST="
69*e71ca95cSGerald Jelinek 
70*e71ca95cSGerald Jelinek #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
71*e71ca95cSGerald Jelinek #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
72*e71ca95cSGerald Jelinek #endif
73*e71ca95cSGerald Jelinek 
74*e71ca95cSGerald Jelinek /*PRINTFLIKE1*/
75*e71ca95cSGerald Jelinek static void
76*e71ca95cSGerald Jelinek s10_err(char *msg, ...)
77*e71ca95cSGerald Jelinek {
78*e71ca95cSGerald Jelinek 	char	buf[1024];
79*e71ca95cSGerald Jelinek 	va_list	ap;
80*e71ca95cSGerald Jelinek 
81*e71ca95cSGerald Jelinek 	va_start(ap, msg);
82*e71ca95cSGerald Jelinek 	(void) vsnprintf(buf, sizeof (buf), msg, ap);
83*e71ca95cSGerald Jelinek 	va_end(ap);
84*e71ca95cSGerald Jelinek 
85*e71ca95cSGerald Jelinek 	/* This needs go to stdout so the msgs show up through zoneadm. */
86*e71ca95cSGerald Jelinek 	(void) printf("Error: %s\n", buf);
87*e71ca95cSGerald Jelinek 
88*e71ca95cSGerald Jelinek 	exit(1);
89*e71ca95cSGerald Jelinek 	/*NOTREACHED*/
90*e71ca95cSGerald Jelinek }
91*e71ca95cSGerald Jelinek 
92*e71ca95cSGerald Jelinek static int
93*e71ca95cSGerald Jelinek s10_verify(char *xmlfile)
94*e71ca95cSGerald Jelinek {
95*e71ca95cSGerald Jelinek 	zone_dochandle_t	handle;
96*e71ca95cSGerald Jelinek 	struct zone_fstab	fstab;
97*e71ca95cSGerald Jelinek 	struct zone_devtab	devtab;
98*e71ca95cSGerald Jelinek 	zone_iptype_t		iptype;
99*e71ca95cSGerald Jelinek 	struct zone_dstab	dstab;
100*e71ca95cSGerald Jelinek 
101*e71ca95cSGerald Jelinek 	if ((handle = zonecfg_init_handle()) == NULL)
102*e71ca95cSGerald Jelinek 		s10_err(gettext("internal libzonecfg.so.1 error"), 0);
103*e71ca95cSGerald Jelinek 
104*e71ca95cSGerald Jelinek 	if (zonecfg_get_xml_handle(xmlfile, handle) != Z_OK) {
105*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
106*e71ca95cSGerald Jelinek 		s10_err(gettext("zonecfg provided an invalid XML file"));
107*e71ca95cSGerald Jelinek 	}
108*e71ca95cSGerald Jelinek 
109*e71ca95cSGerald Jelinek 	/*
110*e71ca95cSGerald Jelinek 	 * Check to see whether the zone has any inherit-pkg-dirs
111*e71ca95cSGerald Jelinek 	 * configured.
112*e71ca95cSGerald Jelinek 	 */
113*e71ca95cSGerald Jelinek 	if (zonecfg_setipdent(handle) != Z_OK) {
114*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
115*e71ca95cSGerald Jelinek 		s10_err(gettext("zonecfg provided an invalid XML file"));
116*e71ca95cSGerald Jelinek 	}
117*e71ca95cSGerald Jelinek 	if (zonecfg_getipdent(handle, &fstab) == Z_OK) {
118*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
119*e71ca95cSGerald Jelinek 		s10_err(gettext("solaris10 zones do not support "
120*e71ca95cSGerald Jelinek 		    "inherit-pkg-dirs"));
121*e71ca95cSGerald Jelinek 	}
122*e71ca95cSGerald Jelinek 	(void) zonecfg_endipdent(handle);
123*e71ca95cSGerald Jelinek 
124*e71ca95cSGerald Jelinek 	/*
125*e71ca95cSGerald Jelinek 	 * Check to see whether the zone has any unsupported devices
126*e71ca95cSGerald Jelinek 	 * configured.
127*e71ca95cSGerald Jelinek 	 *
128*e71ca95cSGerald Jelinek 	 * The audio framework has changed in Solaris Next as compared to
129*e71ca95cSGerald Jelinek 	 * S10.  Data indicates the less than 1/10 of 1 percent of zones
130*e71ca95cSGerald Jelinek 	 * are using /dev/sound.  Given the low usage vs. the effort to
131*e71ca95cSGerald Jelinek 	 * provide emulation, /dev/sound is currently disallowed.  We can
132*e71ca95cSGerald Jelinek 	 * revisit this if there is enough demand.
133*e71ca95cSGerald Jelinek 	 */
134*e71ca95cSGerald Jelinek 	if (zonecfg_setdevent(handle) != Z_OK) {
135*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
136*e71ca95cSGerald Jelinek 		s10_err(gettext("zonecfg provided an invalid XML file"));
137*e71ca95cSGerald Jelinek 	}
138*e71ca95cSGerald Jelinek 	if (zonecfg_getdevent(handle, &devtab) == Z_OK) {
139*e71ca95cSGerald Jelinek 		if (strncmp(devtab.zone_dev_match, "/dev/sound", 10) == 0 &&
140*e71ca95cSGerald Jelinek 		    !override) {
141*e71ca95cSGerald Jelinek 			zonecfg_fini_handle(handle);
142*e71ca95cSGerald Jelinek 			s10_err(gettext("solaris10 zones do not currently "
143*e71ca95cSGerald Jelinek 			    "support /dev/sound"));
144*e71ca95cSGerald Jelinek 		}
145*e71ca95cSGerald Jelinek 	}
146*e71ca95cSGerald Jelinek 	(void) zonecfg_enddevent(handle);
147*e71ca95cSGerald Jelinek 
148*e71ca95cSGerald Jelinek 	/*
149*e71ca95cSGerald Jelinek 	 * Check to see whether the zone has any experimental features
150*e71ca95cSGerald Jelinek 	 * configured.
151*e71ca95cSGerald Jelinek 	 */
152*e71ca95cSGerald Jelinek 	if (zonecfg_get_iptype(handle, &iptype) == Z_OK &&
153*e71ca95cSGerald Jelinek 	    iptype == ZS_EXCLUSIVE && !override) {
154*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
155*e71ca95cSGerald Jelinek 		s10_err(gettext("solaris10 zones do not currently support "
156*e71ca95cSGerald Jelinek 		    "exclusive ip-type stacks"));
157*e71ca95cSGerald Jelinek 	}
158*e71ca95cSGerald Jelinek 
159*e71ca95cSGerald Jelinek 	if (zonecfg_setdsent(handle) != Z_OK) {
160*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
161*e71ca95cSGerald Jelinek 		s10_err(gettext("zonecfg provided an invalid XML file"));
162*e71ca95cSGerald Jelinek 	}
163*e71ca95cSGerald Jelinek 	if (zonecfg_getdsent(handle, &dstab) == Z_OK && !override) {
164*e71ca95cSGerald Jelinek 		zonecfg_fini_handle(handle);
165*e71ca95cSGerald Jelinek 		s10_err(gettext("solaris10 zones do not currently support "
166*e71ca95cSGerald Jelinek 		    "delegated datasets"));
167*e71ca95cSGerald Jelinek 	}
168*e71ca95cSGerald Jelinek 	(void) zonecfg_enddsent(handle);
169*e71ca95cSGerald Jelinek 
170*e71ca95cSGerald Jelinek 	zonecfg_fini_handle(handle);
171*e71ca95cSGerald Jelinek 	return (0);
172*e71ca95cSGerald Jelinek }
173*e71ca95cSGerald Jelinek 
174*e71ca95cSGerald Jelinek /*
175*e71ca95cSGerald Jelinek  * Read an entry from a pkginfo file.  Some of these lines can
176*e71ca95cSGerald Jelinek  * either be arbitrarily long or be continued by a backslash at the end of
177*e71ca95cSGerald Jelinek  * the line.  This function coalesces lines that are longer than the read
178*e71ca95cSGerald Jelinek  * buffer, and lines that are continued, into one buffer which is returned.
179*e71ca95cSGerald Jelinek  * The caller must free this memory.  NULL is returned when we hit EOF or
180*e71ca95cSGerald Jelinek  * if we run out of memory (errno is set to ENOMEM).
181*e71ca95cSGerald Jelinek  */
182*e71ca95cSGerald Jelinek static char *
183*e71ca95cSGerald Jelinek read_pkg_data(FILE *fp)
184*e71ca95cSGerald Jelinek {
185*e71ca95cSGerald Jelinek 	char *start;
186*e71ca95cSGerald Jelinek 	char *inp;
187*e71ca95cSGerald Jelinek 	char *p;
188*e71ca95cSGerald Jelinek 	int char_cnt = 0;
189*e71ca95cSGerald Jelinek 
190*e71ca95cSGerald Jelinek 	errno = 0;
191*e71ca95cSGerald Jelinek 	if ((start = (char *)malloc(PKGINFO_RD_LEN)) == NULL) {
192*e71ca95cSGerald Jelinek 		errno = ENOMEM;
193*e71ca95cSGerald Jelinek 		return (NULL);
194*e71ca95cSGerald Jelinek 	}
195*e71ca95cSGerald Jelinek 
196*e71ca95cSGerald Jelinek 	inp = start;
197*e71ca95cSGerald Jelinek 	while ((p = fgets(inp, PKGINFO_RD_LEN, fp)) != NULL) {
198*e71ca95cSGerald Jelinek 		int len;
199*e71ca95cSGerald Jelinek 
200*e71ca95cSGerald Jelinek 		len = strlen(inp);
201*e71ca95cSGerald Jelinek 		if (inp[len - 1] == '\n' &&
202*e71ca95cSGerald Jelinek 		    (len == 1 || inp[len - 2] != '\\')) {
203*e71ca95cSGerald Jelinek 			char_cnt = len;
204*e71ca95cSGerald Jelinek 			break;
205*e71ca95cSGerald Jelinek 		}
206*e71ca95cSGerald Jelinek 
207*e71ca95cSGerald Jelinek 		if (inp[len - 1] == '\n' && inp[len - 2] == '\\')
208*e71ca95cSGerald Jelinek 			char_cnt += len - 2;
209*e71ca95cSGerald Jelinek 		else
210*e71ca95cSGerald Jelinek 			char_cnt += PKGINFO_RD_LEN - 1;
211*e71ca95cSGerald Jelinek 
212*e71ca95cSGerald Jelinek 		if ((p = realloc(start, char_cnt + PKGINFO_RD_LEN)) == NULL) {
213*e71ca95cSGerald Jelinek 			errno = ENOMEM;
214*e71ca95cSGerald Jelinek 			break;
215*e71ca95cSGerald Jelinek 		}
216*e71ca95cSGerald Jelinek 
217*e71ca95cSGerald Jelinek 		start = p;
218*e71ca95cSGerald Jelinek 		inp = start + char_cnt;
219*e71ca95cSGerald Jelinek 	}
220*e71ca95cSGerald Jelinek 
221*e71ca95cSGerald Jelinek 	if (errno == ENOMEM || (p == NULL && char_cnt == 0)) {
222*e71ca95cSGerald Jelinek 		free(start);
223*e71ca95cSGerald Jelinek 		start = NULL;
224*e71ca95cSGerald Jelinek 	}
225*e71ca95cSGerald Jelinek 
226*e71ca95cSGerald Jelinek 	return (start);
227*e71ca95cSGerald Jelinek }
228*e71ca95cSGerald Jelinek 
229*e71ca95cSGerald Jelinek /*
230*e71ca95cSGerald Jelinek  * Read the SUNWcakr pkginfo file and get the PATCHLIST for the pkg.
231*e71ca95cSGerald Jelinek  */
232*e71ca95cSGerald Jelinek static int
233*e71ca95cSGerald Jelinek get_ku_patchlist(char *zonename, char **patchlist)
234*e71ca95cSGerald Jelinek {
235*e71ca95cSGerald Jelinek 	char		zonepath[MAXPATHLEN];
236*e71ca95cSGerald Jelinek 	char		pkginfo[MAXPATHLEN];
237*e71ca95cSGerald Jelinek 	FILE		*fp;
238*e71ca95cSGerald Jelinek 	char		*buf;
239*e71ca95cSGerald Jelinek 	int		err = 0;
240*e71ca95cSGerald Jelinek 
241*e71ca95cSGerald Jelinek 	if (zone_get_zonepath(zonename, zonepath, sizeof (zonepath)) != Z_OK)
242*e71ca95cSGerald Jelinek 		s10_err(gettext("error getting zone's path"));
243*e71ca95cSGerald Jelinek 
244*e71ca95cSGerald Jelinek 	if (snprintf(pkginfo, sizeof (pkginfo),
245*e71ca95cSGerald Jelinek 	    "%s/root/var/sadm/pkg/SUNWcakr/pkginfo", zonepath)
246*e71ca95cSGerald Jelinek 	    >= sizeof (pkginfo))
247*e71ca95cSGerald Jelinek 		s10_err(gettext("error formating pkg path"));
248*e71ca95cSGerald Jelinek 
249*e71ca95cSGerald Jelinek 	if ((fp = fopen(pkginfo, "r")) == NULL)
250*e71ca95cSGerald Jelinek 		return (errno);
251*e71ca95cSGerald Jelinek 
252*e71ca95cSGerald Jelinek 	while ((buf = read_pkg_data(fp)) != NULL) {
253*e71ca95cSGerald Jelinek 		if (strncmp(buf, PATCHLIST, sizeof (PATCHLIST) - 1) == 0) {
254*e71ca95cSGerald Jelinek 			int len;
255*e71ca95cSGerald Jelinek 
256*e71ca95cSGerald Jelinek 			/* remove trailing newline */
257*e71ca95cSGerald Jelinek 			len = strlen(buf);
258*e71ca95cSGerald Jelinek 			buf[len - 1] = '\0';
259*e71ca95cSGerald Jelinek 
260*e71ca95cSGerald Jelinek 			if ((*patchlist =
261*e71ca95cSGerald Jelinek 			    strdup(buf + sizeof (PATCHLIST) - 1)) == NULL)
262*e71ca95cSGerald Jelinek 				err = ENOMEM;
263*e71ca95cSGerald Jelinek 
264*e71ca95cSGerald Jelinek 			free(buf);
265*e71ca95cSGerald Jelinek 			break;
266*e71ca95cSGerald Jelinek 		}
267*e71ca95cSGerald Jelinek 
268*e71ca95cSGerald Jelinek 		free(buf);
269*e71ca95cSGerald Jelinek 	}
270*e71ca95cSGerald Jelinek 	(void) fclose(fp);
271*e71ca95cSGerald Jelinek 
272*e71ca95cSGerald Jelinek 	return (err);
273*e71ca95cSGerald Jelinek }
274*e71ca95cSGerald Jelinek 
275*e71ca95cSGerald Jelinek /*
276*e71ca95cSGerald Jelinek  * Verify that we have the minimum KU needed.
277*e71ca95cSGerald Jelinek  * Note that KU patches are accumulative so future KUs will still deliver
278*e71ca95cSGerald Jelinek  * 141444 or 141445.
279*e71ca95cSGerald Jelinek  */
280*e71ca95cSGerald Jelinek static boolean_t
281*e71ca95cSGerald Jelinek have_valid_ku(char *zonename)
282*e71ca95cSGerald Jelinek {
283*e71ca95cSGerald Jelinek 	char		*p;
284*e71ca95cSGerald Jelinek 	char		*lastp;
285*e71ca95cSGerald Jelinek 	char		*pstr;
286*e71ca95cSGerald Jelinek 	char		*patchlist = NULL;
287*e71ca95cSGerald Jelinek 	int		i;
288*e71ca95cSGerald Jelinek 	char 		*vers_table[] = {
289*e71ca95cSGerald Jelinek 			    "141444-09",
290*e71ca95cSGerald Jelinek 			    "141445-09",
291*e71ca95cSGerald Jelinek 			    NULL};
292*e71ca95cSGerald Jelinek 
293*e71ca95cSGerald Jelinek 	if (get_ku_patchlist(zonename, &patchlist) != 0 || patchlist == NULL)
294*e71ca95cSGerald Jelinek 		return (B_FALSE);
295*e71ca95cSGerald Jelinek 
296*e71ca95cSGerald Jelinek 	pstr = patchlist;
297*e71ca95cSGerald Jelinek 	while ((p = strtok_r(pstr, " ", &lastp)) != NULL) {
298*e71ca95cSGerald Jelinek 		for (i = 0; vers_table[i] != NULL; i++)
299*e71ca95cSGerald Jelinek 			if (strcmp(p, vers_table[i]) == 0)
300*e71ca95cSGerald Jelinek 				return (B_TRUE);
301*e71ca95cSGerald Jelinek 
302*e71ca95cSGerald Jelinek 		pstr = NULL;
303*e71ca95cSGerald Jelinek 	}
304*e71ca95cSGerald Jelinek 
305*e71ca95cSGerald Jelinek 	return (B_FALSE);
306*e71ca95cSGerald Jelinek }
307*e71ca95cSGerald Jelinek 
308*e71ca95cSGerald Jelinek /*
309*e71ca95cSGerald Jelinek  * Get the emulation version from the /usr/lib/brand/solaris10/version file
310*e71ca95cSGerald Jelinek  * in either the global zone or the non-global zone.
311*e71ca95cSGerald Jelinek  */
312*e71ca95cSGerald Jelinek static int
313*e71ca95cSGerald Jelinek get_emul_version_number(char *verspath)
314*e71ca95cSGerald Jelinek {
315*e71ca95cSGerald Jelinek 	int	vers = 0;
316*e71ca95cSGerald Jelinek 	FILE	*fp;
317*e71ca95cSGerald Jelinek 	char	buf[LINE_MAX];
318*e71ca95cSGerald Jelinek 
319*e71ca95cSGerald Jelinek 	/* If the file doesn't exist, assume version 0 */
320*e71ca95cSGerald Jelinek 	if ((fp = fopen(verspath, "r")) == NULL)
321*e71ca95cSGerald Jelinek 		return (vers);
322*e71ca95cSGerald Jelinek 
323*e71ca95cSGerald Jelinek 	while (fgets(buf, sizeof (buf), fp) != NULL) {
324*e71ca95cSGerald Jelinek 		if (buf[0] == '#')
325*e71ca95cSGerald Jelinek 			continue;
326*e71ca95cSGerald Jelinek 
327*e71ca95cSGerald Jelinek 		errno = 0;
328*e71ca95cSGerald Jelinek 		vers = strtol(buf, (char **)NULL, 10);
329*e71ca95cSGerald Jelinek 		if (errno != 0) {
330*e71ca95cSGerald Jelinek 			(void) fclose(fp);
331*e71ca95cSGerald Jelinek 			s10_err(gettext("error reading minimum version"));
332*e71ca95cSGerald Jelinek 		}
333*e71ca95cSGerald Jelinek 	}
334*e71ca95cSGerald Jelinek 
335*e71ca95cSGerald Jelinek 	(void) fclose(fp);
336*e71ca95cSGerald Jelinek 
337*e71ca95cSGerald Jelinek 	return (vers);
338*e71ca95cSGerald Jelinek }
339*e71ca95cSGerald Jelinek 
340*e71ca95cSGerald Jelinek /*
341*e71ca95cSGerald Jelinek  * Get the current emulation version that is implemented.
342*e71ca95cSGerald Jelinek  */
343*e71ca95cSGerald Jelinek static int
344*e71ca95cSGerald Jelinek get_current_emul_version()
345*e71ca95cSGerald Jelinek {
346*e71ca95cSGerald Jelinek 	return (get_emul_version_number("/usr/lib/brand/solaris10/version"));
347*e71ca95cSGerald Jelinek }
348*e71ca95cSGerald Jelinek 
349*e71ca95cSGerald Jelinek /*
350*e71ca95cSGerald Jelinek  * Get the emulation version that the S10 image requires.  This
351*e71ca95cSGerald Jelinek  * reads the optional /usr/lib/brand/solaris10/version file that might
352*e71ca95cSGerald Jelinek  * exist on Solaris 10.  That file specifies the minimal solaris10 brand
353*e71ca95cSGerald Jelinek  * emulation version that the specific release of S10 requires.  If no
354*e71ca95cSGerald Jelinek  * minimal version is specified, the initial emulation remains compatible.
355*e71ca95cSGerald Jelinek  *
356*e71ca95cSGerald Jelinek  * If a new KU patch is created which needs different handling by the
357*e71ca95cSGerald Jelinek  * emulation, then the S10 /usr/lib/brand/solaris10/version file should be
358*e71ca95cSGerald Jelinek  * updated to specify a new version.
359*e71ca95cSGerald Jelinek  */
360*e71ca95cSGerald Jelinek static int
361*e71ca95cSGerald Jelinek get_image_emul_rqd_version(char *zonename)
362*e71ca95cSGerald Jelinek {
363*e71ca95cSGerald Jelinek 	char	zonepath[MAXPATHLEN];
364*e71ca95cSGerald Jelinek 	char	verspath[MAXPATHLEN];
365*e71ca95cSGerald Jelinek 
366*e71ca95cSGerald Jelinek 	if (zone_get_zonepath(zonename, zonepath, sizeof (zonepath)) != Z_OK)
367*e71ca95cSGerald Jelinek 		s10_err(gettext("error getting zone's path"));
368*e71ca95cSGerald Jelinek 
369*e71ca95cSGerald Jelinek 	if (snprintf(verspath, sizeof (verspath),
370*e71ca95cSGerald Jelinek 	    "%s/root/usr/lib/brand/solaris10/version",
371*e71ca95cSGerald Jelinek 	    zonepath) >= sizeof (verspath))
372*e71ca95cSGerald Jelinek 		s10_err(gettext("error formating version path"));
373*e71ca95cSGerald Jelinek 
374*e71ca95cSGerald Jelinek 	return (get_emul_version_number(verspath));
375*e71ca95cSGerald Jelinek }
376*e71ca95cSGerald Jelinek 
377*e71ca95cSGerald Jelinek static void
378*e71ca95cSGerald Jelinek fail_xvm()
379*e71ca95cSGerald Jelinek {
380*e71ca95cSGerald Jelinek 	char buf[80];
381*e71ca95cSGerald Jelinek 
382*e71ca95cSGerald Jelinek 	if (sysinfo(SI_PLATFORM, buf, sizeof (buf)) != -1 &&
383*e71ca95cSGerald Jelinek 	    strcmp(buf, "i86xpv") == 0 && !override)
384*e71ca95cSGerald Jelinek 		s10_err(gettext("running the solaris10 brand "
385*e71ca95cSGerald Jelinek 		    "in a paravirtualized\ndomain is currently not supported"));
386*e71ca95cSGerald Jelinek }
387*e71ca95cSGerald Jelinek 
388*e71ca95cSGerald Jelinek static int
389*e71ca95cSGerald Jelinek s10_boot(char *zonename)
390*e71ca95cSGerald Jelinek {
391*e71ca95cSGerald Jelinek 	zoneid_t zoneid;
392*e71ca95cSGerald Jelinek 	int emul_vers;
393*e71ca95cSGerald Jelinek 	int rqd_emul_vers;
394*e71ca95cSGerald Jelinek 
395*e71ca95cSGerald Jelinek 	if (!have_valid_ku(zonename))
396*e71ca95cSGerald Jelinek 		s10_err(gettext("The installed version of Solaris 10 is "
397*e71ca95cSGerald Jelinek 		    "not supported"));
398*e71ca95cSGerald Jelinek 
399*e71ca95cSGerald Jelinek 	emul_vers = get_current_emul_version();
400*e71ca95cSGerald Jelinek 	rqd_emul_vers = get_image_emul_rqd_version(zonename);
401*e71ca95cSGerald Jelinek 
402*e71ca95cSGerald Jelinek 	if (rqd_emul_vers > emul_vers)
403*e71ca95cSGerald Jelinek 		s10_err(gettext("The zone's version of Solaris 10 is "
404*e71ca95cSGerald Jelinek 		    "incompatible with the current version of the solaris10 "
405*e71ca95cSGerald Jelinek 		    "brand."));
406*e71ca95cSGerald Jelinek 
407*e71ca95cSGerald Jelinek 	if ((zoneid = getzoneidbyname(zonename)) < 0)
408*e71ca95cSGerald Jelinek 		s10_err(gettext("unable to get zoneid"));
409*e71ca95cSGerald Jelinek 
410*e71ca95cSGerald Jelinek 	if (zone_setattr(zoneid, S10_EMUL_VERSION_NUM, &rqd_emul_vers,
411*e71ca95cSGerald Jelinek 	    sizeof (int)) == -1)
412*e71ca95cSGerald Jelinek 		s10_err(gettext("error setting zone's emulation version "
413*e71ca95cSGerald Jelinek 		    "property"));
414*e71ca95cSGerald Jelinek 
415*e71ca95cSGerald Jelinek 	fail_xvm();
416*e71ca95cSGerald Jelinek 
417*e71ca95cSGerald Jelinek 	return (0);
418*e71ca95cSGerald Jelinek }
419*e71ca95cSGerald Jelinek 
420*e71ca95cSGerald Jelinek static void
421*e71ca95cSGerald Jelinek usage()
422*e71ca95cSGerald Jelinek {
423*e71ca95cSGerald Jelinek 	(void) fprintf(stderr, gettext(
424*e71ca95cSGerald Jelinek 	    "usage:\t%s verify <xml file>\n"
425*e71ca95cSGerald Jelinek 	    "\t%s boot\n"),
426*e71ca95cSGerald Jelinek 	    bname, bname);
427*e71ca95cSGerald Jelinek 	exit(1);
428*e71ca95cSGerald Jelinek }
429*e71ca95cSGerald Jelinek 
430*e71ca95cSGerald Jelinek int
431*e71ca95cSGerald Jelinek main(int argc, char *argv[])
432*e71ca95cSGerald Jelinek {
433*e71ca95cSGerald Jelinek 	(void) setlocale(LC_ALL, "");
434*e71ca95cSGerald Jelinek 	(void) textdomain(TEXT_DOMAIN);
435*e71ca95cSGerald Jelinek 
436*e71ca95cSGerald Jelinek 	bname = basename(argv[0]);
437*e71ca95cSGerald Jelinek 
438*e71ca95cSGerald Jelinek 	if (argc != 3)
439*e71ca95cSGerald Jelinek 		usage();
440*e71ca95cSGerald Jelinek 
441*e71ca95cSGerald Jelinek 	/*
442*e71ca95cSGerald Jelinek 	 * XXX This is a temporary env variable for the initial release to
443*e71ca95cSGerald Jelinek 	 * enable the use of features which are not yet tested or fully
444*e71ca95cSGerald Jelinek 	 * implemented.
445*e71ca95cSGerald Jelinek 	 */
446*e71ca95cSGerald Jelinek 	if (getenv("S10BRAND_TEST") != NULL)
447*e71ca95cSGerald Jelinek 		override = B_TRUE;
448*e71ca95cSGerald Jelinek 
449*e71ca95cSGerald Jelinek 	if (strcmp(argv[1], "verify") == 0)
450*e71ca95cSGerald Jelinek 		return (s10_verify(argv[2]));
451*e71ca95cSGerald Jelinek 
452*e71ca95cSGerald Jelinek 	if (strcmp(argv[1], "boot") == 0)
453*e71ca95cSGerald Jelinek 		return (s10_boot(argv[2]));
454*e71ca95cSGerald Jelinek 
455*e71ca95cSGerald Jelinek 	usage();
456*e71ca95cSGerald Jelinek 	/*NOTREACHED*/
457*e71ca95cSGerald Jelinek }
458