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
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.
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]
23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
31 #include <dhcp_impl.h>
33 #include <sys/nvpair.h>
34 #include <netinet/inetutil.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
40 #include <sys/salib.h>
41 #include <sys/bootcmn.h>
44 #endif /* defined(_BOOT) */
46 #include <bootinfo_aux.h>
49 * Declarations and definitions describing parameters which may be known by
50 * a bootconf name, a property of /chosen, a DHCP option or a 'bootmisc' name.
53 const char *opt_name
; /* DHCP option name */
54 dsym_cdtype_t opt_type
; /* DHCP option type (dhcp_symbol.h) */
55 uchar_t opt_cat
; /* DHCP option category */
56 uint16_t opt_code
; /* DHCP option code */
57 uint16_t opt_size
; /* DHCP option size (FIELDs only) */
61 * Possible values for the 'bi_flags' field below.
63 #define BI_F_BYTES 0x01 /* chosen value is bytes, not string */
66 const char *bi_name
; /* parameter name */
67 int bi_repository
; /* entry's repository(s) */
68 int bi_flags
; /* BI_F_BYTES or zero */
69 bi_dhcpopt_t
*bi_dhcp
; /* &dhcpopt struct */
73 * DHCP options which have bootinfo equivalents, and the information
74 * necessary to retrieve their values via dhcp_getinfo(). The 'type'
75 * is necessary so that all values may be converted to ascii strings.
77 static bi_dhcpopt_t Yiaddr
= {
78 "Yiaddr", DSYM_IP
, DSYM_FIELD
, 16, 4
80 static bi_dhcpopt_t Subnet
= {
81 "Subnet", DSYM_IP
, DSYM_STANDARD
, 1, 0
83 static bi_dhcpopt_t Router
= {
84 "Router", DSYM_IP
, DSYM_STANDARD
, 3, 0
86 static bi_dhcpopt_t Hostname
= {
87 "Hostname", DSYM_ASCII
, DSYM_STANDARD
, 12, 0
89 static bi_dhcpopt_t ClientID
= {
90 "ClientID", DSYM_OCTET
, DSYM_STANDARD
, 61, 0
92 static bi_dhcpopt_t SHTTPproxy
= {
93 "SHTTPproxy", DSYM_ASCII
, DSYM_VENDOR
, 17, 0
96 static bi_dhcpopt_t BootFile
= {
97 "BootFile", DSYM_ASCII
, DSYM_FIELD
, 108, 128
99 static bi_dhcpopt_t SbootURI
= {
100 "SbootURI", DSYM_ASCII
, DSYM_VENDOR
, 16, 0
103 static bi_dhcpopt_t SsysidCF
= {
104 "SsysidCF", DSYM_ASCII
, DSYM_VENDOR
, 13, 0
106 static bi_dhcpopt_t SjumpsCF
= {
107 "SjumpsCF", DSYM_ASCII
, DSYM_VENDOR
, 14, 0
109 #endif /* defined(_BOOT) */
112 * bootinfo's main data structure.
114 static bi_param_t bi_params
[] = {
116 * Parameters from /chosen or DHCP:
118 { BI_HOST_IP
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
120 { BI_SUBNET_MASK
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
122 { BI_ROUTER_IP
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
124 { BI_HOSTNAME
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
126 { BI_CLIENT_ID
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
127 BI_F_BYTES
, &ClientID
},
128 { BI_HTTP_PROXY
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
133 * Parameters from /chosen or DHCP:
135 { BI_NETWORK_BOOT_FILE
, BI_R_CHOSEN
|BI_R_DHCPOPT
,
139 * Parameters from DHCP only:
141 { BI_BOOTFILE
, BI_R_DHCPOPT
,
145 * Parameters from /chosen only:
147 { BI_BOOTP_RESPONSE
, BI_R_CHOSEN
,
149 { BI_NET_CONFIG_STRATEGY
, BI_R_CHOSEN
,
153 * Parameters from 'bootmisc' only:
155 { BI_BOOTSERVER
, BI_R_BOOTMISC
,
157 { BI_AES_KEY
, BI_R_BOOTMISC
,
159 { BI_3DES_KEY
, BI_R_BOOTMISC
,
161 { BI_SHA1_KEY
, BI_R_BOOTMISC
,
165 * Parameters from DHCP only:
167 { BI_SYSIDCFG
, BI_R_DHCPOPT
,
169 { BI_JUMPSCFG
, BI_R_DHCPOPT
,
173 * Parameters from /chosen or 'bootmisc':
175 { BI_NET_CONFIG_STRATEGY
, BI_R_CHOSEN
|BI_R_BOOTMISC
,
179 * Parameters from 'bootmisc' only:
181 { BI_ROOTFS_TYPE
, BI_R_BOOTMISC
,
183 { BI_INTERFACE_NAME
, BI_R_BOOTMISC
,
185 #endif /* defined(_BOOT) */
191 * Bootmisc data is handled internally as a nvpair list.
193 static nvlist_t
*bi_nvl
= NULL
;
197 * Scan our parameter table to see whether 'name' matches any entry.
200 bi_find_param(const char *name
)
204 for (bip
= bi_params
; bip
->bi_name
!= NULL
; bip
++) {
205 if (strcmp(name
, bip
->bi_name
) == 0 ||
206 ((bip
->bi_repository
& BI_R_DHCPOPT
) &&
207 strcmp(name
, bip
->bi_dhcp
->opt_name
) == 0)) {
215 * Functions for retrieving /chosen, DHCP and bootmisc data.
218 bi_getval_chosen(bi_param_t
*bip
, void *valbuf
, size_t *vallenp
)
220 size_t buflen
= *vallenp
;
222 if (!bi_get_chosen_prop(bip
->bi_name
, valbuf
, vallenp
)) {
224 } else if (*vallenp
> buflen
) {
225 return (BI_E_BUF2SMALL
);
228 return (BI_E_SUCCESS
);
232 bi_getval_dhcpopt(bi_param_t
*bip
, void *valbuf
, size_t *vallenp
)
235 size_t len
, buflen
= *vallenp
;
236 struct in_addr ipaddr
;
238 if (bip
->bi_dhcp
->opt_type
== DSYM_IP
) {
240 len
= sizeof (ipaddr
);
246 if (!bi_get_dhcp_info(bip
->bi_dhcp
->opt_cat
, bip
->bi_dhcp
->opt_code
,
247 bip
->bi_dhcp
->opt_size
, val
, &len
)) {
251 switch (bip
->bi_dhcp
->opt_type
) {
253 if (buflen
< INET_ADDRSTRLEN
+ 1) {
255 return (BI_E_BUF2SMALL
);
257 len
= strlen(strcpy(valbuf
, inet_ntoa(ipaddr
))) + 1;
262 return (BI_E_BUF2SMALL
);
264 ((uchar_t
*)valbuf
)[len
++] = '\0';
269 return (BI_E_SUCCESS
);
273 bi_getval_bootmisc(bi_param_t
*bip
, void *valbuf
, size_t *vallenp
)
278 if (nvlist_lookup_byte_array(bi_nvl
, (char *)bip
->bi_name
,
281 } else if (*vallenp
< len
) {
283 return (BI_E_BUF2SMALL
);
286 (void) memcpy(valbuf
, val
, *vallenp
);
288 return (BI_E_SUCCESS
);
292 * This is also called from the userland bootinfo_aux.c to initialize
296 bi_put_bootmisc(const char *name
, const void *valbuf
, size_t vallen
)
298 return (nvlist_add_byte_array(bi_nvl
, (char *)name
,
299 (uchar_t
*)valbuf
, (uint_t
)vallen
) == 0);
304 * Functions for storing /chosen and bootmisc data.
307 bi_putval_chosen(bi_param_t
*bip
, const void *valbuf
, size_t vallen
)
309 return (bi_put_chosen_prop(bip
->bi_name
, valbuf
, vallen
,
310 (bip
->bi_flags
& BI_F_BYTES
)) ? BI_E_SUCCESS
: BI_E_ERROR
);
314 bi_putval_bootmisc(bi_param_t
*bip
, const void *valbuf
, size_t vallen
)
316 return (bi_put_bootmisc(bip
->bi_name
, valbuf
, vallen
)
317 ? BI_E_SUCCESS
: BI_E_ERROR
);
319 #endif /* defined(_BOOT) */
323 * Deallocate resources, etc. after accessing bootinfo.
328 if (bi_nvl
!= NULL
) {
336 * Perform bootinfo initialization.
341 if (bi_nvl
== NULL
&&
342 nvlist_alloc(&bi_nvl
, NV_UNIQUE_NAME
, 0) == 0) {
343 if (!bi_init_bootinfo()) {
349 return (bi_nvl
!= NULL
);
353 * bootinfo_get(const char *name, void *valbuf, size_t *vallenp,
356 * Obtain a value for a named boot parameter from one of a number of possible
359 * - stored properties under /chosen in the device tree;
360 * - returned DHCP data;
361 * - miscellaneous boot information, determined from the standalone or
362 * the kernel (depending on whether we're in the standalone or userland).
364 * These repositories are interrogated in the order listed above; the first
365 * one to match is value returned.
368 * 0 => successful, value copied to valbuf, length assigned to *vallen.
369 * >0 => error (BI_E_* codes defined in bootinfo.h)
372 bootinfo_get(const char *name
, void *valbufp
, size_t *vallenp
,
381 * Check whether we were successfully initialized.
383 if (bi_nvl
== NULL
) {
388 * Determine which repositories might be accessed; a NULL pointer
389 * means to (possibly) access them all.
391 if (repositoryp
!= NULL
) {
392 repositories
= *repositoryp
;
395 repositories
= BI_R_ALL
;
399 * Check that we know about this name in one or more of the
400 * requested repositories.
402 if ((bip
= bi_find_param(name
)) == NULL
) {
403 return (BI_E_ILLNAME
);
405 repositories
&= bip
->bi_repository
;
406 if (repositories
== 0) {
407 return (BI_E_ILLNAME
);
411 * The caller may simply be enquiring whether a value is present:
413 * bootinfo_get(name, NULL, NULL, repository) == BI_E_BUF2SMALL
415 * indicates that there is a value, but doesn't fetch it.
417 if (vallenp
== NULL
) {
422 * To retrieve a value, try the various repositories in order.
424 if ((repositories
& BI_R_CHOSEN
) != 0 &&
425 (err
= bi_getval_chosen(bip
, valbufp
, vallenp
)) != BI_E_NOVAL
) {
426 if (repositoryp
!= NULL
) {
427 *repositoryp
= BI_R_CHOSEN
;
431 if ((repositories
& BI_R_DHCPOPT
) != 0 &&
432 (err
= bi_getval_dhcpopt(bip
, valbufp
, vallenp
)) != BI_E_NOVAL
) {
433 if (repositoryp
!= NULL
) {
434 *repositoryp
= BI_R_DHCPOPT
;
438 if ((repositories
& BI_R_BOOTMISC
) != 0 &&
439 (err
= bi_getval_bootmisc(bip
, valbufp
, vallenp
)) != BI_E_NOVAL
) {
440 if (repositoryp
!= NULL
) {
441 *repositoryp
= BI_R_BOOTMISC
;
447 * No-one has a value for 'name'.
454 * bootinfo_put(const char *name, char *valbuf, int vallen,
457 * Create/update a value in the bootinfo repository (standalone only).
460 * 0 => successful, valbuf[0..vallen-1] bytes stored in repository
461 * >0 => error (BI_E_* codes defined in bootinfo.h)
464 bootinfo_put(const char *name
, const void *valbuf
, size_t vallen
,
470 * Check whether we were successfully initialized.
472 if (bi_nvl
== NULL
) {
477 * Determine which repositories might be accessed; a zero value
478 * means to (possibly) access them all.
480 if (repository
== 0) {
481 repository
= BI_R_ALL
;
485 * Check that we know about this name in the specified repository,
486 * and that it may be written (note that DHCP options cannot be
489 if ((bip
= bi_find_param(name
)) == NULL
||
490 (repository
& bip
->bi_repository
) == 0) {
491 return (BI_E_ILLNAME
);
493 if ((repository
& bip
->bi_repository
) == BI_R_DHCPOPT
) {
494 return (BI_E_RDONLY
);
498 * To put the value, try the various repositories in order.
500 if ((bip
->bi_repository
& BI_R_CHOSEN
) != 0) {
501 return (bi_putval_chosen(bip
, valbuf
, vallen
));
503 if ((bip
->bi_repository
& BI_R_BOOTMISC
) != 0) {
504 return (bi_putval_bootmisc(bip
, valbuf
, vallen
));
509 #endif /* defined(_BOOT) */