int i_cpr_is_supported(int sleeptype) { char es_prop[] = "energystar-v2"; pnode_t node; int last; extern int cpr_supported_override; extern int cpr_platform_enable; if (sleeptype != CPR_TODISK) return (0); /* * The next statement tests if a specific platform has turned off * cpr support. */ if (cpr_supported_override) return (0); /* * Do not inspect energystar-v* property if a platform has * specifically turned on cpr support */ if (cpr_platform_enable) return (1); node = prom_rootnode(); if (prom_getproplen(node, es_prop) != -1) return (1); last = strlen(es_prop) - 1; es_prop[last] = '3'; return (prom_getproplen(node, es_prop) != -1); }
/* * Note that this routine does not take into account the endianness * of the host or the device (or PROM) when retrieving properties. */ static int getlongprop_buf(int id, char *name, char *buf, int maxlen) { int size; size = prom_getproplen((pnode_t)id, name); if (size <= 0 || (size > maxlen - 1)) return (-1); if (-1 == prom_getprop((pnode_t)id, name, buf)) return (-1); /* * Workaround for bugid 1085575 - OBP may return a "name" property * without null terminating the string with '\0'. When this occurs, * append a '\0' and return (size + 1). */ if (strcmp("name", name) == 0) { if (buf[size - 1] != '\0') { buf[size] = '\0'; size += 1; } } return (size); }
int mc_get_dimm_size(pnode_t nodeid) { uint64_t psi_addr; uint_t dimmtype; int i, rlen; struct sf_memunit_regspec reg; rlen = prom_getproplen(nodeid, "reg"); if (rlen != sizeof (struct sf_memunit_regspec)) return (-1); if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) return (-1); psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; psi_addr |= (uint64_t)reg.regspec_addr_lo; psi_addr = STARFIRE_MC_DIMMTYPE_ADDR(psi_addr); if (psi_addr == (uint64_t)-1) return (-1); dimmtype = ldphysio(psi_addr); dimmtype &= STARFIRE_MC_DIMMSIZE_MASK; for (i = 0; dimmsize_table[i].mc_type != 0; i++) if (dimmsize_table[i].mc_type == dimmtype) break; return (dimmsize_table[i].mc_module_size); }
static void __init read_obp_memory(const char *property, struct linux_prom64_registers *regs, int *num_ents) { int node = prom_finddevice("/memory"); int prop_size = prom_getproplen(node, property); int ents, ret, i; ents = prop_size / sizeof(struct linux_prom64_registers); if (ents > MAX_BANKS) { prom_printf("The machine has more %s property entries than " "this kernel can support (%d).\n", property, MAX_BANKS); prom_halt(); } ret = prom_getproperty(node, property, (char *) regs, prop_size); if (ret == -1) { prom_printf("Couldn't get %s property from /memory.\n"); prom_halt(); } /* Sanitize what we got from the firmware, by page aligning * everything. */ for (i = 0; i < ents; i++) { unsigned long base, size; base = regs[i].phys_addr; size = regs[i].reg_size; size &= PAGE_MASK; if (base & ~PAGE_MASK) { unsigned long new_base = PAGE_ALIGN(base); size -= new_base - base; if ((long) size < 0L) size = 0UL; base = new_base; } if (size == 0UL) { /* If it is empty, simply get rid of it. * This simplifies the logic of the other * functions that process these arrays. */ memmove(®s[i], ®s[i + 1], (ents - i - 1) * sizeof(regs[0])); i--; ents--; continue; } regs[i].phys_addr = base; regs[i].reg_size = size; } *num_ents = ents; sort(regs, ents, sizeof(struct linux_prom64_registers), cmp_p64, NULL); }
int prom_getprop(pnode_t nodeid, caddr_t name, caddr_t value) { int len, rv; cell_t ci[8]; /* * This function assumes the buffer is large enough to * hold the result, so in 1275 mode, we pass in the length * of the property as the length of the buffer, since we * have no way of knowing the size of the buffer. Pre-1275 * OpenBoot(tm) PROMs did not have a bounded getprop. * * Note that we ignore the "length" result of the service. */ if ((len = prom_getproplen(nodeid, name)) <= 0) return (len); ci[0] = p1275_ptr2cell("getprop"); /* Service name */ ci[1] = (cell_t)4; /* #argument cells */ ci[2] = (cell_t)0; /* #result cells */ ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: package */ ci[4] = p1275_ptr2cell(name); /* Arg2: property name */ ci[5] = p1275_ptr2cell(value); /* Arg3: buffer address */ ci[6] = len; /* Arg4: buf len (assumed) */ promif_preprom(); rv = p1275_cif_handler(&ci); promif_postprom(); if (rv != 0) return (-1); return (len); /* Return known length */ }
/* * write new or original values to nvram */ int cpr_update_nvram(cprop_t *props) { cprop_t *tail; pnode_t node; int len, rc; if (rc = cpr_get_options_node(&node)) return (rc); if (cpr_show_props) prom_printf("\ncpr_show_props:\n"); for (tail = props + CPR_MAXPROP; props < tail; props++) { if (cpr_show_props) { prom_printf("mod=%c, name \"%s\",\tvalue \"%s\"\n", props->mod, props->name, props->value); } if (props->mod == PROP_NOMOD) continue; /* * Note: When doing a prom_setprop you must include the * trailing NULL in the length argument, but when calling * prom_getproplen() the NULL is excluded from the count! */ len = strlen(props->value); rc = prom_setprop(node, props->name, props->value, len + 1); if (rc < 0 || prom_getproplen(node, props->name) != len) { cpr_err(CE_WARN, "cannot set nvram \"%s\" to \"%s\"", props->name, props->value); return (ENXIO); } } return (0); }
/* * This routine returns B_TRUE if the bootpath corresponds to * IP over IB driver. * * The format of the bootpath for the IP over IB looks like * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip * * The minor node portion "port=1,pkey=8001,protocol=ip" represents * IP over IB driver. */ static boolean_t netboot_over_ib(char *bootpath) { char *temp; boolean_t ret = B_FALSE; pnode_t node = prom_finddevice(bootpath); int len; char devicetype[OBP_MAXDRVNAME]; /* Is this IB node ? */ len = prom_getproplen(node, OBP_DEVICETYPE); if (len <= 1 || len >= OBP_MAXDRVNAME) return (B_FALSE); (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype); if (strncmp("ib", devicetype, 2) == 0) { /* Check for proper IP over IB string */ if ((temp = strstr(bootpath, ":port=")) != NULL) { if ((temp = strstr(temp, ",pkey=")) != NULL) if ((temp = strstr(temp, ",protocol=ip")) != NULL) { ret = B_TRUE; } } } return (ret); }
/* Acquire a boolean property, 1=TRUE 0=FALSE. */ int prom_getbool(int node, char *prop) { int retval; retval = prom_getproplen(node, prop); if(retval == -1) return 0; return 1; }
void ibd_init(void) { pnode_t chosen; char *mtuprop = "ipib-frame-size"; char *bcastprop = "ipib-broadcast"; char *addrprop = "ipib-address"; char *cidprop = "client-id"; int cidlen; uint8_t dhcpcid[DHCP_MAX_CID_LEN]; mac_state.mac_addr_len = IPOIB_ADDRL; mac_state.mac_addr_buf = bkmem_alloc(mac_state.mac_addr_len); if (mac_state.mac_addr_buf == NULL) prom_panic("ibd_init: Cannot allocate memory."); chosen = prom_finddevice("/chosen"); if (chosen == OBP_NONODE || chosen == OBP_BADNODE) prom_panic("ibd_init: Cannot find /chosen."); if (prom_getprop(chosen, addrprop, (caddr_t)mac_state.mac_addr_buf) != IPOIB_ADDRL) prom_panic("ibd_init: Cannot find /chosen:ipib-address\n."); if (prom_getprop(chosen, bcastprop, (caddr_t)&ibdbroadcastaddr) != IPOIB_ADDRL) prom_panic("ibd_init: Cannot find /chosen:ipib-broadcast\n."); if (((cidlen = prom_getproplen(chosen, cidprop)) <= 0) || (cidlen > DHCP_MAX_CID_LEN) || (prom_getprop(chosen, cidprop, (caddr_t)&dhcpcid) != cidlen)) prom_panic("ibd_init: Invalid /chosen:client-id\n."); dhcp_set_client_id(dhcpcid, cidlen); /* * Note that prom reports mtu including 20 bytes of * addressing information. */ if (prom_getprop(chosen, mtuprop, (caddr_t)&mac_state.mac_mtu) <= 0) mac_state.mac_mtu = IBDSIZE + IPOIB_ADDRL; /* * Tell upper layers that we can support a little * more. We will be taking off these 20 bytes at * the start before we invoke prom_write() to send * over the wire. */ mac_state.mac_arp_timeout = IBD_ARP_TIMEOUT; mac_state.mac_in_timeout = IBD_IN_TIMEOUT; mac_state.mac_arp = ibd_arp; mac_state.mac_rarp = ibd_revarp; mac_state.mac_header_len = ibd_header_len; mac_state.mac_input = ibd_input; mac_state.mac_output = ibd_output; }
/* Acquire a boolean property, 1=TRUE 0=FALSE. */ int prom_getbool(phandle node, const char *prop) { int retval; retval = prom_getproplen(node, prop); if (retval == -1) return 0; return 1; }
void system_check(void) { char buf[PROM_VERS_MAX_LEN]; pnode_t n; char arch[128]; size_t len; bootplat_defaults_t *plat_defaults; /* * This is a sun4v machine iff the device_type property * exists on the root node and has the value "sun4v". * Some older sunfire proms do not have such a property. */ is_sun4v = 0; n = prom_rootnode(); len = prom_getproplen(n, "device_type"); if (len > 0 && len < sizeof (arch)) { (void) prom_getprop(n, "device_type", arch); arch[len] = '\0'; dprintf("device_type=%s\n", arch); if (strcmp(arch, "sun4v") == 0) { is_sun4v = 1; } } else { dprintf("device_type: no such property, len=%d\n", (int)len); } if (!is_sun4v && cpu_is_ultrasparc_1()) { printf("UltraSPARC I processors are not supported by this " "release of Solaris.\n"); prom_exit_to_mon(); } /* * Set up defaults per platform */ plat_defaults = (is_sun4v) ? &sun4v_plat_defaults : &sun4u_plat_defaults; default_name = plat_defaults->plat_defaults_name; default_path = plat_defaults->plat_defaults_path; vac = plat_defaults->plat_defaults_vac; dprintf("default_name: %s\n", default_name); dprintf("default_path: %s\n", default_path); dprintf("vac: %d\n", vac); if (prom_version_check(buf, PROM_VERS_MAX_LEN, NULL) != PROM_VER64_OK) { printf("The firmware on this system does not support the 64-bit" " OS.\n\tPlease upgrade to at least the following version:" "\n\n\t%s\n", buf); prom_exit_to_mon(); } }
static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) { static struct property *tmp = NULL; struct property *p; const char *name; if (tmp) { p = tmp; memset(p, 0, sizeof(*p) + 32); tmp = NULL; } else { p = prom_early_alloc(sizeof(struct property) + 32); p->unique_id = prom_unique_id++; } p->name = (char *) (p + 1); if (special_name) { strcpy(p->name, special_name); p->length = special_len; p->value = prom_early_alloc(special_len); memcpy(p->value, special_val, special_len); } else { if (prev == NULL) { name = prom_firstprop(node, p->name); } else { name = prom_nextprop(node, prev, p->name); } if (!name || strlen(name) == 0) { tmp = p; return NULL; } #ifdef CONFIG_SPARC32 strcpy(p->name, name); #endif p->length = prom_getproplen(node, p->name); if (p->length <= 0) { p->length = 0; } else { int len; p->value = prom_early_alloc(p->length + 1); len = prom_getproperty(node, p->name, p->value, p->length); if (len <= 0) p->length = 0; ((unsigned char *)p->value)[p->length] = '\0'; } } return p; }
/* Get the idprom and stuff it into buffer 'idbuf'. Returns the * format type. 'num_bytes' is the number of bytes that your idbuf * has space for. Returns 0xff on error. */ unsigned char prom_get_idprom(char *idbuf, int num_bytes) { int len; len = prom_getproplen(prom_root_node, "idprom"); if((len>num_bytes) || (len==-1)) return 0xff; if(!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes)) return idbuf[0]; return 0xff; }
/* Acquire a boolean property, 1=TRUE 0=FALSE. */ int prom_getbool(int node, char *prop) { int retval; #if CONFIG_AP1000 printk("prom_getbool(%s) -> 0\n",prop); return 0; #endif retval = prom_getproplen(node, prop); if(retval == -1) return 0; return 1; }
static char * __init get_one_property(phandle node, const char *name) { char *buf = "<NULL>"; int len; len = prom_getproplen(node, name); if (len > 0) { buf = prom_early_alloc(len); len = prom_getproperty(node, name, buf, len); } return buf; }
static int impl_name(char *buf, size_t bufsz) { pnode_t n = prom_rootnode(); size_t len = prom_getproplen(n, "name"); if (len == 0 || len >= bufsz) return (-1); (void) prom_getprop(n, "name", buf); buf[len] = '\0'; return (0); }
/* * Here we use the "screen-#columns" and "screen-#rows" settings of * PROM to help us decide the console size and cursor position. The * actual sizes of PROM's TEM and the console might be different with * those "screen-#.." settings, in cases that they are too big to * accommodate. */ void prom_get_tem_size(size_t *height, size_t *width) { char buf[MAXPATHLEN]; char name[16]; pnode_t node; int len; if ((node = prom_optionsnode()) == OBP_BADNODE) return; (void) prom_strcpy(name, "screen-#rows"); if ((len = prom_getproplen(node, (caddr_t)name)) > 0) { (void) prom_getprop(node, (caddr_t)name, (caddr_t)buf); *height = prom_atol(buf, len); } (void) prom_strcpy(name, "screen-#columns"); if ((len = prom_getproplen(node, (caddr_t)name)) > 0) { (void) prom_getprop(node, (caddr_t)name, (caddr_t)buf); *width = prom_atol(buf, len); } }
ihandle_t prom_memory_ihandle(void) { static ihandle_t imemory; if (imemory != (ihandle_t)0) return (imemory); if (prom_getproplen(prom_chosennode(), "memory") != sizeof (ihandle_t)) return (imemory = (ihandle_t)-1); (void) prom_getprop(prom_chosennode(), "memory", (caddr_t)(&imemory)); return (imemory); }
/* * This function replaces sys/dev/cninit.c * Determine which device is the console using * the PROM "input source" and "output sink". */ void consinit(void) { char buffer[128]; const char *consname = "unknown"; DBPRINT(("consinit()\r\n")); if (cn_tab != &consdev_prom) return; if ((prom_stdin_node = prom_instance_to_package(prom_stdin())) == 0) { printf("WARNING: no PROM stdin\n"); } DBPRINT(("stdin node = %x\r\n", prom_stdin_node)); if ((prom_stdout_node = prom_instance_to_package(prom_stdout())) == 0) printf("WARNING: no PROM stdout\n"); DBPRINT(("stdout package = %x\r\n", prom_stdout_node)); DBPRINT(("buffer @ %p\r\n", buffer)); if (prom_stdin_node != 0 && (prom_getproplen(prom_stdin_node, "keyboard") >= 0)) { #if NUKBD > 0 if ((OF_instance_to_path(prom_stdin(), buffer, sizeof(buffer)) >= 0) && (strstr(buffer, "/usb@") != NULL)) { /* * If we have a USB keyboard, it will show up as (e.g.) * /pci@1f,0/usb@c,3/keyboard@1 (Blade 100) */ consname = "usb-keyboard/display"; ukbd_cnattach(); } else #endif consname = "sun-keyboard/display"; } else if (prom_stdin_node != 0 && (OF_instance_to_path(prom_stdin(), buffer, sizeof(buffer)) >= 0)) { consname = buffer; } DBPRINT(("console is %s\n", consname)); #ifndef DEBUG (void)consname; #endif /* Initialize PROM console */ (*cn_tab->cn_probe)(cn_tab); (*cn_tab->cn_init)(cn_tab); }
/* Acquire a property 'prop' at node 'node' and place it in * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize) { int plen, ret; unsigned long flags; plen = prom_getproplen(node, prop); if((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; /* Ok, things seem all right. */ spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_getprop(node, prop, buffer); restore_current(); spin_unlock_irqrestore(&prom_lock, flags); return ret; }
/* Acquire a property 'prop' at node 'node' and place it in * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ int prom_getproperty(int node, char *prop, char *buffer, int bufsize) { int plen; #if CONFIG_AP1000 printk("prom_getproperty(%s) -> -1\n",prop); return -1; #endif plen = prom_getproplen(node, prop); if((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; /* Ok, things seem all right. */ return prom_nodeops->no_getprop(node, prop, buffer); }
/* Acquire a property 'prop' at node 'node' and place it in * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ int prom_getproperty(int node, char *prop, char *buffer, int bufsize) { int plen, ret; unsigned long flags; plen = prom_getproplen(node, prop); if((plen > bufsize) || (plen == 0) || (plen == -1)) return -1; /* Ok, things seem all right. */ save_flags(flags); cli(); ret = prom_nodeops->no_getprop(node, prop, buffer); restore_current(); restore_flags(flags); return ret; }
int prom_devicetype(pnode_t id, char *type) { register int len; char buf[OBP_MAXDRVNAME]; len = prom_getproplen(id, OBP_DEVICETYPE); if (len <= 0 || len >= OBP_MAXDRVNAME) return (0); (void) prom_getprop(id, OBP_DEVICETYPE, (caddr_t)buf); if (prom_strcmp(type, buf) == 0) return (1); return (0); }
int prom_getnode_byname(pnode_t id, char *name) { int len; char buf[OBP_MAXDRVNAME]; len = prom_getproplen(id, OBP_NAME); if (len <= 0 || len >= OBP_MAXDRVNAME) return (0); (void) prom_getprop(id, OBP_NAME, (caddr_t)buf); if (prom_strcmp(name, buf) == 0) return (1); return (0); }
static int central_get_string(int node, const char *name, char **buf) { int len; len = prom_getproplen(node, name); if (len < 0) return (len); *buf = (char *)malloc(len + 1, M_DEVBUF, M_NOWAIT); if (*buf == NULL) return (-1); if (len != 0) prom_getpropstringA(node, name, *buf, len + 1); (*buf)[len] = '\0'; return (0); }
/* Acquire a property 'prop' at node 'node' and place it in * 'buffer' which has a size of 'bufsize'. If the acquisition * was successful the length will be returned, else -1 is returned. */ inline int prom_getproperty(int node, const char *prop, char *buffer, int bufsize) { int plen; plen = prom_getproplen(node, prop); if ((plen > bufsize) || (plen == 0) || (plen == -1)) { return -1; } else { /* Ok, things seem all right. */ return p1275_cmd(prom_getprop_name, P1275_ARG(1,P1275_ARG_IN_STRING)| P1275_ARG(2,P1275_ARG_OUT_BUF)| P1275_INOUT(4, 1), node, prop, buffer, P1275_SIZE(plen)); } }
/* * If the stdin device exports the "keyboard" property and * the length of the property is 0, return true. Otherwise, * check the name of the stdin device node. If the name is * "keyboard" return true, else return false. * XXX: The "keyboard" property is not part of the IEEE 1275 standard. * XXX: Perhaps this belongs in platform dependent directories? */ int prom_stdin_is_keyboard(void) { char dev_name[OBP_MAXDRVNAME]; /* * NB: A keyboard property with a value might be an alias * or something else so we distinguish it by length. */ if (prom_getproplen(prom_stdin_node(), "keyboard") == 0) return (1); if (prom_stdin_devname(dev_name) == -1) return (0); return (prom_strcmp(dev_name, "keyboard") == 0); }
/* * returns non-zero on error, otherwise returns 0 and * sets the result code based on (prop value == "true") */ static int cpr_get_bool_prop(char *name, int *result) { char value[PROP_BOOL_LEN]; pnode_t node; int len, err; if (err = cpr_get_options_node(&node)) return (err); len = prom_getproplen(node, name); if (len < 0 || len >= sizeof (value)) return (ENXIO); bzero(value, sizeof (value)); if (prom_getprop(node, name, value) != len) return (ENOENT); *result = (strcmp(value, "true") == 0); return (0); }
uint64_t mc_get_asr_addr(pnode_t nodeid) { int rlen; uint64_t psi_addr; struct sf_memunit_regspec reg; rlen = prom_getproplen(nodeid, "reg"); if (rlen != sizeof (struct sf_memunit_regspec)) return ((uint64_t)-1); if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) return ((uint64_t)-1); psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; psi_addr |= (uint64_t)reg.regspec_addr_lo; return (STARFIRE_MC_ASR_ADDR(psi_addr)); }
uint64_t mc_get_alignment_mask(pnode_t nodeid) { uint64_t psi_addr, seg_sz; uint_t mcreg, seg_sz_mask; int i, rlen; struct sf_memunit_regspec reg; rlen = prom_getproplen(nodeid, "reg"); if (rlen != sizeof (struct sf_memunit_regspec)) return (-1); if (prom_getprop(nodeid, "reg", (caddr_t)®) < 0) return (-1); psi_addr = ((uint64_t)reg.regspec_addr_hi) << 32; psi_addr |= (uint64_t)reg.regspec_addr_lo; psi_addr = STARFIRE_MC_ASR_ADDR(psi_addr); if (psi_addr == (uint64_t)-1) return (-1); mcreg = ldphysio(psi_addr); seg_sz_mask = (mcreg & STARFIRE_MC_MASK_MASK) >> 8; for (i = 0; mc_seg_table[i].seg_size != 0; i++) if (mc_seg_table[i].seg_mask == seg_sz_mask) break; if (mc_seg_table[i].seg_size == 0) seg_sz = mc_get_mem_alignment(); else seg_sz = mc_seg_table[i].seg_size; #ifdef DEBUG printf("nodeid %x, mc asr addr %lx, val %x, seg_sz_mask %x, " "seg_sz %lx\n", nodeid, psi_addr, mcreg, seg_sz_mask, seg_sz); #endif /* DEBUG */ return (seg_sz - 1); }