]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S
MdeModulePkg/UfsPciHcDxe: Fix EBC build error
[mirror_edk2.git] / ArmPlatformPkg / ArmVirtualizationPkg / Library / ArmXenRelocatablePlatformLib / AARCH64 / MemnodeParser.S
CommitLineData
f9849036
AB
1/*\r
2 * Copyright (c) 2014, Linaro Ltd. All rights reserved.\r
3 *\r
4 * This program and the accompanying materials\r
5 * are licensed and made available under the terms and conditions of the BSD License\r
6 * which accompanies this distribution. The full text of the license may be found at\r
7 * http://opensource.org/licenses/bsd-license.php\r
8 *\r
9 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 */\r
12\r
13/*\r
14 * Theory of operation\r
15 * -------------------\r
16 *\r
17 * This code parses a Flattened Device Tree binary (DTB) to find the base of\r
18 * system RAM. It is written in assembly so that it can be executed before a\r
19 * stack has been set up.\r
20 *\r
21 * To find the base of system RAM, we have to traverse the FDT to find a memory\r
22 * node. In the context of this implementation, the first node that has a\r
23 * device_type property with the value 'memory' and a 'reg' property is\r
24 * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any\r
25 * other nodes that match the above constraints.\r
26 *\r
27 * In pseudo code, this implementation does the following:\r
28 *\r
29 * for each node {\r
58bc4065
OM
30 * have_device_type = false\r
31 * have_reg = false\r
f9849036 32 *\r
58bc4065
OM
33 * for each property {\r
34 * if property value == 'memory' {\r
35 * if property name == 'device_type' {\r
36 * have_device_type = true\r
37 * }\r
38 * } else {\r
39 * if property name == 'reg' {\r
40 * have_reg = true\r
41 * membase = property value[0]\r
42 * memsize = property value[1]\r
43 * }\r
44 * }\r
45 * }\r
46 * if have_device_type and have_reg {\r
47 * return membase and memsize\r
48 * }\r
f9849036
AB
49 * }\r
50 * return NOT_FOUND\r
51 */\r
52\r
58bc4065 53#define FDT_MAGIC 0xedfe0dd0\r
f9849036 54\r
58bc4065
OM
55#define FDT_BEGIN_NODE 0x1\r
56#define FDT_END_NODE 0x2\r
57#define FDT_PROP 0x3\r
58#define FDT_END 0x9\r
f9849036 59\r
58bc4065
OM
60 xMEMSIZE .req x0 // recorded system RAM size\r
61 xMEMBASE .req x1 // recorded system RAM base\r
f9849036 62\r
58bc4065
OM
63 xLR .req x8 // our preserved link register\r
64 xDTP .req x9 // pointer to traverse the DT structure\r
65 xSTRTAB .req x10 // pointer to the DTB string table\r
66 xMEMNODE .req x11 // bit field to record found properties\r
f9849036 67\r
58bc4065
OM
68#define HAVE_REG 0x1\r
69#define HAVE_DEVICE_TYPE 0x2\r
f9849036 70\r
58bc4065
OM
71 .text\r
72 .align 3\r
f9849036 73_memory:\r
58bc4065 74 .asciz "memory"\r
f9849036 75_reg:\r
58bc4065 76 .asciz "reg"\r
f9849036 77_device_type:\r
58bc4065 78 .asciz "device_type"\r
f9849036 79\r
58bc4065
OM
80 /*\r
81 * Compare strings in x4 and x5, return in w7\r
82 */\r
83 .align 3\r
f9849036 84strcmp:\r
58bc4065
OM
85 ldrb w2, [x4], #1\r
86 ldrb w3, [x5], #1\r
87 subs w7, w2, w3\r
88 cbz w2, 0f\r
89 cbz w3, 0f\r
90 beq strcmp\r
910: ret\r
92\r
93 .globl find_memnode\r
f9849036 94find_memnode:\r
58bc4065
OM
95 // preserve link register\r
96 mov xLR, x30\r
97 mov xDTP, x0\r
98\r
99 /*\r
100 * Check the DTB magic at offset 0\r
101 */\r
102 movz w4, #:abs_g0_nc:FDT_MAGIC\r
103 movk w4, #:abs_g1:FDT_MAGIC\r
104 ldr w5, [xDTP]\r
105 cmp w4, w5\r
106 bne err_invalid_magic\r
107\r
108 /*\r
109 * Read the string offset and store it for later use\r
110 */\r
111 ldr w4, [xDTP, #12]\r
112 rev w4, w4\r
113 add xSTRTAB, xDTP, x4\r
114\r
115 /*\r
116 * Read the struct offset and add it to the DT pointer\r
117 */\r
118 ldr w5, [xDTP, #8]\r
119 rev w5, w5\r
120 add xDTP, xDTP, x5\r
121\r
122 /*\r
123 * Check current tag for FDT_BEGIN_NODE\r
124 */\r
125 ldr w5, [xDTP]\r
126 rev w5, w5\r
127 cmp w5, #FDT_BEGIN_NODE\r
128 bne err_unexpected_begin_tag\r
f9849036
AB
129\r
130begin_node:\r
58bc4065
OM
131 mov xMEMNODE, #0\r
132 add xDTP, xDTP, #4\r
f9849036 133\r
58bc4065
OM
134 /*\r
135 * Advance xDTP past NULL terminated string\r
136 */\r
1370: ldrb w4, [xDTP], #1\r
138 cbnz w4, 0b\r
f9849036
AB
139\r
140next_tag:\r
58bc4065
OM
141 /*\r
142 * Align the DT pointer xDTP to the next 32-bit boundary\r
143 */\r
144 add xDTP, xDTP, #3\r
145 and xDTP, xDTP, #~3\r
146\r
147 /*\r
148 * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END\r
149 */\r
150 ldr w5, [xDTP]\r
151 rev w5, w5\r
152 cmp w5, #FDT_BEGIN_NODE\r
153 beq begin_node\r
154 cmp w5, #FDT_END_NODE\r
155 beq end_node\r
156 cmp w5, #FDT_PROP\r
157 beq prop_node\r
158 cmp w5, #FDT_END\r
159 beq err_end_of_fdt\r
160 b err_unexpected_tag\r
f9849036
AB
161\r
162prop_node:\r
58bc4065
OM
163 /*\r
164 * If propname == 'reg', record as membase and memsize\r
165 * If propname == 'device_type' and value == 'memory',\r
166 * set the 'is_memnode' flag for this node\r
167 */\r
168 ldr w6, [xDTP, #4]\r
169 add xDTP, xDTP, #12\r
170 rev w6, w6\r
171 mov x5, xDTP\r
172 adr x4, _memory\r
173 bl strcmp\r
174\r
175 /*\r
176 * Get handle to property name\r
177 */\r
178 ldr w5, [xDTP, #-4]\r
179 rev w5, w5\r
180 add x5, xSTRTAB, x5\r
181\r
182 cbz w7, check_device_type\r
183\r
184 /*\r
185 * Check for 'reg' property\r
186 */\r
187 adr x4, _reg\r
188 bl strcmp\r
189 cbnz w7, inc_and_next_tag\r
190\r
191 /*\r
192 * Extract two 64-bit quantities from the 'reg' property. These values\r
193 * will only be used if the node also turns out to have a device_type\r
194 * property with a value of 'memory'.\r
195 *\r
196 * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most\r
197 * likely executing with the MMU off, so we cannot use 64 bit\r
198 * wide accesses here.\r
199 */\r
200 ldp w4, w5, [xDTP]\r
201 orr xMEMBASE, x4, x5, lsl #32\r
202 ldp w4, w5, [xDTP, #8]\r
203 orr xMEMSIZE, x4, x5, lsl #32\r
204 rev xMEMBASE, xMEMBASE\r
205 rev xMEMSIZE, xMEMSIZE\r
206 orr xMEMNODE, xMEMNODE, #HAVE_REG\r
207 b inc_and_next_tag\r
f9849036
AB
208\r
209check_device_type:\r
58bc4065
OM
210 /*\r
211 * Check whether the current property's name is 'device_type'\r
212 */\r
213 adr x4, _device_type\r
214 bl strcmp\r
215 cbnz w7, inc_and_next_tag\r
216 orr xMEMNODE, xMEMNODE, #HAVE_DEVICE_TYPE\r
f9849036
AB
217\r
218inc_and_next_tag:\r
58bc4065
OM
219 add xDTP, xDTP, x6\r
220 b next_tag\r
f9849036
AB
221\r
222end_node:\r
58bc4065
OM
223 /*\r
224 * Check for device_type = memory and reg = xxxx\r
225 * If we have both, we are done\r
226 */\r
227 add xDTP, xDTP, #4\r
228 cmp xMEMNODE, #(HAVE_REG | HAVE_DEVICE_TYPE)\r
229 bne next_tag\r
f9849036 230\r
58bc4065 231 ret xLR\r
f9849036
AB
232\r
233err_invalid_magic:\r
234err_unexpected_begin_tag:\r
235err_unexpected_tag:\r
236err_end_of_fdt:\r
58bc4065 237 wfi\r