17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5ecb24f52Svb70745 * Common Development and Distribution License (the "License"). 6ecb24f52Svb70745 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22ecb24f52Svb70745 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * cpr functions for supported sparc platforms 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate #include <sys/types.h> 327c478bd9Sstevel@tonic-gate #include <sys/systm.h> 337c478bd9Sstevel@tonic-gate #include <sys/cpr.h> 347c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 357c478bd9Sstevel@tonic-gate #include <sys/errno.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 387c478bd9Sstevel@tonic-gate * new_def_info is used as tmp space to store new values and write them 397c478bd9Sstevel@tonic-gate * to nvram. orig_def_info gets filled with the original nvram values, 407c478bd9Sstevel@tonic-gate * gets written to disk, and later used by cprboot to restore the 417c478bd9Sstevel@tonic-gate * original nvram values. 427c478bd9Sstevel@tonic-gate */ 437c478bd9Sstevel@tonic-gate static cdef_t *new_def_info; 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate static cdef_t orig_def_info = { 467c478bd9Sstevel@tonic-gate 0, 0, 477c478bd9Sstevel@tonic-gate 0, "boot-file", "", /* props[0] */ 487c478bd9Sstevel@tonic-gate 0, "boot-device", "", /* props[1] */ 497c478bd9Sstevel@tonic-gate 0, "auto-boot?", "", /* props[2] */ 507c478bd9Sstevel@tonic-gate 0, "diag-file", "", /* props[3] */ 517c478bd9Sstevel@tonic-gate 0, "diag-device", "", /* props[4] */ 527c478bd9Sstevel@tonic-gate }; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * since the above array is the only place where cprop_t content 567c478bd9Sstevel@tonic-gate * is specified, these defines are provided for quick/direct access. 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate #define CPR_BF_IDX 0 /* index for boot-file */ 597c478bd9Sstevel@tonic-gate #define CPR_BD_IDX 1 /* index for boot-device */ 607c478bd9Sstevel@tonic-gate #define CPR_AB_IDX 2 /* index for auto-boot? */ 617c478bd9Sstevel@tonic-gate #define CPR_DF_IDX 3 /* index for diag-file */ 627c478bd9Sstevel@tonic-gate #define CPR_DD_IDX 4 /* index for diag-device */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #define CPR_PROP_PTR(dfp, idx) &(dfp)->props[idx] 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate static char *cpr_next_component(char **); 687c478bd9Sstevel@tonic-gate static char *cpr_get_prefix(char *); 69fa9e4066Sahrens static char *cpr_build_nodename(pnode_t); 707c478bd9Sstevel@tonic-gate static void cpr_abbreviate_devpath(char *, char *); 717c478bd9Sstevel@tonic-gate static int cpr_show_props = 0; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate static int 75fa9e4066Sahrens cpr_get_options_node(pnode_t *nodep) 767c478bd9Sstevel@tonic-gate { 777c478bd9Sstevel@tonic-gate *nodep = prom_optionsnode(); 787c478bd9Sstevel@tonic-gate if (*nodep == OBP_NONODE || *nodep == OBP_BADNODE) { 797c478bd9Sstevel@tonic-gate cpr_err(CE_WARN, "cannot get \"options\" node"); 807c478bd9Sstevel@tonic-gate return (ENOENT); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate return (0); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * returns non-zero on error, otherwise returns 0 and 897c478bd9Sstevel@tonic-gate * sets the result code based on (prop value == "true") 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate static int 927c478bd9Sstevel@tonic-gate cpr_get_bool_prop(char *name, int *result) 937c478bd9Sstevel@tonic-gate { 947c478bd9Sstevel@tonic-gate char value[PROP_BOOL_LEN]; 95fa9e4066Sahrens pnode_t node; 967c478bd9Sstevel@tonic-gate int len, err; 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if (err = cpr_get_options_node(&node)) 997c478bd9Sstevel@tonic-gate return (err); 1007c478bd9Sstevel@tonic-gate len = prom_getproplen(node, name); 1017c478bd9Sstevel@tonic-gate if (len < 0 || len >= sizeof (value)) 1027c478bd9Sstevel@tonic-gate return (ENXIO); 1037c478bd9Sstevel@tonic-gate bzero(value, sizeof (value)); 1047c478bd9Sstevel@tonic-gate if (prom_getprop(node, name, value) != len) 1057c478bd9Sstevel@tonic-gate return (ENOENT); 1067c478bd9Sstevel@tonic-gate *result = (strcmp(value, "true") == 0); 1077c478bd9Sstevel@tonic-gate return (0); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * write new or original values to nvram 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate int 1157c478bd9Sstevel@tonic-gate cpr_update_nvram(cprop_t *props) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate cprop_t *tail; 118fa9e4066Sahrens pnode_t node; 1197c478bd9Sstevel@tonic-gate int len, rc; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (rc = cpr_get_options_node(&node)) 1227c478bd9Sstevel@tonic-gate return (rc); 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate if (cpr_show_props) 1257c478bd9Sstevel@tonic-gate prom_printf("\ncpr_show_props:\n"); 1267c478bd9Sstevel@tonic-gate for (tail = props + CPR_MAXPROP; props < tail; props++) { 1277c478bd9Sstevel@tonic-gate if (cpr_show_props) { 1287c478bd9Sstevel@tonic-gate prom_printf("mod=%c, name \"%s\",\tvalue \"%s\"\n", 1297c478bd9Sstevel@tonic-gate props->mod, props->name, props->value); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate if (props->mod == PROP_NOMOD) 1327c478bd9Sstevel@tonic-gate continue; 1337c478bd9Sstevel@tonic-gate /* 1347c478bd9Sstevel@tonic-gate * Note: When doing a prom_setprop you must include the 1357c478bd9Sstevel@tonic-gate * trailing NULL in the length argument, but when calling 1367c478bd9Sstevel@tonic-gate * prom_getproplen() the NULL is excluded from the count! 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate len = strlen(props->value); 1397c478bd9Sstevel@tonic-gate rc = prom_setprop(node, props->name, props->value, len + 1); 1407c478bd9Sstevel@tonic-gate if (rc < 0 || prom_getproplen(node, props->name) != len) { 1417c478bd9Sstevel@tonic-gate cpr_err(CE_WARN, "cannot set nvram \"%s\" to \"%s\"", 1427c478bd9Sstevel@tonic-gate props->name, props->value); 1437c478bd9Sstevel@tonic-gate return (ENXIO); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate return (0); 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * update nvram with the new or original nvram values; 1537c478bd9Sstevel@tonic-gate * this routine provides local access to both sets 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate int 1567c478bd9Sstevel@tonic-gate cpr_set_properties(int new) 1577c478bd9Sstevel@tonic-gate { 1587c478bd9Sstevel@tonic-gate cprop_t *props; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate props = new ? new_def_info->props : orig_def_info.props; 1617c478bd9Sstevel@tonic-gate return (cpr_update_nvram(props)); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * update the .mod field in both new_def_info and orig_def_info; 1687c478bd9Sstevel@tonic-gate * this tells cpr and cprboot which properties to set/reset. 1697c478bd9Sstevel@tonic-gate * then copy the arg str into a new property value at index 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate static void 1727c478bd9Sstevel@tonic-gate cpr_prop_update(int index, char *str) 1737c478bd9Sstevel@tonic-gate { 1747c478bd9Sstevel@tonic-gate cprop_t *prop; 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate prop = CPR_PROP_PTR(&orig_def_info, index); 1777c478bd9Sstevel@tonic-gate prop->mod = PROP_MOD; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate prop = CPR_PROP_PTR(new_def_info, index); 1807c478bd9Sstevel@tonic-gate prop->mod = PROP_MOD; 1817c478bd9Sstevel@tonic-gate (void) strcpy(prop->value, str); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * setup new property values within new_def_info; 1877c478bd9Sstevel@tonic-gate * these are used later to udpate nvram 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate static int 1907c478bd9Sstevel@tonic-gate cpr_prop_setup(void) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate int len, err, ds_ival, dev_idx, file_idx; 1937c478bd9Sstevel@tonic-gate char bootdev[OBP_MAXPATHLEN], bootfile[OBP_MAXPATHLEN]; 1947c478bd9Sstevel@tonic-gate char *cp, *sp; 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * create a new boot-device value. for some older prom revs, 1987c478bd9Sstevel@tonic-gate * a fully qualified device path can be truncated when stored 1997c478bd9Sstevel@tonic-gate * to nvram. this call generates the shortest equivalent. 2007c478bd9Sstevel@tonic-gate * using devaliases could be simpler in most cases. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate cpr_abbreviate_devpath(prom_bootpath(), bootdev); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * create a new boot-file value; flags get appended when 206ecb24f52Svb70745 * not reusable and when the statefile is a block device 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate (void) strcpy(bootfile, CPRBOOT); 209ecb24f52Svb70745 if (!cpr_reusable_mode && cpr_statefile_is_spec()) 2107c478bd9Sstevel@tonic-gate sp = " -S "; 2117c478bd9Sstevel@tonic-gate else 2127c478bd9Sstevel@tonic-gate sp = NULL; 2137c478bd9Sstevel@tonic-gate if (sp) { 2147c478bd9Sstevel@tonic-gate (void) strcat(bootfile, sp); 2157c478bd9Sstevel@tonic-gate len = strlen(bootfile); 2167c478bd9Sstevel@tonic-gate sp = cpr_get_statefile_prom_path(); 2177c478bd9Sstevel@tonic-gate cpr_abbreviate_devpath(sp, &bootfile[len]); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * record property info for booting with cprboot based on 2227c478bd9Sstevel@tonic-gate * the value of diag-switch?. when "false", set boot-device 2237c478bd9Sstevel@tonic-gate * and boot-file; when "true", set diag-device and diag-file 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate if (err = cpr_get_bool_prop("diag-switch?", &ds_ival)) 2267c478bd9Sstevel@tonic-gate return (err); 2277c478bd9Sstevel@tonic-gate else if (ds_ival == 0) { 2287c478bd9Sstevel@tonic-gate dev_idx = CPR_BD_IDX; 2297c478bd9Sstevel@tonic-gate file_idx = CPR_BF_IDX; 2307c478bd9Sstevel@tonic-gate } else { 2317c478bd9Sstevel@tonic-gate dev_idx = CPR_DD_IDX; 2327c478bd9Sstevel@tonic-gate file_idx = CPR_DF_IDX; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate cpr_prop_update(dev_idx, bootdev); 235ecb24f52Svb70745 236ecb24f52Svb70745 if (!cpr_reusable_mode) 2377c478bd9Sstevel@tonic-gate cpr_prop_update(file_idx, bootfile); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * check/set auto-boot? 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate sp = orig_def_info.props[CPR_AB_IDX].value; 2437c478bd9Sstevel@tonic-gate cp = "true"; 2447c478bd9Sstevel@tonic-gate if (strcmp(sp, cp)) 2457c478bd9Sstevel@tonic-gate cpr_prop_update(CPR_AB_IDX, cp); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate return (0); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate /* 2527c478bd9Sstevel@tonic-gate * setup the original and new sets of property names/values 2537c478bd9Sstevel@tonic-gate */ 2547c478bd9Sstevel@tonic-gate int 2557c478bd9Sstevel@tonic-gate cpr_default_setup(int alloc) 2567c478bd9Sstevel@tonic-gate { 2577c478bd9Sstevel@tonic-gate cprop_t *orig, *new, *tail; 2587c478bd9Sstevel@tonic-gate int len, err = 0; 259fa9e4066Sahrens pnode_t node; 2607c478bd9Sstevel@tonic-gate char *fmt; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate if (alloc == 0) { 2637c478bd9Sstevel@tonic-gate ASSERT(new_def_info); 2647c478bd9Sstevel@tonic-gate kmem_free(new_def_info, sizeof (*new_def_info)); 2657c478bd9Sstevel@tonic-gate new_def_info = NULL; 2667c478bd9Sstevel@tonic-gate return (0); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate if (err = cpr_get_options_node(&node)) 2707c478bd9Sstevel@tonic-gate return (err); 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * allocate space for new properties, get the original nvram 2747c478bd9Sstevel@tonic-gate * property values, mark both property sets with PROP_NOMOD, 2757c478bd9Sstevel@tonic-gate * and copy the original prop names to the new set. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate ASSERT(new_def_info == NULL); 2787c478bd9Sstevel@tonic-gate new_def_info = kmem_zalloc(sizeof (*new_def_info), KM_SLEEP); 2797c478bd9Sstevel@tonic-gate new = new_def_info->props; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate for (orig = orig_def_info.props, tail = orig + CPR_MAXPROP; 2827c478bd9Sstevel@tonic-gate orig < tail; orig++, new++) { 2837c478bd9Sstevel@tonic-gate len = prom_getproplen(node, orig->name); 2847c478bd9Sstevel@tonic-gate if (len < 0 || len >= (int)sizeof (orig->value)) { 2857c478bd9Sstevel@tonic-gate fmt = "invalid property or length for \"%s\""; 2867c478bd9Sstevel@tonic-gate err = ENXIO; 2877c478bd9Sstevel@tonic-gate break; 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate bzero(orig->value, sizeof (orig->value)); 2907c478bd9Sstevel@tonic-gate if (prom_getprop(node, orig->name, orig->value) < 0) { 2917c478bd9Sstevel@tonic-gate fmt = "cannot get \"%s\" value"; 2927c478bd9Sstevel@tonic-gate err = ENXIO; 2937c478bd9Sstevel@tonic-gate break; 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate new->mod = orig->mod = PROP_NOMOD; 2977c478bd9Sstevel@tonic-gate (void) strcpy(new->name, orig->name); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate if (err) { 3017c478bd9Sstevel@tonic-gate kmem_free(new_def_info, sizeof (*new_def_info)); 3027c478bd9Sstevel@tonic-gate new_def_info = NULL; 3037c478bd9Sstevel@tonic-gate cpr_err(CE_WARN, fmt, orig->name); 3047c478bd9Sstevel@tonic-gate } else 3057c478bd9Sstevel@tonic-gate err = cpr_prop_setup(); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate return (err); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate int 3127c478bd9Sstevel@tonic-gate cpr_validate_definfo(int reusable) 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate orig_def_info.mini.magic = CPR->c_cprboot_magic = CPR_DEFAULT_MAGIC; 3157c478bd9Sstevel@tonic-gate orig_def_info.mini.reusable = reusable; 3167c478bd9Sstevel@tonic-gate return (cpr_write_deffile(&orig_def_info)); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate void 3217c478bd9Sstevel@tonic-gate cpr_send_notice(void) 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate static char cstr[] = "\014" "\033[1P" "\033[18;21H"; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate prom_printf(cstr); 3267c478bd9Sstevel@tonic-gate prom_printf("Saving System State. Please Wait... "); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate void 3307c478bd9Sstevel@tonic-gate cpr_spinning_bar(void) 3317c478bd9Sstevel@tonic-gate { 3327c478bd9Sstevel@tonic-gate static char *spin_strings[] = { "|\b", "/\b", "-\b", "\\\b" }; 3337c478bd9Sstevel@tonic-gate static int idx; 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate prom_printf(spin_strings[idx]); 3367c478bd9Sstevel@tonic-gate if (++idx == 4) 3377c478bd9Sstevel@tonic-gate idx = 0; 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 340*2df1fe9cSrandyf void 341*2df1fe9cSrandyf cpr_resume_notice(void) 342*2df1fe9cSrandyf { 343*2df1fe9cSrandyf static char cstr[] = "\014" "\033[1P" "\033[18;21H"; 344*2df1fe9cSrandyf 345*2df1fe9cSrandyf prom_printf(cstr); 346*2df1fe9cSrandyf prom_printf("Restoring System State. Please Wait... "); 347*2df1fe9cSrandyf } 348*2df1fe9cSrandyf 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * Convert a full device path to its shortest unambiguous equivalent. 3517c478bd9Sstevel@tonic-gate * For example, a path which starts out /iommu@x,y/sbus@i,j/espdma . . . 3527c478bd9Sstevel@tonic-gate * might be converted to /iommu/sbus/espdma . . . If we encounter 3537c478bd9Sstevel@tonic-gate * problems at any point, just output the unabbreviated path. 3547c478bd9Sstevel@tonic-gate */ 3557c478bd9Sstevel@tonic-gate static void 3567c478bd9Sstevel@tonic-gate cpr_abbreviate_devpath(char *in_path, char *out_path) 3577c478bd9Sstevel@tonic-gate { 358fa9e4066Sahrens static pnode_t cur_node; 3597c478bd9Sstevel@tonic-gate char *position = in_path + 1; /* Skip the leading slash. */ 3607c478bd9Sstevel@tonic-gate char *cmpt; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate cur_node = prom_nextnode(0); 3637c478bd9Sstevel@tonic-gate *out_path = '\0'; 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate while ((cmpt = cpr_next_component(&position)) != NULL) { 366fa9e4066Sahrens pnode_t long_match = NULL; 367fa9e4066Sahrens pnode_t short_match = NULL; 3687c478bd9Sstevel@tonic-gate int short_hits = 0; 3697c478bd9Sstevel@tonic-gate char *name; 3707c478bd9Sstevel@tonic-gate char *prefix = cpr_get_prefix(cmpt); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* Go to next tree level by getting first child. */ 3737c478bd9Sstevel@tonic-gate if ((cur_node = prom_childnode(cur_node)) == 0) { 3747c478bd9Sstevel@tonic-gate (void) strcpy(out_path, in_path); 3757c478bd9Sstevel@tonic-gate return; 3767c478bd9Sstevel@tonic-gate } 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Traverse the current level and remember the node (if any) 3807c478bd9Sstevel@tonic-gate * where we match on the fully qualified component name. 3817c478bd9Sstevel@tonic-gate * Also remember the node of the most recent prefix match 3827c478bd9Sstevel@tonic-gate * and the number of such matches. 3837c478bd9Sstevel@tonic-gate */ 3847c478bd9Sstevel@tonic-gate do { 3857c478bd9Sstevel@tonic-gate name = cpr_build_nodename(cur_node); 3867c478bd9Sstevel@tonic-gate if (strcmp(name, cmpt) == 0) 3877c478bd9Sstevel@tonic-gate long_match = cur_node; 3887c478bd9Sstevel@tonic-gate if (strncmp(prefix, name, strlen(prefix)) == 0) { 3897c478bd9Sstevel@tonic-gate short_match = cur_node; 3907c478bd9Sstevel@tonic-gate short_hits++; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate } while ((cur_node = prom_nextnode(cur_node)) != 0); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * We don't want to be too dependent on what we know 3967c478bd9Sstevel@tonic-gate * about how the names are stored. We just assume that 3977c478bd9Sstevel@tonic-gate * if there is only one match on the prefix, we can 3987c478bd9Sstevel@tonic-gate * use it, otherwise we need to use a fully qualified 3997c478bd9Sstevel@tonic-gate * name. In the "impossible" cases we just give up 4007c478bd9Sstevel@tonic-gate * and use the complete input devpath. 4017c478bd9Sstevel@tonic-gate */ 4027c478bd9Sstevel@tonic-gate (void) strcat(out_path, "/"); 4037c478bd9Sstevel@tonic-gate if (short_hits == 1) { 4047c478bd9Sstevel@tonic-gate (void) strcat(out_path, prefix); 4057c478bd9Sstevel@tonic-gate cur_node = short_match; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate else 4087c478bd9Sstevel@tonic-gate if (long_match) { 4097c478bd9Sstevel@tonic-gate (void) strcat(out_path, cmpt); 4107c478bd9Sstevel@tonic-gate cur_node = long_match; 4117c478bd9Sstevel@tonic-gate } else { 4127c478bd9Sstevel@tonic-gate (void) strcpy(out_path, in_path); 4137c478bd9Sstevel@tonic-gate return; 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate /* We need to copy the target and slice info manually. */ 4177c478bd9Sstevel@tonic-gate (void) strcat(out_path, strrchr(in_path, '@')); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Return a pointer to the next component of a device path or NULL if 4227c478bd9Sstevel@tonic-gate * the entire path has been consumed. Note that we update the caller's 4237c478bd9Sstevel@tonic-gate * pointer to the current position in the full pathname buffer. 4247c478bd9Sstevel@tonic-gate */ 4257c478bd9Sstevel@tonic-gate static char * 4267c478bd9Sstevel@tonic-gate cpr_next_component(char **path) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate static char obuf[64]; 4297c478bd9Sstevel@tonic-gate char *slash; 4307c478bd9Sstevel@tonic-gate int len = strlen(*path); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate if (len == 0) 4337c478bd9Sstevel@tonic-gate return (NULL); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if ((slash = strchr(*path, '/'))) { 4367c478bd9Sstevel@tonic-gate len = slash - *path; 4377c478bd9Sstevel@tonic-gate (void) strncpy(obuf, *path, len); 4387c478bd9Sstevel@tonic-gate obuf[len] = '\0'; 4397c478bd9Sstevel@tonic-gate *path += len + 1; /* Position beyond the slash. */ 4407c478bd9Sstevel@tonic-gate } else { 4417c478bd9Sstevel@tonic-gate (void) strcpy(obuf, *path); 4427c478bd9Sstevel@tonic-gate *path += len; /* Position at the terminal NULL. */ 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate return (obuf); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * Return a pointer to the prefix (i.e., the basic unqualified node name) 4507c478bd9Sstevel@tonic-gate * Basically, this is the part of the fully qualified name before the @. 4517c478bd9Sstevel@tonic-gate */ 4527c478bd9Sstevel@tonic-gate static char * 4537c478bd9Sstevel@tonic-gate cpr_get_prefix(char *cmpt) 4547c478bd9Sstevel@tonic-gate { 4557c478bd9Sstevel@tonic-gate static char prefix[OBP_MAXDRVNAME]; 4567c478bd9Sstevel@tonic-gate char *at_sign = strchr(cmpt, '@'); 4577c478bd9Sstevel@tonic-gate int len = at_sign ? at_sign - cmpt : strlen(cmpt); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate (void) strncpy(prefix, cmpt, len); 4607c478bd9Sstevel@tonic-gate prefix[len] = '\0'; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate return (prefix); 4637c478bd9Sstevel@tonic-gate } 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate /* 4667c478bd9Sstevel@tonic-gate * Build the unambiguous name for the current node, like iommu@f,e10000000. 4677c478bd9Sstevel@tonic-gate * The prefix is just the "name" property, and the qualifier is constructed 4687c478bd9Sstevel@tonic-gate * from the first two (binary) words of the "reg" property. 4697c478bd9Sstevel@tonic-gate */ 4707c478bd9Sstevel@tonic-gate static char * 471fa9e4066Sahrens cpr_build_nodename(pnode_t node) 4727c478bd9Sstevel@tonic-gate { 4737c478bd9Sstevel@tonic-gate static char name[OBP_MAXPATHLEN]; 4747c478bd9Sstevel@tonic-gate int reg[512]; 4757c478bd9Sstevel@tonic-gate char buf[32]; /* must contain expansion of @%x,%x */ 4767c478bd9Sstevel@tonic-gate int prop_len = prom_getproplen(node, OBP_NAME); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if (prop_len < 0 || prop_len >= sizeof (name) || 4797c478bd9Sstevel@tonic-gate prom_getprop(node, OBP_NAME, name) < 0) 4807c478bd9Sstevel@tonic-gate return (""); 4817c478bd9Sstevel@tonic-gate name[prop_len] = '\0'; 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate if ((prop_len = prom_getproplen(node, OBP_REG)) < 4847c478bd9Sstevel@tonic-gate 2 * sizeof (int) || prop_len >= sizeof (reg)) 4857c478bd9Sstevel@tonic-gate return (name); 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate if (prom_getprop(node, OBP_REG, (caddr_t)reg) < 0) 4887c478bd9Sstevel@tonic-gate return (name); 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate (void) sprintf(buf, "@%x,%x", reg[0], reg[1]); 4917c478bd9Sstevel@tonic-gate (void) strcat(name, buf); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate return (name); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * Makes a printable list of prom_prop names for error messages 4987c478bd9Sstevel@tonic-gate * Caller must free space. 4997c478bd9Sstevel@tonic-gate */ 5007c478bd9Sstevel@tonic-gate char * 5017c478bd9Sstevel@tonic-gate cpr_enumerate_promprops(char **bufp, size_t *len) 5027c478bd9Sstevel@tonic-gate { 5037c478bd9Sstevel@tonic-gate cprop_t *prop, *tail; 5047c478bd9Sstevel@tonic-gate size_t size = 2; /* for "." */ 5057c478bd9Sstevel@tonic-gate char *buf; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate tail = &orig_def_info.props[CPR_MAXPROP]; 5087c478bd9Sstevel@tonic-gate for (prop = orig_def_info.props; prop < tail; prop++) 5097c478bd9Sstevel@tonic-gate size += strlen(prop->name) + 2; /* + ", " */ 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate buf = kmem_alloc(size, KM_SLEEP); 5127c478bd9Sstevel@tonic-gate *buf = '\0'; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate for (prop = orig_def_info.props; prop < tail; prop++) { 5157c478bd9Sstevel@tonic-gate if (strlen(buf)) 5167c478bd9Sstevel@tonic-gate (void) strcat(buf, ", "); 5177c478bd9Sstevel@tonic-gate (void) strcat(buf, prop->name); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate (void) strcat(buf, "."); 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate *bufp = buf; 5227c478bd9Sstevel@tonic-gate *len = size; 5237c478bd9Sstevel@tonic-gate return (buf); 5247c478bd9Sstevel@tonic-gate } 525