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, lenp: &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(p: val, size: 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(s1: prop->name, s2: 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(objp: 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(lock: &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(root_node: prom_root_node, ops: &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 | |