2 * Copyright (c) 2014, Linaro Ltd. All rights reserved.
4 * This program and the accompanying materials
5 * are licensed and made available under the terms and conditions of the BSD License
6 * which accompanies this distribution. The full text of the license may be found at
7 * http://opensource.org/licenses/bsd-license.php
9 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 * This code parses a Flattened Device Tree binary (DTB) to find the base of
18 * system RAM. It is written in assembly so that it can be executed before a
19 * stack has been set up.
21 * To find the base of system RAM, we have to traverse the FDT to find a memory
22 * node. In the context of this implementation, the first node that has a
23 * device_type property with the value 'memory' and a 'reg' property is
24 * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any
25 * other nodes that match the above constraints.
27 * In pseudo code, this implementation does the following:
30 * have_device_type = false
34 * if property value == 'memory' {
35 * if property name == 'device_type' {
36 * have_device_type = true
39 * if property name == 'reg' {
41 * membase = property value[0]
42 * memsize = property value[1]
46 * if have_device_type and have_reg {
47 * return membase and memsize
53 #define FDT_MAGIC 0xedfe0dd0
55 #define FDT_BEGIN_NODE 0x1
56 #define FDT_END_NODE 0x2
60 xMEMSIZE .req x0 // recorded system RAM size
61 xMEMBASE .req x1 // recorded system RAM base
63 xLR .req x8 // our preserved link register
64 xDTP .req x9 // pointer to traverse the DT structure
65 xSTRTAB .req x10 // pointer to the DTB string table
66 xMEMNODE .req x11 // bit field to record found properties
69 #define HAVE_DEVICE_TYPE 0x2
81 * Compare strings in x4 and x5, return in w7
95 // preserve link register
100 * Check the DTB magic at offset 0
102 movz w4, #:abs_g0_nc:FDT_MAGIC
103 movk w4, #:abs_g1:FDT_MAGIC
106 bne err_invalid_magic
109 * Read the string offset and store it for later use
113 add xSTRTAB, xDTP, x4
116 * Read the struct offset and add it to the DT pointer
123 * Check current tag for FDT_BEGIN_NODE
127 cmp w5, #FDT_BEGIN_NODE
128 bne err_unexpected_begin_tag
135 * Advance xDTP past NULL terminated string
137 0: ldrb w4, [xDTP], #1
142 * Align the DT pointer xDTP to the next 32-bit boundary
148 * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END
152 cmp w5, #FDT_BEGIN_NODE
154 cmp w5, #FDT_END_NODE
164 * If propname == 'reg', record as membase and memsize
165 * If propname == 'device_type' and value == 'memory',
166 * set the 'is_memnode' flag for this node
176 * Get handle to property name
182 cbz w7, check_device_type
185 * Check for 'reg' property
189 cbnz w7, inc_and_next_tag
192 * Extract two 64-bit quantities from the 'reg' property. These values
193 * will only be used if the node also turns out to have a device_type
194 * property with a value of 'memory'.
196 * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most
197 * likely executing with the MMU off, so we cannot use 64 bit
198 * wide accesses here.
201 orr xMEMBASE, x4, x5, lsl #32
202 ldp w4, w5, [xDTP, #8]
203 orr xMEMSIZE, x4, x5, lsl #32
204 rev xMEMBASE, xMEMBASE
205 rev xMEMSIZE, xMEMSIZE
206 orr xMEMNODE, xMEMNODE, #HAVE_REG
211 * Check whether the current property's name is 'device_type'
215 cbnz w7, inc_and_next_tag
216 orr xMEMNODE, xMEMNODE, #HAVE_DEVICE_TYPE
224 * Check for device_type = memory and reg = xxxx
225 * If we have both, we are done
228 cmp xMEMNODE, #(HAVE_REG | HAVE_DEVICE_TYPE)
234 err_unexpected_begin_tag: