1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* prom_common.c: OF device tree support common code. 3 * 4 * Paul Mackerras August 1996. 5 * Copyright (C) 1996-2005 Paul Mackerras. 6 * 7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 8 * {engebret|bergner}@us.ibm.com 9 * 10 * Adapted for sparc by David S. Miller davem@davemloft.net 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/export.h> 15 #include <linux/errno.h> 16 #include <linux/mutex.h> 17 #include <linux/slab.h> 18 #include <linux/of.h> 19 #include <linux/of_pdt.h> 20 #include <asm/prom.h> 21 #include <asm/oplib.h> 22 23 #include "prom.h" 24 25 struct device_node *of_console_device; 26 EXPORT_SYMBOL(of_console_device); 27 28 char *of_console_path; 29 EXPORT_SYMBOL(of_console_path); 30 31 char *of_console_options; 32 EXPORT_SYMBOL(of_console_options); 33 34 int of_getintprop_default(struct device_node *np, const char *name, int def) 35 { 36 struct property *prop; 37 int len; 38 39 prop = of_find_property(np, name, &len); 40 if (!prop || len != 4) 41 return def; 42 43 return *(int *) prop->value; 44 } 45 EXPORT_SYMBOL(of_getintprop_default); 46 47 DEFINE_MUTEX(of_set_property_mutex); 48 EXPORT_SYMBOL(of_set_property_mutex); 49 50 int of_set_property(struct device_node *dp, const char *name, void *val, int len) 51 { 52 struct property **prevp; 53 unsigned long flags; 54 void *new_val; 55 int err; 56 57 new_val = kmemdup(val, len, GFP_KERNEL); 58 if (!new_val) 59 return -ENOMEM; 60 61 err = -ENODEV; 62 63 mutex_lock(&of_set_property_mutex); 64 raw_spin_lock_irqsave(&devtree_lock, flags); 65 prevp = &dp->properties; 66 while (*prevp) { 67 struct property *prop = *prevp; 68 69 if (!strcasecmp(prop->name, name)) { 70 void *old_val = prop->value; 71 int ret; 72 73 ret = prom_setprop(dp->phandle, name, val, len); 74 75 err = -EINVAL; 76 if (ret >= 0) { 77 prop->value = new_val; 78 prop->length = len; 79 80 if (OF_IS_DYNAMIC(prop)) 81 kfree(old_val); 82 83 OF_MARK_DYNAMIC(prop); 84 85 err = 0; 86 } 87 break; 88 } 89 prevp = &(*prevp)->next; 90 } 91 raw_spin_unlock_irqrestore(&devtree_lock, flags); 92 mutex_unlock(&of_set_property_mutex); 93 94 /* XXX Upate procfs if necessary... */ 95 96 return err; 97 } 98 EXPORT_SYMBOL(of_set_property); 99 100 int of_find_in_proplist(const char *list, const char *match, int len) 101 { 102 while (len > 0) { 103 int l; 104 105 if (!strcmp(list, match)) 106 return 1; 107 l = strlen(list) + 1; 108 list += l; 109 len -= l; 110 } 111 return 0; 112 } 113 EXPORT_SYMBOL(of_find_in_proplist); 114 115 /* 116 * SPARC32 and SPARC64's prom_nextprop() do things differently 117 * here, despite sharing the same interface. SPARC32 doesn't fill in 'buf', 118 * returning NULL on an error. SPARC64 fills in 'buf', but sets it to an 119 * empty string upon error. 120 */ 121 static int __init handle_nextprop_quirks(char *buf, const char *name) 122 { 123 if (!name || strlen(name) == 0) 124 return -1; 125 126 #ifdef CONFIG_SPARC32 127 strcpy(buf, name); 128 #endif 129 return 0; 130 } 131 132 static int __init prom_common_nextprop(phandle node, char *prev, char *buf) 133 { 134 const char *name; 135 136 buf[0] = '\0'; 137 name = prom_nextprop(node, prev, buf); 138 return handle_nextprop_quirks(buf, name); 139 } 140 141 unsigned int prom_early_allocated __initdata; 142 143 static struct of_pdt_ops prom_sparc_ops __initdata = { 144 .nextprop = prom_common_nextprop, 145 .getproplen = prom_getproplen, 146 .getproperty = prom_getproperty, 147 .getchild = prom_getchild, 148 .getsibling = prom_getsibling, 149 }; 150 151 void __init prom_build_devicetree(void) 152 { 153 of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops); 154 of_console_init(); 155 156 pr_info("PROM: Built device tree with %u bytes of memory.\n", 157 prom_early_allocated); 158 } 159