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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
35 #include <sys/types.h>
39 #include <sys/modctl.h>
41 #include <sys/openpromio.h>
44 #include <sys/sunddi.h>
47 #include "device_info.h"
53 /* alias node searching return values */
56 #define INEXACT_MATCH 2
58 /* for prom io operations */
60 #define MAXPROPSIZE 256
61 #define MAXVALSIZE (BUFSIZE - MAXPROPSIZE - sizeof (uint_t))
63 /* prom_obp_vers() return values */
64 #define OBP_OF 0x4 /* versions OBP 3.x */
65 #define OBP_NO_ALIAS_NODE 0x8 /* No alias node */
70 /* default logical and physical device name space */
72 #define DEVICES "/devices"
74 /* for boot device identification on x86 */
75 #define CREATE_DISKMAP "/boot/solaris/bin/create_diskmap"
76 #define GRUBDISK_MAP "/var/run/solaris_grubdisk.map"
79 * internal structure declarations
82 /* for prom io functions */
85 struct openpromio opp
;
88 /* used to manage lists of devices and aliases */
91 struct name_list
*next
;
95 * internal global data
98 /* global since nftw does not let you pass args to be updated */
99 static struct name_list
**dev_list
;
101 /* global since nftw does not let you pass args to be updated */
102 static struct boot_dev
**bootdev_list
;
104 /* mutex to protect bootdev_list and dev_list */
105 static mutex_t dev_lists_lk
= DEFAULTMUTEX
;
108 * internal function prototypes
111 static int prom_open(int);
112 static void prom_close(int);
113 static int is_openprom(int);
115 static int prom_dev_to_alias(char *dev
, uint_t options
, char ***ret_buf
);
116 static int alias_to_prom_dev(char *alias
, char *ret_buf
);
117 static int prom_srch_aliases_by_def(char *, struct name_list
**,
118 struct name_list
**, int);
119 static int prom_find_aliases_node(int fd
);
120 static int prom_compare_devs(char *prom_dev1
, char *prom_dev2
);
121 static int _prom_strcmp(char *s1
, char *s2
);
122 static int prom_srch_node(int fd
, char *prop_name
, char *ret_buf
);
123 static uint_t
prom_next_node(int fd
, uint_t node_id
);
124 static uint_t
prom_child_node(int fd
, uint_t node_id
);
126 static int prom_obp_vers(void);
128 static void parse_name(char *, char **, char **, char **);
129 static int process_bootdev(const char *, const char *, struct boot_dev
***);
130 static int process_minor_name(char *dev_path
, const char *default_root
);
131 static void options_override(char *prom_path
, char *alias_name
);
132 static int devfs_phys_to_logical(struct boot_dev
**bootdev_array
,
133 const int array_size
, const char *default_root
);
134 static int check_logical_dev(const char *, const struct stat
*, int,
136 static struct boot_dev
*alloc_bootdev(char *);
137 static void free_name_list(struct name_list
*list
, int free_name
);
138 static int insert_alias_list(struct name_list
**list
,
140 static int get_boot_dev_var(struct openpromio
*opp
);
141 static int set_boot_dev_var(struct openpromio
*opp
, char *bootdev
);
142 static int devfs_prom_to_dev_name(char *prom_path
, char *dev_path
);
143 static int devfs_dev_to_prom_names(char *dev_path
, char *prom_path
, size_t len
);
146 * frees a list of paths from devfs_get_prom_name_list
149 prom_list_free(char **prom_list
)
156 while (prom_list
[i
]) {
164 devfs_get_prom_name_list(const char *dev_name
, char ***prom_list
)
166 char *prom_path
= NULL
;
167 int count
= 0; /* # of slots we will need in prom_list */
172 if (dev_name
== NULL
)
173 return (DEVFS_INVAL
);
174 if (*dev_name
!= '/')
175 return (DEVFS_INVAL
);
176 if (prom_list
== NULL
)
177 return (DEVFS_INVAL
);
180 * make sure we are on a machine which supports a prom
181 * and we have permission to use /dev/openprom
183 if ((ret
= prom_obp_vers()) < 0)
185 if ((prom_path
= (char *)malloc(MAXVALSIZE
)) == NULL
)
186 return (DEVFS_NOMEM
);
188 * get the prom path name
190 ret
= devfs_dev_to_prom_names((char *)dev_name
, prom_path
, MAXVALSIZE
);
195 /* deal with list of names */
196 for (i
= 0; i
< ret
; i
++)
197 if (prom_path
[i
] == '\0')
200 if ((list
= (char **)calloc(count
+ 1, sizeof (char *))) == NULL
) {
202 return (DEVFS_NOMEM
);
206 for (i
= 0; i
< count
; i
++) {
207 len
= strlen(ptr
) + 1;
208 if ((list
[i
] = (char *)malloc(len
)) == NULL
) {
211 return (DEVFS_NOMEM
);
213 (void) snprintf(list
[i
], len
, "%s", ptr
);
224 * retrieve the list of prom representations for a given device name
225 * the list will be sorted in the following order: exact aliases,
226 * inexact aliases, prom device path name. If multiple matches occur
227 * for exact or inexact aliases, then these are sorted in collating
228 * order. The list is returned in prom_list
230 * the list may be restricted by specifying the correct flags in options.
233 devfs_get_prom_names(const char *dev_name
, uint_t options
, char ***prom_list
)
235 char *prom_path
= NULL
;
236 int count
= 0; /* # of slots we will need in prom_list */
237 char **alias_list
= NULL
;
241 if (dev_name
== NULL
) {
242 return (DEVFS_INVAL
);
244 if (*dev_name
!= '/') {
245 return (DEVFS_INVAL
);
247 if (prom_list
== NULL
) {
248 return (DEVFS_INVAL
);
251 * make sure we are on a machine which supports a prom
252 * and we have permission to use /dev/openprom
254 if ((ret
= prom_obp_vers()) < 0) {
257 if ((prom_path
= (char *)malloc(MAXPATHLEN
)) == NULL
) {
258 return (DEVFS_NOMEM
);
261 * get the prom path name
263 ret
= devfs_dev_to_prom_name((char *)dev_name
, prom_path
);
268 /* get the list of aliases (exact and inexact) */
269 if ((ret
= prom_dev_to_alias(prom_path
, options
, &alias_list
)) < 0) {
273 /* now figure out how big the return array must be */
274 if (alias_list
!= NULL
) {
275 while (alias_list
[count
] != NULL
) {
279 if ((options
& BOOTDEV_NO_PROM_PATH
) == 0) {
280 count
++; /* # of slots we will need in prom_list */
282 count
++; /* for the null terminator */
284 /* allocate space for the list */
285 if ((list
= (char **)calloc(count
, sizeof (char *))) == NULL
) {
287 while ((alias_list
) && (alias_list
[count
] != NULL
)) {
288 free(alias_list
[count
]);
293 return (DEVFS_NOMEM
);
295 /* fill in the array and free the name list of aliases. */
297 while ((alias_list
) && (alias_list
[count
] != NULL
)) {
298 list
[count
] = alias_list
[count
];
301 if ((options
& BOOTDEV_NO_PROM_PATH
) == 0) {
302 list
[count
] = prom_path
;
304 if (alias_list
!= NULL
) {
312 * Get a list prom-path translations for a solaris device.
314 * Returns the number of and all OBP paths and alias variants that
315 * reference the Solaris device path passed in.
318 devfs_get_all_prom_names(const char *solaris_path
, uint_t flags
,
319 struct devfs_prom_path
**paths
)
321 int ret
, len
, i
, count
= 0;
322 char *ptr
, *prom_path
;
323 struct devfs_prom_path
*cur
= NULL
, *new;
325 if ((ret
= prom_obp_vers()) < 0)
327 if ((prom_path
= (char *)malloc(MAXVALSIZE
)) == NULL
)
328 return (DEVFS_NOMEM
);
330 if ((ret
= devfs_dev_to_prom_names((char *)solaris_path
,
331 prom_path
, MAXVALSIZE
)) < 0) {
336 for (i
= 0; i
< ret
; i
++)
337 if (prom_path
[i
] == '\0')
342 for (i
= 0; i
< count
; i
++) {
343 if ((new = (struct devfs_prom_path
*)calloc(
344 sizeof (struct devfs_prom_path
), 1)) == NULL
) {
346 devfs_free_all_prom_names(*paths
);
347 return (DEVFS_NOMEM
);
356 len
= strlen(ptr
) + 1;
357 if ((cur
->obp_path
= (char *)calloc(len
, 1)) == NULL
) {
359 devfs_free_all_prom_names(*paths
);
360 return (DEVFS_NOMEM
);
363 (void) snprintf(cur
->obp_path
, len
, "%s", ptr
);
365 if ((ret
= prom_dev_to_alias(cur
->obp_path
, flags
,
366 &(cur
->alias_list
))) < 0) {
368 devfs_free_all_prom_names(*paths
);
378 devfs_free_all_prom_names(struct devfs_prom_path
*paths
)
385 devfs_free_all_prom_names(paths
->next
);
387 if (paths
->obp_path
!= NULL
)
388 free(paths
->obp_path
);
390 if (paths
->alias_list
!= NULL
) {
391 for (i
= 0; paths
->alias_list
[i
] != NULL
; i
++)
392 if (paths
->alias_list
[i
] != NULL
)
393 free(paths
->alias_list
[i
]);
395 free(paths
->alias_list
);
402 * Accepts a device name as an input argument. Uses this to set the
403 * boot-device (or like) variable
405 * By default, this routine prepends to the list and converts the
406 * logical device name to its most compact prom representation.
407 * Available options include: converting the device name to a prom
408 * path name (but not an alias) or performing no conversion at all;
409 * overwriting the existing contents of boot-device rather than
413 devfs_bootdev_set_list(const char *dev_name
, const uint_t options
)
418 char **alias_list
= NULL
;
419 char **prom_list
= NULL
;
421 struct openpromio
*opp
= &(oppbuf
.opp
);
424 if (devfs_bootdev_modifiable() != 0) {
425 return (DEVFS_NOTSUP
);
427 if (dev_name
== NULL
) {
428 return (DEVFS_INVAL
);
430 if (strlen(dev_name
) >= MAXPATHLEN
)
431 return (DEVFS_INVAL
);
433 if ((*dev_name
!= '/') && !(options
& BOOTDEV_LITERAL
)) {
434 return (DEVFS_INVAL
);
436 if ((options
& BOOTDEV_LITERAL
) && (options
& BOOTDEV_PROMDEV
)) {
437 return (DEVFS_INVAL
);
440 * if we are prepending, make sure that this obp rev
441 * supports multiple boot device entries.
443 ret
= prom_obp_vers();
448 if ((prom_path
= (char *)malloc(MAXVALSIZE
)) == NULL
) {
449 return (DEVFS_NOMEM
);
451 if (options
& BOOTDEV_LITERAL
) {
452 (void) strcpy(prom_path
, dev_name
);
454 /* need to convert to prom representation */
455 ret
= devfs_get_prom_name_list(dev_name
, &prom_list
);
464 while (prom_list
&& prom_list
[i
]) {
465 if (!(options
& BOOTDEV_PROMDEV
)) {
466 ret
= prom_dev_to_alias(prom_list
[i
], 0,
470 prom_list_free(prom_list
);
473 if ((alias_list
!= NULL
) &&
474 (alias_list
[0] != NULL
)) {
475 (void) snprintf(ptr
, len
, "%s ",
477 for (ret
= 0; alias_list
[ret
] != NULL
;
479 free(alias_list
[ret
]);
481 (void) snprintf(ptr
, len
, "%s ",
484 if (alias_list
!= NULL
)
487 (void) snprintf(ptr
, len
, "%s ", prom_list
[i
]);
497 prom_list_free(prom_list
);
499 if (options
& BOOTDEV_OVERWRITE
) {
500 new_bootdev
= prom_path
;
502 /* retrieve the current value of boot-device */
503 ret
= get_boot_dev_var(opp
);
508 /* prepend new entry - deal with duplicates */
509 new_bootdev
= (char *)malloc(strlen(opp
->oprom_array
)
510 + strlen(prom_path
) + 2);
511 if (new_bootdev
== NULL
) {
513 return (DEVFS_NOMEM
);
515 (void) strcpy(new_bootdev
, prom_path
);
516 if (opp
->oprom_size
> 0) {
517 for (ptr
= strtok(opp
->oprom_array
, " "); ptr
!= NULL
;
518 ptr
= strtok(NULL
, " ")) {
519 /* we strip out duplicates */
520 if (strcmp(prom_path
, ptr
) == 0) {
523 (void) strcat(new_bootdev
, " ");
524 (void) strcat(new_bootdev
, ptr
);
529 /* now set the new value */
530 ret
= set_boot_dev_var(opp
, new_bootdev
);
532 if (options
& BOOTDEV_OVERWRITE
) {
543 * sets the string bootdev as the new value for boot-device
546 set_boot_dev_var(struct openpromio
*opp
, char *bootdev
)
553 char *bootdev_variables
[] = {
560 int *ip
= (int *)((void *)opp
->oprom_array
);
563 prom_fd
= prom_open(O_RDWR
);
568 /* get the diagnostic-mode? property */
569 (void) strcpy(opp
->oprom_array
, "diagnostic-mode?");
570 opp
->oprom_size
= MAXVALSIZE
;
571 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) >= 0) {
572 if ((opp
->oprom_size
> 0) &&
573 (strcmp(opp
->oprom_array
, "true") == 0)) {
578 /* get the diag-switch? property */
579 (void) strcpy(opp
->oprom_array
, "diag-switch?");
580 opp
->oprom_size
= MAXVALSIZE
;
581 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) >= 0) {
582 if ((opp
->oprom_size
> 0) &&
583 (strcmp(opp
->oprom_array
, "true") == 0)) {
589 * look for one of the following properties in order:
594 * Use the first one that we find.
597 opp
->oprom_size
= MAXPROPSIZE
;
598 while ((opp
->oprom_size
!= 0) && (!found
)) {
599 opp
->oprom_size
= MAXPROPSIZE
;
600 if (ioctl(prom_fd
, OPROMNXTOPT
, opp
) < 0) {
603 for (i
= 0; bootdev_variables
[i
] != NULL
; i
++) {
604 if (strcmp(opp
->oprom_array
, bootdev_variables
[i
])
612 (void) strcpy(opp
->oprom_array
, bootdev_variables
[i
]);
613 opp
->oprom_size
= MAXVALSIZE
;
614 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) < 0) {
616 return (DEVFS_NOTSUP
);
620 return (DEVFS_NOTSUP
);
623 /* save the old copy in case we fail */
624 if ((save_bootdev
= strdup(opp
->oprom_array
)) == NULL
) {
626 return (DEVFS_NOMEM
);
628 /* set up the new value of boot-device */
629 (void) strcpy(opp
->oprom_array
, bootdev_variables
[i
]);
630 valbuf
= opp
->oprom_array
+ strlen(opp
->oprom_array
) + 1;
631 (void) strcpy(valbuf
, bootdev
);
633 opp
->oprom_size
= strlen(valbuf
) + strlen(opp
->oprom_array
) + 2;
635 if (ioctl(prom_fd
, OPROMSETOPT
, opp
) < 0) {
642 * now read it back to make sure it took
644 (void) strcpy(opp
->oprom_array
, bootdev_variables
[i
]);
645 opp
->oprom_size
= MAXVALSIZE
;
646 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) >= 0) {
647 if (_prom_strcmp(opp
->oprom_array
, bootdev
) == 0) {
653 /* deal with setting it to "" */
654 if ((strlen(bootdev
) == 0) && (opp
->oprom_size
== 0)) {
662 * something did not take - write out the old value and
663 * hope that we can restore things...
665 * unfortunately, there is no way for us to differentiate
666 * whether we exceeded the maximum number of characters
667 * allowable. The limit varies from prom rev to prom
668 * rev, and on some proms, when the limit is
669 * exceeded, whatever was in the
670 * boot-device variable becomes unreadable.
672 * so if we fail, we will assume we ran out of room. If we
673 * not able to restore the original setting, then we will
674 * return DEVFS_ERR instead.
677 (void) strcpy(opp
->oprom_array
, bootdev_variables
[i
]);
678 valbuf
= opp
->oprom_array
+ strlen(opp
->oprom_array
) + 1;
679 (void) strcpy(valbuf
, save_bootdev
);
681 opp
->oprom_size
= strlen(valbuf
) + strlen(opp
->oprom_array
) + 2;
683 if (ioctl(prom_fd
, OPROMSETOPT
, opp
) < 0) {
691 * retrieve the current value for boot-device
694 get_boot_dev_var(struct openpromio
*opp
)
698 char *bootdev_variables
[] = {
705 int *ip
= (int *)((void *)opp
->oprom_array
);
708 prom_fd
= prom_open(O_RDONLY
);
713 /* get the diagnostic-mode? property */
714 (void) strcpy(opp
->oprom_array
, "diagnostic-mode?");
715 opp
->oprom_size
= MAXVALSIZE
;
716 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) >= 0) {
717 if ((opp
->oprom_size
> 0) &&
718 (strcmp(opp
->oprom_array
, "true") == 0)) {
723 /* get the diag-switch? property */
724 (void) strcpy(opp
->oprom_array
, "diag-switch?");
725 opp
->oprom_size
= MAXVALSIZE
;
726 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) >= 0) {
727 if ((opp
->oprom_size
> 0) &&
728 (strcmp(opp
->oprom_array
, "true") == 0)) {
734 * look for one of the following properties in order:
739 * Use the first one that we find.
742 opp
->oprom_size
= MAXPROPSIZE
;
743 while ((opp
->oprom_size
!= 0) && (!found
)) {
744 opp
->oprom_size
= MAXPROPSIZE
;
745 if (ioctl(prom_fd
, OPROMNXTOPT
, opp
) < 0) {
748 for (i
= 0; bootdev_variables
[i
] != NULL
; i
++) {
749 if (strcmp(opp
->oprom_array
, bootdev_variables
[i
])
757 (void) strcpy(opp
->oprom_array
, bootdev_variables
[i
]);
758 opp
->oprom_size
= MAXVALSIZE
;
759 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) < 0) {
763 /* boot-device exists but contains nothing */
764 if (opp
->oprom_size
== 0) {
765 *opp
->oprom_array
= '\0';
769 return (DEVFS_NOTSUP
);
782 /* make sure we have a map file */
783 fp
= fopen(GRUBDISK_MAP
, "r");
785 (void) snprintf(cmd
, sizeof (cmd
),
786 "%s > /dev/null", CREATE_DISKMAP
);
788 fp
= fopen(GRUBDISK_MAP
, "r");
794 find_x86_boot_device(struct openpromio
*opp
)
797 char *cp
, line
[MAXVALSIZE
+ 6];
800 file
= open_diskmap();
804 while (fgets(line
, MAXVALSIZE
+ 6, file
)) {
805 if (strncmp(line
, "0 ", 2) != 0)
808 line
[strlen(line
) - 1] = '\0';
810 * an x86 BIOS only boots a disk, not a partition
811 * or a slice, so hard-code :q (p0)
813 cp
= strchr(line
+ 2, ' ');
816 (void) snprintf(opp
->oprom_array
, MAXVALSIZE
,
818 opp
->oprom_size
= MAXVALSIZE
;
825 #endif /* ndef __sparc */
828 * retrieve the list of entries in the boot-device configuration
829 * variable. An array of boot_dev structs will be created, one entry
830 * for each device name in the boot-device variable. Each entry
831 * in the array will contain the logical device representation of the
832 * boot-device entry, if any.
834 * default_root. if set, is used to locate logical device entries in
835 * directories other than /dev
838 devfs_bootdev_get_list(const char *default_root
,
839 struct boot_dev
***bootdev_list
)
842 struct openpromio
*opp
= &(oppbuf
.opp
);
844 struct boot_dev
**tmp_list
;
846 if (default_root
== NULL
) {
848 } else if (*default_root
!= '/') {
849 return (DEVFS_INVAL
);
852 if (bootdev_list
== NULL
) {
853 return (DEVFS_INVAL
);
856 /* get the boot-device variable */
858 i
= get_boot_dev_var(opp
);
860 i
= find_x86_boot_device(opp
);
865 /* now try to translate each entry to a logical device. */
866 i
= process_bootdev(opp
->oprom_array
, default_root
, &tmp_list
);
868 *bootdev_list
= tmp_list
;
876 * loop thru the list of entries in a boot-device configuration
880 process_bootdev(const char *bootdevice
, const char *default_root
,
881 struct boot_dev
***list
)
885 char prom_path
[MAXPATHLEN
];
886 char ret_buf
[MAXPATHLEN
];
887 struct boot_dev
**bootdev_array
;
892 if ((entry
= (char *)malloc(strlen(bootdevice
) + 1)) == NULL
) {
893 return (DEVFS_NOMEM
);
895 /* count the number of entries */
896 (void) strcpy(entry
, bootdevice
);
897 for (ptr
= strtok(entry
, " "); ptr
!= NULL
;
898 ptr
= strtok(NULL
, " ")) {
901 (void) strcpy(entry
, bootdevice
);
903 bootdev_array
= (struct boot_dev
**)
904 calloc((size_t)num_entries
+ 1, sizeof (struct boot_dev
*));
906 if (bootdev_array
== NULL
) {
908 return (DEVFS_NOMEM
);
911 vers
= prom_obp_vers();
917 /* for each entry in boot-device, do... */
918 for (ptr
= strtok(entry
, " "), i
= 0; ptr
!= NULL
;
919 ptr
= strtok(NULL
, " "), i
++) {
921 if ((bootdev_array
[i
] = alloc_bootdev(ptr
)) == NULL
) {
922 devfs_bootdev_free_list(bootdev_array
);
924 return (DEVFS_NOMEM
);
928 * prom boot-device may be aliased, so we need to do
929 * the necessary prom alias to dev translation.
932 if (alias_to_prom_dev(ptr
, prom_path
) < 0) {
936 (void) strcpy(prom_path
, ptr
);
939 /* now we have a prom device path - convert to a devfs name */
940 if (devfs_prom_to_dev_name(prom_path
, ret_buf
) < 0) {
944 /* append any default minor names necessary */
945 if (process_minor_name(ret_buf
, default_root
) < 0) {
951 * store the physical device path for now - when
952 * we are all done with the entries, we will convert
953 * these to their logical device name equivalents
955 bootdev_array
[i
]->bootdev_trans
[0] = strdup(ret_buf
);
958 * Convert all of the boot-device entries that translated to a
959 * physical device path in /devices to a logical device path
960 * in /dev (note that there may be several logical device paths
961 * associated with a single physical device path - return them all
964 if (devfs_phys_to_logical(bootdev_array
, num_entries
,
966 devfs_bootdev_free_list(bootdev_array
);
967 bootdev_array
= NULL
;
971 *list
= bootdev_array
;
976 * We may get a device path from the prom that has no minor name
977 * information included in it. Since this device name will not
978 * correspond directly to a physical device in /devices, we do our
979 * best to append what the default minor name should be and try this.
981 * For sparc: we append slice 0 (:a).
982 * For x86: we append fdisk partition 0 (:q).
985 process_minor_name(char *dev_path
, const char *root
)
989 const char *default_minor_name
= "a";
991 const char *default_minor_name
= "q";
994 struct stat stat_buf
;
995 char path
[MAXPATHLEN
];
997 (void) snprintf(path
, sizeof (path
), "%s%s%s", root
, DEVICES
, dev_path
);
999 * if the device file already exists as given to us, there
1000 * is nothing to do but return.
1002 if (stat(path
, &stat_buf
) == 0) {
1006 * if there is no ':' after the last '/' character, or if there is
1007 * a ':' with no specifier, append the default segment specifier
1008 * ; if there is a ':' followed by a digit, this indicates
1009 * a partition number (which does not map into the /devices name
1010 * space), so strip the number and replace it with the letter
1011 * that represents the partition index
1013 if ((cp
= strrchr(dev_path
, '/')) != NULL
) {
1014 if ((cp
= strchr(cp
, ':')) == NULL
) {
1015 (void) strcat(dev_path
, ":");
1016 (void) strcat(dev_path
, default_minor_name
);
1017 } else if (*++cp
== '\0') {
1018 (void) strcat(dev_path
, default_minor_name
);
1019 } else if (isdigit(*cp
)) {
1021 /* make sure to squash the digit */
1024 case 0: (void) strcat(dev_path
, "q");
1026 case 1: (void) strcat(dev_path
, "r");
1028 case 2: (void) strcat(dev_path
, "s");
1030 case 3: (void) strcat(dev_path
, "t");
1032 case 4: (void) strcat(dev_path
, "u");
1034 default: (void) strcat(dev_path
, "a");
1040 * see if we can find something now.
1042 (void) snprintf(path
, sizeof (path
), "%s%s%s", root
, DEVICES
, dev_path
);
1044 if (stat(path
, &stat_buf
) == 0) {
1052 * for each entry in bootdev_array, convert the physical device
1053 * representation of the boot-device entry to one or more logical device
1054 * entries. We use the hammer method - walk through the logical device
1055 * name space looking for matches (/dev). We use nftw to do this.
1058 devfs_phys_to_logical(struct boot_dev
**bootdev_array
, const int array_size
,
1059 const char *default_root
)
1061 int walk_flags
= FTW_PHYS
| FTW_MOUNT
;
1063 struct name_list
*list
;
1065 char **dev_name_array
;
1066 size_t default_root_len
;
1067 char *dev_dir
= DEV
;
1070 if (array_size
< 0) {
1074 if (bootdev_array
== NULL
) {
1077 if (default_root
== NULL
) {
1080 default_root_len
= strlen(default_root
);
1081 if ((default_root_len
!= 0) && (*default_root
!= '/')) {
1085 /* short cut for an empty array */
1086 if (*bootdev_array
== NULL
) {
1090 /* tell nftw where to start (default: /dev) */
1091 len
= default_root_len
+ strlen(dev_dir
) + 1;
1092 if ((full_path
= (char *)malloc(len
)) == NULL
) {
1097 * if the default root path is terminated with a /, we have to
1098 * make sure we don't end up with one too many slashes in the
1099 * path we are building.
1101 if ((default_root_len
> (size_t)0) &&
1102 (default_root
[default_root_len
- 1] == '/')) {
1103 (void) snprintf(full_path
, len
, "%s%s", default_root
,
1106 (void) snprintf(full_path
, len
, "%s%s", default_root
, dev_dir
);
1110 * we need to muck with global data to make nftw work
1111 * so single thread access
1113 (void) mutex_lock(&dev_lists_lk
);
1116 * set the global vars bootdev_list and dev_list for use by nftw
1117 * dev_list is an array of lists - one for each boot-device
1118 * entry. The nftw function will create a list of logical device
1119 * entries for each boot-device and put all of the lists in
1122 dev_list
= (struct name_list
**)
1123 calloc(array_size
, sizeof (struct name_list
*));
1124 if (dev_list
== NULL
) {
1126 (void) mutex_unlock(&dev_lists_lk
);
1129 bootdev_list
= bootdev_array
;
1131 if (nftw(full_path
, check_logical_dev
, FT_DEPTH
, walk_flags
) == -1) {
1132 bootdev_list
= NULL
;
1134 for (i
= 0; i
< array_size
; i
++) {
1135 free_name_list(dev_list
[i
], 1);
1137 /* don't free dev_list here because it's been handed off */
1139 (void) mutex_unlock(&dev_lists_lk
);
1144 * now we have a filled in dev_list. So for each logical device
1145 * list in dev_list, count the number of entries in the list,
1146 * create an array of strings of logical devices, and save in the
1147 * corresponding boot_dev structure.
1149 for (i
= 0; i
< array_size
; i
++) {
1150 /* get the next list */
1154 /* count the number of entries in the list */
1155 while (list
!= NULL
) {
1159 if ((dev_name_array
=
1160 (char **)malloc((count
+ 1) * sizeof (char *)))
1167 /* fill in the array */
1168 while (list
!= NULL
) {
1169 dev_name_array
[count
] = list
->name
;
1175 * null terminate the array
1177 dev_name_array
[count
] = NULL
;
1178 if ((bootdev_array
[i
] != NULL
) && (bootdev_array
[i
]->
1179 bootdev_trans
[0] != NULL
)) {
1180 free(bootdev_array
[i
]->bootdev_trans
[0]);
1182 if (bootdev_array
[i
] != NULL
) {
1183 free(bootdev_array
[i
]->bootdev_trans
);
1184 bootdev_array
[i
]->bootdev_trans
= dev_name_array
;
1187 bootdev_list
= NULL
;
1189 for (i
= 0; i
< array_size
; i
++) {
1190 free_name_list(dev_list
[i
], 0);
1194 (void) mutex_unlock(&dev_lists_lk
);
1199 * for a logical dev entry, it walks the list of boot-devices and
1200 * sees if there are any matches. If so, it saves the logical device
1201 * name off in the appropriate list in dev_list
1205 check_logical_dev(const char *node
, const struct stat
*node_stat
, int flags
,
1206 struct FTW
*ftw_info
)
1208 char link_buf
[MAXPATHLEN
];
1211 struct name_list
*dev
;
1215 if (flags
!= FTW_SL
) {
1219 if ((link_buf_len
= readlink(node
, (void *)link_buf
, MAXPATHLEN
))
1223 link_buf
[link_buf_len
] = '\0';
1224 if ((name
= strstr(link_buf
, DEVICES
)) == NULL
) {
1227 name
= (char *)(name
+ strlen(DEVICES
));
1229 for (i
= 0; bootdev_list
[i
] != NULL
; i
++) {
1230 if (bootdev_list
[i
]->bootdev_trans
[0] == NULL
) {
1234 * compare the contents of the link with the physical
1235 * device representation of this boot device
1237 physdev
= bootdev_list
[i
]->bootdev_trans
[0];
1238 if ((strcmp(name
, physdev
) == 0) &&
1239 (strlen(name
) == strlen(physdev
))) {
1240 if ((dev
= (struct name_list
*)
1241 malloc(sizeof (struct name_list
))) == NULL
) {
1244 if ((dev
->name
= strdup(node
)) == NULL
) {
1248 if (dev_list
[i
] == NULL
) {
1250 dev_list
[i
]->next
= NULL
;
1252 dev
->next
= dev_list
[i
];
1261 * frees a list of boot_dev struct pointers
1264 devfs_bootdev_free_list(struct boot_dev
**array
)
1269 if (array
== NULL
) {
1273 while (array
[i
] != NULL
) {
1274 free(array
[i
]->bootdev_element
);
1276 while (array
[i
]->bootdev_trans
[j
] != NULL
) {
1277 free(array
[i
]->bootdev_trans
[j
++]);
1279 free(array
[i
]->bootdev_trans
);
1286 * allocates a boot_dev struct and fills in the bootdev_element portion
1288 static struct boot_dev
*
1289 alloc_bootdev(char *entry_name
)
1291 struct boot_dev
*entry
;
1293 entry
= (struct boot_dev
*)calloc(1, sizeof (struct boot_dev
));
1295 if (entry
== NULL
) {
1298 if ((entry
->bootdev_element
= strdup(entry_name
)) == NULL
) {
1303 * Allocate room for 1 name and a null terminator - the caller of
1304 * this function will need the first slot right away.
1306 if ((entry
->bootdev_trans
= (char **)calloc(2, sizeof (char *)))
1308 free(entry
->bootdev_element
);
1316 * will come back with a concatenated list of paths
1319 devfs_dev_to_prom_names(char *dev_path
, char *prom_path
, size_t len
)
1322 struct openpromio
*opp
= &(oppbuf
.opp
);
1324 int ret
= DEVFS_INVAL
;
1327 if (prom_path
== NULL
) {
1328 return (DEVFS_INVAL
);
1330 if (dev_path
== NULL
) {
1331 return (DEVFS_INVAL
);
1333 if (strlen(dev_path
) >= MAXPATHLEN
)
1334 return (DEVFS_INVAL
);
1336 if (*dev_path
!= '/')
1337 return (DEVFS_INVAL
);
1339 prom_fd
= prom_open(O_RDONLY
);
1344 /* query the prom */
1345 (void) snprintf(opp
->oprom_array
, MAXVALSIZE
, "%s", dev_path
);
1346 opp
->oprom_size
= MAXVALSIZE
;
1348 if (ioctl(prom_fd
, OPROMDEV2PROMNAME
, opp
) == 0) {
1349 prom_close(prom_fd
);
1351 /* return the prom path in prom_path */
1353 i
= len
- opp
->oprom_size
;
1355 bcopy(opp
->oprom_array
, prom_path
, len
);
1356 prom_path
[len
- 1] = NULL
;
1359 bcopy(opp
->oprom_array
, prom_path
, len
);
1360 return (opp
->oprom_size
);
1364 * either the prom does not support this ioctl or the argument
1367 if (errno
== ENXIO
) {
1370 prom_close(prom_fd
);
1375 * Convert a physical or logical device name to a name the prom would
1376 * understand. Fail if this platform does not support a prom or if
1377 * the device does not correspond to a valid prom device.
1378 * dev_path should be the name of a device in the logical or
1379 * physical device namespace.
1380 * prom_path is the prom version of the device name
1381 * prom_path must be large enough to contain the result and is
1382 * supplied by the user.
1384 * This routine only supports converting leaf device paths
1387 devfs_dev_to_prom_name(char *dev_path
, char *prom_path
)
1391 rval
= devfs_dev_to_prom_names(dev_path
, prom_path
, MAXPATHLEN
);
1400 * Use the openprom driver's OPROMPATH2DRV ioctl to convert a devfs
1401 * path to a driver name.
1402 * devfs_path - the pathname of interest. This must be the physcical device
1403 * path with the mount point prefix (ie. /devices) stripped off.
1404 * drv_buf - user supplied buffer - the driver name will be stored here.
1406 * If the prom lookup fails, we return the name of the last component in
1407 * the pathname. This routine is useful for looking up driver names
1408 * associated with generically named devices.
1410 * This routine returns driver names that have aliases resolved.
1413 devfs_path_to_drv(char *devfs_path
, char *drv_buf
)
1416 struct openpromio
*opp
= &(oppbuf
.opp
);
1417 char *slash
, *colon
, *dev_addr
;
1418 char driver_path
[MAXPATHLEN
];
1421 if (drv_buf
== NULL
) {
1424 if (devfs_path
== NULL
) {
1428 if (strlen(devfs_path
) >= MAXPATHLEN
)
1431 if (*devfs_path
!= '/')
1435 /* strip off any minor node info at the end of the path */
1436 (void) strcpy(driver_path
, devfs_path
);
1437 slash
= strrchr(driver_path
, '/');
1440 colon
= strrchr(slash
, ':');
1444 /* query the prom */
1445 if ((prom_fd
= prom_open(O_RDONLY
)) >= 0) {
1446 (void) strcpy(opp
->oprom_array
, driver_path
);
1447 opp
->oprom_size
= MAXVALSIZE
;
1449 if (ioctl(prom_fd
, OPROMPATH2DRV
, opp
) == 0) {
1450 prom_close(prom_fd
);
1451 /* return the driver name in drv_buf */
1452 (void) strcpy(drv_buf
, opp
->oprom_array
);
1455 prom_close(prom_fd
);
1456 } else if (prom_fd
!= DEVFS_NOTSUP
)
1459 * If we get here, then either:
1460 * 1. this platform does not support an openprom driver
1461 * 2. we were asked to look up a device the prom does
1462 * not know about (e.g. a pseudo device)
1463 * In this case, we use the last component of the devfs path
1464 * name and try to derive the driver name
1467 /* use the last component of devfs_path as the driver name */
1468 if ((dev_addr
= strrchr(slash
, '@')) != NULL
)
1472 /* use opp->oprom_array as a buffer */
1473 (void) strcpy(opp
->oprom_array
, slash
);
1474 if (devfs_resolve_aliases(opp
->oprom_array
) == NULL
)
1476 (void) strcpy(drv_buf
, opp
->oprom_array
);
1481 * These modctl calls do the equivalent of:
1482 * ddi_name_to_major()
1483 * ddi_major_to_name()
1484 * This results in two things:
1485 * - the driver name must be a valid one
1486 * - any driver aliases are resolved.
1487 * drv is overwritten with the resulting name.
1490 devfs_resolve_aliases(char *drv
)
1493 char driver_name
[MAXNAMELEN
+ 1];
1499 if (modctl(MODGETMAJBIND
, drv
, strlen(drv
) + 1, &maj
) < 0)
1501 else if (modctl(MODGETNAME
, driver_name
, sizeof (driver_name
), &maj
)
1505 (void) strcpy(drv
, driver_name
);
1511 * open the openprom device. and verify that we are on an
1512 * OBP/1275 OF machine. If the prom does not exist, then we
1516 prom_open(int oflag
)
1519 char *promdev
= "/dev/openprom";
1521 while (prom_fd
< 0) {
1522 if ((prom_fd
= open(promdev
, oflag
)) < 0) {
1523 if (errno
== EAGAIN
) {
1527 if ((errno
== ENXIO
) || (errno
== ENOENT
)) {
1528 return (DEVFS_NOTSUP
);
1530 if ((errno
== EPERM
) || (errno
== EACCES
)) {
1531 return (DEVFS_PERM
);
1537 if (is_openprom(prom_fd
))
1540 prom_close(prom_fd
);
1546 prom_close(int prom_fd
)
1548 (void) close(prom_fd
);
1552 * is this an OBP/1275 OF machine?
1555 is_openprom(int prom_fd
)
1558 struct openpromio
*opp
= &(oppbuf
.opp
);
1561 opp
->oprom_size
= MAXVALSIZE
;
1562 if (ioctl(prom_fd
, OPROMGETCONS
, opp
) < 0)
1565 i
= (unsigned int)((unsigned char)opp
->oprom_array
[0]);
1566 return ((i
& OPROMCONS_OPENPROM
) == OPROMCONS_OPENPROM
);
1570 * convert a prom device path name to an equivalent physical device
1571 * path in the kernel.
1574 devfs_prom_to_dev_name(char *prom_path
, char *dev_path
)
1577 struct openpromio
*opp
= &(oppbuf
.opp
);
1579 int ret
= DEVFS_INVAL
;
1581 if (dev_path
== NULL
) {
1582 return (DEVFS_INVAL
);
1584 if (prom_path
== NULL
) {
1585 return (DEVFS_INVAL
);
1587 if (strlen(prom_path
) >= MAXPATHLEN
)
1588 return (DEVFS_INVAL
);
1590 if (*prom_path
!= '/') {
1591 return (DEVFS_INVAL
);
1594 /* query the prom */
1595 prom_fd
= prom_open(O_RDONLY
);
1599 (void) strcpy(opp
->oprom_array
, prom_path
);
1600 opp
->oprom_size
= MAXVALSIZE
;
1602 if (ioctl(prom_fd
, OPROMPROM2DEVNAME
, opp
) == 0) {
1603 prom_close(prom_fd
);
1606 * return the prom path in prom_path
1608 (void) strcpy(dev_path
, opp
->oprom_array
);
1612 * either the argument was not a valid name or the openprom
1613 * driver does not support this ioctl.
1615 if (errno
== ENXIO
) {
1618 prom_close(prom_fd
);
1622 * convert a prom device path to a list of equivalent alias names
1623 * If there is no alias node, or there are no aliases that correspond
1624 * to dev, we return empty lists.
1627 prom_dev_to_alias(char *dev
, uint_t options
, char ***ret_buf
)
1629 struct name_list
*exact_list
;
1630 struct name_list
*inexact_list
;
1631 struct name_list
*list
;
1638 vers
= prom_obp_vers();
1644 return (DEVFS_INVAL
);
1648 return (DEVFS_INVAL
);
1650 if (strlen(dev
) >= MAXPATHLEN
)
1651 return (DEVFS_INVAL
);
1653 if ((ptr
= strchr(dev
, ':')) != NULL
) {
1654 if (strchr(ptr
, '/') != NULL
)
1655 return (DEVFS_INVAL
);
1657 if (ret_buf
== NULL
) {
1658 return (DEVFS_INVAL
);
1661 prom_fd
= prom_open(O_RDONLY
);
1666 (void) prom_srch_aliases_by_def(dev
, &exact_list
,
1667 &inexact_list
, prom_fd
);
1669 prom_close(prom_fd
);
1671 if ((options
& BOOTDEV_NO_EXACT_ALIAS
) != 0) {
1672 free_name_list(exact_list
, 1);
1676 if ((options
& BOOTDEV_NO_INEXACT_ALIAS
) != 0) {
1677 free_name_list(inexact_list
, 1);
1678 inexact_list
= NULL
;
1683 while (list
!= NULL
) {
1687 list
= inexact_list
;
1688 while (list
!= NULL
) {
1693 if ((*ret_buf
= (char **)malloc((count
+ 1) * sizeof (char *)))
1695 free_name_list(inexact_list
, 1);
1696 free_name_list(exact_list
, 1);
1697 return (DEVFS_NOMEM
);
1703 while (list
!= NULL
) {
1704 array
[count
] = list
->name
;
1708 list
= inexact_list
;
1709 while (list
!= NULL
) {
1710 array
[count
] = list
->name
;
1714 array
[count
] = NULL
;
1715 free_name_list(inexact_list
, 0);
1716 free_name_list(exact_list
, 0);
1722 * determine the version of prom we are running on.
1723 * Also include any prom revision specific information.
1729 struct openpromio
*opp
= &(oppbuf
.opp
);
1731 static int version
= 0;
1738 prom_fd
= prom_open(O_RDONLY
);
1743 opp
->oprom_size
= MAXVALSIZE
;
1745 if ((ioctl(prom_fd
, OPROMGETVERSION
, opp
)) < 0) {
1746 prom_close(prom_fd
);
1749 prom_close(prom_fd
);
1756 * search the aliases node by definition - compile a list of
1757 * alias names that are both exact and inexact matches.
1760 prom_srch_aliases_by_def(char *promdev_def
, struct name_list
**exact_list
,
1761 struct name_list
**inexact_list
, int prom_fd
)
1764 Oppbuf propdef_oppbuf
;
1765 struct openpromio
*opp
= &(oppbuf
.opp
);
1766 struct openpromio
*propdef_opp
= &(propdef_oppbuf
.opp
);
1767 int *ip
= (int *)((void *)opp
->oprom_array
);
1769 struct name_list
*inexact_match
= *inexact_list
= NULL
;
1770 struct name_list
*exact_match
= *exact_list
= NULL
;
1771 char alias_buf
[MAXNAMELEN
];
1774 (void) memset(oppbuf
.buf
, 0, BUFSIZE
);
1775 opp
->oprom_size
= MAXPROPSIZE
;
1778 if ((ret
= ioctl(prom_fd
, OPROMNXTPROP
, opp
)) < 0)
1780 if (opp
->oprom_size
== 0)
1783 while ((ret
>= 0) && (opp
->oprom_size
> 0)) {
1784 (void) strcpy(propdef_opp
->oprom_array
, opp
->oprom_array
);
1785 opp
->oprom_size
= MAXPROPSIZE
;
1786 propdef_opp
->oprom_size
= MAXVALSIZE
;
1787 if ((ioctl(prom_fd
, OPROMGETPROP
, propdef_opp
) < 0) ||
1788 (propdef_opp
->oprom_size
== 0)) {
1789 ret
= ioctl(prom_fd
, OPROMNXTPROP
, opp
);
1792 ret
= prom_compare_devs(promdev_def
, propdef_opp
->oprom_array
);
1793 if (ret
== EXACT_MATCH
) {
1795 if (insert_alias_list(exact_list
, opp
->oprom_array
)
1797 free_name_list(exact_match
, 1);
1798 free_name_list(inexact_match
, 1);
1802 if (ret
== INEXACT_MATCH
) {
1804 (void) strcpy(alias_buf
, opp
->oprom_array
);
1805 options_override(promdev_def
, alias_buf
);
1806 if (insert_alias_list(inexact_list
, alias_buf
)
1808 free_name_list(exact_match
, 1);
1809 free_name_list(inexact_match
, 1);
1813 ret
= ioctl(prom_fd
, OPROMNXTPROP
, opp
);
1823 * free a list of name_list structs and optionally
1824 * free the strings they contain.
1827 free_name_list(struct name_list
*list
, int free_name
)
1829 struct name_list
*next
= list
;
1831 while (next
!= NULL
) {
1841 * insert a new alias in a list of aliases - the list is sorted
1842 * in collating order (ignoring anything that comes after the
1846 insert_alias_list(struct name_list
**list
, char *alias_name
)
1848 struct name_list
*entry
= *list
;
1849 struct name_list
*new_entry
, *prev_entry
;
1851 char *colon1
, *colon2
;
1854 (struct name_list
*)malloc(sizeof (struct name_list
)))
1858 if ((new_entry
->name
= strdup(alias_name
)) == NULL
) {
1862 new_entry
->next
= NULL
;
1864 if (entry
== NULL
) {
1869 if ((colon1
= strchr(alias_name
, ':')) != NULL
) {
1873 while (entry
!= NULL
) {
1874 if ((colon2
= strchr(entry
->name
, ':')) != NULL
) {
1877 ret
= strcmp(alias_name
, entry
->name
);
1878 if (colon2
!= NULL
) {
1883 free(new_entry
->name
);
1885 if (colon1
!= NULL
) {
1891 new_entry
->next
= entry
;
1892 if (prev_entry
== NULL
) {
1893 /* in beginning of list */
1896 /* in middle of list */
1897 prev_entry
->next
= new_entry
;
1899 if (colon1
!= NULL
) {
1905 entry
= entry
->next
;
1907 /* at end of list */
1908 prev_entry
->next
= new_entry
;
1909 new_entry
->next
= NULL
;
1910 if (colon1
!= NULL
) {
1916 * append :x to alias_name to override any default minor name options
1919 options_override(char *prom_path
, char *alias_name
)
1923 if ((colon
= strrchr(alias_name
, ':')) != NULL
) {
1925 * XXX - should alias names in /aliases ever have a
1926 * : embedded in them?
1927 * If so we ignore it.
1932 if ((colon
= strrchr(prom_path
, ':')) != NULL
) {
1933 (void) strcat(alias_name
, colon
);
1938 * compare to prom device names.
1939 * if the device names are not fully qualified. we convert them -
1940 * we only do this as a last resort though since it requires
1941 * jumping into the kernel.
1944 prom_compare_devs(char *prom_dev1
, char *prom_dev2
)
1948 char *drvname1
, *addrname1
, *minorname1
;
1949 char *drvname2
, *addrname2
, *minorname2
;
1950 char component1
[MAXNAMELEN
], component2
[MAXNAMELEN
];
1951 char devname1
[MAXPATHLEN
], devname2
[MAXPATHLEN
];
1952 int unqualified_name
= 0;
1953 int error
= EXACT_MATCH
;
1955 char *wildcard
= ",0";
1960 if ((ptr1
== NULL
) || (*ptr1
!= '/')) {
1963 if ((ptr2
== NULL
) || (*ptr2
!= '/')) {
1968 * compare device names one component at a time.
1970 while ((ptr1
!= NULL
) && (ptr2
!= NULL
)) {
1971 *ptr1
= *ptr2
= '/';
1974 if ((ptr1
= strchr(dev1
, '/')) != NULL
)
1976 if ((ptr2
= strchr(dev2
, '/')) != NULL
)
1979 (void) strcpy(component1
, dev1
);
1980 (void) strcpy(component2
, dev2
);
1982 parse_name(component1
, &drvname1
, &addrname1
, &minorname1
);
1983 parse_name(component2
, &drvname2
, &addrname2
, &minorname2
);
1985 if ((drvname1
== NULL
) && (addrname1
== NULL
)) {
1990 if ((drvname2
== NULL
) && (addrname2
== NULL
)) {
1995 if (_prom_strcmp(drvname1
, drvname2
) != 0) {
2001 * a possible name is driver_name@address. The address
2002 * portion is optional (i.e. the name is not fully
2003 * qualified.). We have to deal with the case where
2004 * the component name is either driver_name or
2005 * driver_name@address
2007 if ((addrname1
== NULL
) ^ (addrname2
== NULL
)) {
2008 unqualified_name
= 1;
2009 } else if (addrname1
&&
2010 (_prom_strcmp(addrname1
, addrname2
) != 0)) {
2012 * check to see if appending a ",0" to the
2013 * shorter address causes a match to occur.
2016 len1
= strlen(addrname1
);
2017 len2
= strlen(addrname2
);
2018 if ((len1
< len2
) &&
2019 (strncmp(addrname1
, addrname2
, len1
) == 0) &&
2020 (strcmp(wildcard
, &addrname2
[len1
]) == 0)) {
2022 } else if ((len2
< len1
) &&
2023 (strncmp(addrname1
, addrname2
, len2
) == 0) &&
2024 (strcmp(wildcard
, &addrname1
[len2
]) == 0)) {
2033 * if either of the two device paths still has more components,
2034 * then we do not have a match.
2044 if (error
== NO_MATCH
) {
2049 * OK - we found a possible match but one or more of the
2050 * path components was not fully qualified (did not have any
2051 * address information. So we need to convert it to a form
2052 * that is fully qualified and then compare the resulting
2055 if (unqualified_name
!= 0) {
2056 if ((devfs_prom_to_dev_name(prom_dev1
, devname1
) < 0) ||
2057 (devfs_prom_to_dev_name(prom_dev2
, devname2
) < 0)) {
2060 if ((dev1
= strrchr(devname1
, ':')) != NULL
) {
2063 if ((dev2
= strrchr(devname2
, ':')) != NULL
) {
2066 if (strcmp(devname1
, devname2
) != 0) {
2071 * the resulting strings matched. If the minorname information
2072 * matches, then we have an exact match, otherwise an inexact match
2074 if (_prom_strcmp(minorname1
, minorname2
) == 0) {
2075 return (EXACT_MATCH
);
2077 return (INEXACT_MATCH
);
2082 * wrapper or strcmp - deals with null strings.
2085 _prom_strcmp(char *s1
, char *s2
)
2087 if ((s1
== NULL
) && (s2
== NULL
))
2089 if ((s1
== NULL
) && (s2
!= NULL
)) {
2092 if ((s1
!= NULL
) && (s2
== NULL
)) {
2095 return (strcmp(s1
, s2
));
2098 * break device@a,b:minor into components
2101 parse_name(char *name
, char **drvname
, char **addrname
, char **minorname
)
2105 cp
= *drvname
= name
;
2106 *addrname
= *minorname
= NULL
;
2110 while ((ch
= *cp
) != '\0') {
2118 *((*addrname
)-1) = '\0';
2121 *((*minorname
)-1) = '\0';
2126 * converts a prom alias to a prom device name.
2127 * if we find no matching device, then we fail since if were
2128 * given a valid alias, then by definition, there must be a
2129 * device pathname associated with it in the /aliases node.
2132 alias_to_prom_dev(char *alias
, char *ret_buf
)
2135 char alias_buf
[MAXNAMELEN
];
2136 char alias_def
[MAXPATHLEN
];
2137 char options
[16] = "";
2142 if (strchr(alias
, '/') != NULL
)
2143 return (DEVFS_INVAL
);
2145 if (strlen(alias
) > (MAXNAMELEN
- 1))
2146 return (DEVFS_INVAL
);
2148 if (ret_buf
== NULL
) {
2149 return (DEVFS_INVAL
);
2152 prom_fd
= prom_open(O_RDONLY
);
2157 (void) strlcpy(alias_buf
, alias
, sizeof (alias_buf
));
2160 * save off any options (minor name info) that is
2161 * explicitly called out in the alias name
2163 if ((options_ptr
= strchr(alias_buf
, ':')) != NULL
) {
2164 *options_ptr
= '\0';
2165 (void) strlcpy(options
, ++options_ptr
, sizeof (options
));
2170 ret
= prom_find_aliases_node(prom_fd
);
2173 * we loop because one alias may define another... we have
2174 * to work our way down to an actual device definition.
2176 for (i
= 0; i
<= 10; i
++) {
2177 ret
= prom_srch_node(prom_fd
, alias_buf
, alias_def
);
2181 (void) strlcpy(alias_buf
, alias_def
,
2182 sizeof (alias_buf
));
2183 if (*alias_def
== '/') {
2188 * save off any explicit options (minor name info)
2189 * if none has been encountered yet
2191 if (options_ptr
== NULL
) {
2192 options_ptr
= strchr(alias_buf
, ':');
2193 if (options_ptr
!= NULL
) {
2194 *options_ptr
= '\0';
2195 (void) strlcpy(options
, ++options_ptr
,
2201 prom_close(prom_fd
);
2208 (void) strlcpy(ret_buf
, alias_def
, MAXPATHLEN
);
2210 /* override minor name information */
2211 if (options_ptr
!= NULL
) {
2212 if ((options_ptr
= strrchr(ret_buf
, ':')) == NULL
) {
2213 (void) strcat(ret_buf
, ":");
2215 *(++options_ptr
) = '\0';
2217 (void) strcat(ret_buf
, options
);
2223 * search a prom node for a property name
2226 prom_srch_node(int fd
, char *prop_name
, char *ret_buf
)
2229 struct openpromio
*opp
= &(oppbuf
.opp
);
2230 int *ip
= (int *)((void *)opp
->oprom_array
);
2232 (void) memset(oppbuf
.buf
, 0, BUFSIZE
);
2233 opp
->oprom_size
= MAXPROPSIZE
;
2236 if (ioctl(fd
, OPROMNXTPROP
, opp
) < 0)
2238 if (opp
->oprom_size
== 0)
2241 while (strcmp(prop_name
, opp
->oprom_array
) != 0) {
2242 opp
->oprom_size
= MAXPROPSIZE
;
2243 if (ioctl(fd
, OPROMNXTPROP
, opp
) < 0)
2245 if (opp
->oprom_size
== 0)
2248 opp
->oprom_size
= MAXVALSIZE
;
2249 if (ioctl(fd
, OPROMGETPROP
, opp
) < 0)
2252 if (opp
->oprom_size
== 0)
2254 (void) strlcpy(ret_buf
, opp
->oprom_array
, MAXPATHLEN
);
2259 * return the aliases node.
2262 prom_find_aliases_node(int fd
)
2265 char buf
[MAXPATHLEN
];
2267 if ((child_id
= prom_next_node(fd
, 0)) == 0)
2269 if ((child_id
= prom_child_node(fd
, child_id
)) == 0)
2272 while (child_id
!= 0) {
2273 if (prom_srch_node(fd
, "name", buf
) == 0) {
2274 if (strcmp(buf
, "aliases") == 0) {
2278 child_id
= prom_next_node(fd
, child_id
);
2287 prom_next_node(int fd
, uint_t node_id
)
2290 struct openpromio
*opp
= &(oppbuf
.opp
);
2291 uint_t
*ip
= (uint_t
*)((void *)opp
->oprom_array
);
2293 (void) memset(oppbuf
.buf
, 0, BUFSIZE
);
2294 opp
->oprom_size
= MAXVALSIZE
;
2297 if (ioctl(fd
, OPROMNEXT
, opp
) < 0)
2300 return (*(uint_t
*)((void *)opp
->oprom_array
));
2307 prom_child_node(int fd
, uint_t node_id
)
2310 struct openpromio
*opp
= &(oppbuf
.opp
);
2311 uint_t
*ip
= (uint_t
*)((void *)opp
->oprom_array
);
2313 (void) memset(oppbuf
.buf
, 0, BUFSIZE
);
2314 opp
->oprom_size
= MAXVALSIZE
;
2317 if (ioctl(fd
, OPROMCHILD
, opp
) < 0)
2320 return (*(uint_t
*)((void *)opp
->oprom_array
));
2324 * only on sparc for now
2327 devfs_bootdev_modifiable(void)
2332 return (DEVFS_NOTSUP
);