xref: /aosp_15_r20/external/arm-trusted-firmware/include/lib/utils.h (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #ifndef UTILS_H
8*54fd6939SJiyong Park #define UTILS_H
9*54fd6939SJiyong Park 
10*54fd6939SJiyong Park /*
11*54fd6939SJiyong Park  * C code should be put in this part of the header to avoid breaking ASM files
12*54fd6939SJiyong Park  * or linker scripts including it.
13*54fd6939SJiyong Park  */
14*54fd6939SJiyong Park #if !(defined(__LINKER__) || defined(__ASSEMBLER__))
15*54fd6939SJiyong Park 
16*54fd6939SJiyong Park #include <stddef.h>
17*54fd6939SJiyong Park #include <stdint.h>
18*54fd6939SJiyong Park 
19*54fd6939SJiyong Park typedef struct mem_region {
20*54fd6939SJiyong Park 	uintptr_t base;
21*54fd6939SJiyong Park 	size_t nbytes;
22*54fd6939SJiyong Park } mem_region_t;
23*54fd6939SJiyong Park 
24*54fd6939SJiyong Park /*
25*54fd6939SJiyong Park  * zero_normalmem all the regions defined in tbl.
26*54fd6939SJiyong Park  */
27*54fd6939SJiyong Park void clear_mem_regions(mem_region_t *tbl, size_t nregions);
28*54fd6939SJiyong Park 
29*54fd6939SJiyong Park /*
30*54fd6939SJiyong Park  * zero_normalmem all the regions defined in region. It dynamically
31*54fd6939SJiyong Park  * maps chunks of 'chunk_size' in 'va' virtual address and clears them.
32*54fd6939SJiyong Park  * For this reason memory regions must be multiple of chunk_size and
33*54fd6939SJiyong Park  * must be aligned to it as well. chunk_size and va can be selected
34*54fd6939SJiyong Park  * in a way that they minimize the number of entries used in the
35*54fd6939SJiyong Park  * translation tables.
36*54fd6939SJiyong Park  */
37*54fd6939SJiyong Park void clear_map_dyn_mem_regions(struct mem_region *regions,
38*54fd6939SJiyong Park 			       size_t nregions,
39*54fd6939SJiyong Park 			       uintptr_t va,
40*54fd6939SJiyong Park 			       size_t chunk);
41*54fd6939SJiyong Park 
42*54fd6939SJiyong Park /*
43*54fd6939SJiyong Park  * checks that a region (addr + nbytes-1) of memory is totally covered by
44*54fd6939SJiyong Park  * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1)
45*54fd6939SJiyong Park  * doesn't overflow.
46*54fd6939SJiyong Park  */
47*54fd6939SJiyong Park int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
48*54fd6939SJiyong Park 			    uintptr_t addr, size_t nbytes);
49*54fd6939SJiyong Park 
50*54fd6939SJiyong Park /*
51*54fd6939SJiyong Park  * Fill a region of normal memory of size "length" in bytes with zero bytes.
52*54fd6939SJiyong Park  *
53*54fd6939SJiyong Park  * WARNING: This function can only operate on normal memory. This means that
54*54fd6939SJiyong Park  *          the MMU must be enabled when using this function. Otherwise, use
55*54fd6939SJiyong Park  *          zeromem.
56*54fd6939SJiyong Park  */
57*54fd6939SJiyong Park void zero_normalmem(void *mem, u_register_t length);
58*54fd6939SJiyong Park 
59*54fd6939SJiyong Park /*
60*54fd6939SJiyong Park  * Fill a region of memory of size "length" in bytes with null bytes.
61*54fd6939SJiyong Park  *
62*54fd6939SJiyong Park  * Unlike zero_normalmem, this function has no restriction on the type of
63*54fd6939SJiyong Park  * memory targeted and can be used for any device memory as well as normal
64*54fd6939SJiyong Park  * memory. This function must be used instead of zero_normalmem when MMU is
65*54fd6939SJiyong Park  * disabled.
66*54fd6939SJiyong Park  *
67*54fd6939SJiyong Park  * NOTE: When data cache and MMU are enabled, prefer zero_normalmem for faster
68*54fd6939SJiyong Park  *       zeroing.
69*54fd6939SJiyong Park  */
70*54fd6939SJiyong Park void zeromem(void *mem, u_register_t length);
71*54fd6939SJiyong Park 
72*54fd6939SJiyong Park /*
73*54fd6939SJiyong Park  * Utility function to return the address of a symbol. By default, the
74*54fd6939SJiyong Park  * compiler generates adr/adrp instruction pair to return the reference
75*54fd6939SJiyong Park  * to the symbol and this utility is used to override this compiler
76*54fd6939SJiyong Park  * generated to code to use `ldr` instruction.
77*54fd6939SJiyong Park  *
78*54fd6939SJiyong Park  * This helps when Position Independent Executable needs to reference a symbol
79*54fd6939SJiyong Park  * which is constant and does not depend on the execute address of the binary.
80*54fd6939SJiyong Park  */
81*54fd6939SJiyong Park #define DEFINE_LOAD_SYM_ADDR(_name)		\
82*54fd6939SJiyong Park static inline u_register_t load_addr_## _name(void)			\
83*54fd6939SJiyong Park {									\
84*54fd6939SJiyong Park 	u_register_t v;							\
85*54fd6939SJiyong Park 	__asm__ volatile ("ldr %0, =" #_name : "=r" (v) : "X" (#_name));\
86*54fd6939SJiyong Park 	return v;							\
87*54fd6939SJiyong Park }
88*54fd6939SJiyong Park 
89*54fd6939SJiyong Park /* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */
90*54fd6939SJiyong Park #define LOAD_ADDR_OF(_name)	(typeof(_name) *) load_addr_## _name()
91*54fd6939SJiyong Park 
92*54fd6939SJiyong Park #endif /* !(defined(__LINKER__) || defined(__ASSEMBLER__)) */
93*54fd6939SJiyong Park 
94*54fd6939SJiyong Park #endif /* UTILS_H */
95