prom_common.c (3442B)
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 25struct device_node *of_console_device; 26EXPORT_SYMBOL(of_console_device); 27 28char *of_console_path; 29EXPORT_SYMBOL(of_console_path); 30 31char *of_console_options; 32EXPORT_SYMBOL(of_console_options); 33 34int 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} 45EXPORT_SYMBOL(of_getintprop_default); 46 47DEFINE_MUTEX(of_set_property_mutex); 48EXPORT_SYMBOL(of_set_property_mutex); 49 50int 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} 98EXPORT_SYMBOL(of_set_property); 99 100int 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} 113EXPORT_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 */ 121static 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 132static 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 141unsigned int prom_early_allocated __initdata; 142 143static 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 151void __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}