1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/types.h>
3 #include <linux/init.h>
4 #include <linux/libfdt.h>
5 #include <linux/ctype.h>
9 u64
get_kaslr_seed(uintptr_t dtb_pa
)
15 node
= fdt_path_offset((void *)dtb_pa
, "/chosen");
19 prop
= fdt_getprop_w((void *)dtb_pa
, node
, "kaslr-seed", &len
);
20 if (!prop
|| len
!= sizeof(u64
))
23 ret
= fdt64_to_cpu(*prop
);
29 * fdt_device_is_available - check if a device is available for use
31 * @fdt: pointer to the device tree blob
32 * @node: offset of the node whose property to find
34 * Returns true if the status property is absent or set to "okay" or "ok",
37 static bool fdt_device_is_available(const void *fdt
, int node
)
42 status
= fdt_getprop(fdt
, node
, "status", &statlen
);
47 if (!strcmp(status
, "okay") || !strcmp(status
, "ok"))
54 /* Copy of fdt_nodename_eq_ */
55 static int fdt_node_name_eq(const void *fdt
, int offset
,
60 const char *p
= fdt_get_name(fdt
, offset
, &olen
);
66 if (memcmp(p
, s
, len
) != 0)
71 else if (!memchr(s
, '@', len
) && (p
[len
] == '@'))
78 * isa_string_contains - check if isa string contains an extension
80 * @isa_str: isa string to search
81 * @ext_name: the extension to search for
83 * Returns true if the extension is in the given isa string,
86 static bool isa_string_contains(const char *isa_str
, const char *ext_name
)
88 size_t i
, single_end
, len
= strlen(ext_name
);
91 /* Error must contain rv32/64 */
92 if (strlen(isa_str
) < 4)
96 single_end
= strcspn(isa_str
, "sSxXzZ");
97 /* Search for single chars between rv32/64 and multi-letter extensions */
98 for (i
= 4; i
< single_end
; i
++) {
99 if (tolower(isa_str
[i
]) == ext_name
[0])
105 /* Skip to start of multi-letter extensions */
106 isa_str
= strpbrk(isa_str
, "sSxXzZ");
108 if (strncasecmp(isa_str
, ext_name
, len
) == 0) {
109 ext_end
= isa_str
[len
];
110 /* Check if matches the whole extension. */
111 if (ext_end
== '\0' || ext_end
== '_')
114 /* Multi-letter extensions must be split from other multi-letter
115 * extensions with an "_", the end of a multi-letter extension will
116 * either be the null character or the "_" at the start of the next
117 * multi-letter extension.
119 isa_str
= strchr(isa_str
, '_');
128 * early_cpu_isa_ext_available - check if cpu node has an extension
130 * @fdt: pointer to the device tree blob
131 * @node: offset of the cpu node
132 * @ext_name: the extension to search for
134 * Returns true if the cpu node has the extension,
137 static bool early_cpu_isa_ext_available(const void *fdt
, int node
, const char *ext_name
)
142 prop
= fdt_getprop(fdt
, node
, "riscv,isa-extensions", &len
);
143 if (prop
&& fdt_stringlist_contains(prop
, len
, ext_name
))
146 prop
= fdt_getprop(fdt
, node
, "riscv,isa", &len
);
147 if (prop
&& isa_string_contains(prop
, ext_name
))
154 * fdt_early_match_extension_isa - check if all cpu nodes have an extension
156 * @fdt: pointer to the device tree blob
157 * @ext_name: the extension to search for
159 * Returns true if the all available the cpu nodes have the extension,
162 bool fdt_early_match_extension_isa(const void *fdt
, const char *ext_name
)
167 parent
= fdt_path_offset(fdt
, "/cpus");
171 fdt_for_each_subnode(node
, fdt
, parent
) {
172 if (!fdt_node_name_eq(fdt
, node
, "cpu"))
175 if (!fdt_device_is_available(fdt
, node
))
178 if (!early_cpu_isa_ext_available(fdt
, node
, ext_name
))