blob: b9739b01d2acc0b060835a9d100bf5e9e064af5a [file] [log] [blame]
Mukesh Ojha82911f82018-04-30 16:45:07 +05301/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29/* Supporting function of UpdateDeviceTree()
30 * Function adds memory map entries to the device tree binary
Jeevan Shriram17f173d2017-10-24 22:11:07 -070031 * dev_tree_add_mem_info() is called at every time when memory type matches
32 * conditions */
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080033
34#include "UpdateDeviceTree.h"
lijuangf0bbcad2017-08-16 16:59:18 +080035#include "AutoGen.h"
Jeevan Shriram17f173d2017-10-24 22:11:07 -070036#include <Library/UpdateDeviceTree.h>
37#include <Protocol/EFIChipInfoTypes.h>
38#include <Protocol/EFIRng.h>
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080039
Jeevan Shriram17f173d2017-10-24 22:11:07 -070040#define DTB_PAD_SIZE 2048
41#define NUM_SPLASHMEM_PROP_ELEM 4
Mayank Groverabfc3532018-05-03 14:52:32 +053042#define DEFAULT_CELL_SIZE 2
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070043
Jeevan Shriram17f173d2017-10-24 22:11:07 -070044STATIC struct FstabNode FstabTable = {"/firmware/android/fstab", "dev",
45 "/soc/"};
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070046STATIC struct DisplaySplashBufferInfo splashBuf;
Jeevan Shriram17f173d2017-10-24 22:11:07 -070047STATIC UINTN splashBufSize = sizeof (splashBuf);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070048
Jeevan Shriram17f173d2017-10-24 22:11:07 -070049STATIC VOID
50PrintSplashMemInfo (CONST CHAR8 *data, INT32 datalen)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070051{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070052 UINT32 i, val[NUM_SPLASHMEM_PROP_ELEM] = {0};
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070053
Jeevan Shriram17f173d2017-10-24 22:11:07 -070054 for (i = 0; (i < NUM_SPLASHMEM_PROP_ELEM) && datalen; i++) {
55 memcpy (&val[i], data, sizeof (UINT32));
56 val[i] = fdt32_to_cpu (val[i]);
57 data += sizeof (UINT32);
58 datalen -= sizeof (UINT32);
59 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070060
Jeevan Shriram17f173d2017-10-24 22:11:07 -070061 DEBUG ((EFI_D_VERBOSE, "reg = <0x%08x 0x%08x 0x%08x 0x%08x>\n", val[0],
62 val[1], val[2], val[3]));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070063}
64
Jeevan Shriram17f173d2017-10-24 22:11:07 -070065STATIC EFI_STATUS
66GetKaslrSeed (UINT64 *KaslrSeed)
Runmin Wang8ecc3f62016-12-09 14:03:05 -080067{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070068 EFI_QCOM_RNG_PROTOCOL *RngIf;
69 EFI_STATUS Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -080070
Jeevan Shriram17f173d2017-10-24 22:11:07 -070071 Status = gBS->LocateProtocol (&gQcomRngProtocolGuid, NULL, (VOID **)&RngIf);
72 if (Status != EFI_SUCCESS) {
73 DEBUG ((EFI_D_VERBOSE,
74 "Error locating PRNG protocol. Fail to generate Kaslr seed:%r\n",
75 Status));
76 return Status;
77 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -080078
Jeevan Shriramf039efb2018-08-24 12:42:23 -070079 Status = RngIf->GetRNG (RngIf,
80 &gEfiRNGAlgRawGuid,
81 sizeof (UINTN),
82 (UINT8 *)KaslrSeed);
Jeevan Shriram17f173d2017-10-24 22:11:07 -070083 if (Status != EFI_SUCCESS) {
84 DEBUG ((EFI_D_VERBOSE,
Jeevan Shriram17f173d2017-10-24 22:11:07 -070085 "Error getting PRNG random number. Fail to generate Kaslr seed:%r\n",
86 Status));
87 *KaslrSeed = 0;
88 return Status;
89 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -080090
Jeevan Shriram17f173d2017-10-24 22:11:07 -070091 return Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -080092}
93
Jeevan Shriram17f173d2017-10-24 22:11:07 -070094STATIC EFI_STATUS
95UpdateSplashMemInfo (VOID *fdt)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070096{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070097 EFI_STATUS Status;
98 CONST struct fdt_property *Prop = NULL;
99 INT32 PropLen = 0;
100 INT32 ret = 0;
101 UINT32 offset;
102 CHAR8 *tmp = NULL;
103 UINT32 CONST SplashMemPropSize = NUM_SPLASHMEM_PROP_ELEM * sizeof (UINT32);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700104
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700105 Status =
106 gRT->GetVariable ((CHAR16 *)L"DisplaySplashBufferInfo",
107 &gQcomTokenSpaceGuid, NULL, &splashBufSize, &splashBuf);
108 if (Status != EFI_SUCCESS) {
109 DEBUG ((EFI_D_ERROR, "Unable to get splash buffer info, %r\n", Status));
110 goto error;
111 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700112
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700113 DEBUG ((EFI_D_VERBOSE, "Version=%d\nAddr=0x%08x\nSize=0x%08x\n",
114 splashBuf.uVersion, splashBuf.uFrameAddr, splashBuf.uFrameSize));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700115
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700116 /* Get offset of the splash memory reservation node */
117 ret = fdt_path_offset (fdt, "/reserved-memory/splash_region");
118 if (ret < 0) {
119 DEBUG ((EFI_D_ERROR, "ERROR: Could not get splash memory region node\n"));
120 return EFI_NOT_FOUND;
121 }
122 offset = ret;
123 DEBUG ((EFI_D_VERBOSE, "FB mem node name: %a\n",
124 fdt_get_name (fdt, offset, NULL)));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700125
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700126 /* Get the property that specifies the splash memory details */
127 Prop = fdt_get_property (fdt, offset, "reg", &PropLen);
128 if (!Prop) {
129 DEBUG ((EFI_D_ERROR, "ERROR: Could not find the splash reg property\n"));
130 return EFI_NOT_FOUND;
131 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700132
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700133 /*
134 * The format of the "reg" field is as follows:
135 * <0x0 FBAddress 0x0 FBSize>
136 * The expected size of this property is 4 * sizeof(UINT32)
137 */
138 if (PropLen != SplashMemPropSize) {
139 DEBUG (
140 (EFI_D_ERROR,
141 "ERROR: splash mem reservation node size. Expected: %d, Actual: %d\n",
142 SplashMemPropSize, PropLen));
143 return EFI_BAD_BUFFER_SIZE;
144 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700145
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700146 DEBUG ((EFI_D_VERBOSE, "Splash memory region before updating:\n"));
147 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700148
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700149 /* First, update the FBAddress */
150 if (CHECK_ADD64 ((UINT64)Prop->data, sizeof (UINT32))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530151 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBAddress"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700152 return EFI_BAD_BUFFER_SIZE;
153 }
154 tmp = (CHAR8 *)Prop->data + sizeof (UINT32);
155 splashBuf.uFrameAddr = cpu_to_fdt32 (splashBuf.uFrameAddr);
156 memcpy (tmp, &splashBuf.uFrameAddr, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700157
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700158 /* Next, update the FBSize */
159 if (CHECK_ADD64 ((UINT64)tmp, (2 * sizeof (UINT32)))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530160 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBSize"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700161 return EFI_BAD_BUFFER_SIZE;
162 }
163 tmp += (2 * sizeof (UINT32));
164 splashBuf.uFrameSize = cpu_to_fdt32 (splashBuf.uFrameSize);
165 memcpy (tmp, &splashBuf.uFrameSize, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700166
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700167 /* Update the property value in place */
168 ret = fdt_setprop_inplace (fdt, offset, "reg", Prop->data, PropLen);
169 if (ret < 0) {
170 DEBUG ((EFI_D_ERROR, "ERROR: Could not update splash mem info\n"));
171 return EFI_NO_MAPPING;
172 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700173
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700174 DEBUG ((EFI_D_VERBOSE, "Splash memory region after updating:\n"));
175 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700176error:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700177 return Status;
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700178}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800179
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700180UINT32
181fdt_check_header_ext (VOID *fdt)
Runmin Wange74d8042016-07-19 18:09:07 -0700182{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700183 UINT64 fdt_start, fdt_end;
184 UINT32 sum;
185 fdt_start = (UINT64)fdt;
Runmin Wange74d8042016-07-19 18:09:07 -0700186
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700187 if (fdt_start + fdt_totalsize (fdt) <= fdt_start) {
188 return FDT_ERR_BADOFFSET;
189 }
190 fdt_end = fdt_start + fdt_totalsize (fdt);
Runmin Wange74d8042016-07-19 18:09:07 -0700191
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700192 if (!(sum = ADD_OF (fdt_off_dt_struct (fdt), fdt_size_dt_struct (fdt)))) {
193 return FDT_ERR_BADOFFSET;
194 } else {
195 if (CHECK_ADD64 (fdt_start, sum))
196 return FDT_ERR_BADOFFSET;
197 else if (fdt_start + sum > fdt_end)
198 return FDT_ERR_BADOFFSET;
199 }
200 if (!(sum = ADD_OF (fdt_off_dt_strings (fdt), fdt_size_dt_strings (fdt)))) {
201 return FDT_ERR_BADOFFSET;
202 } else {
203 if (CHECK_ADD64 (fdt_start, sum))
204 return FDT_ERR_BADOFFSET;
205 else if (fdt_start + sum > fdt_end)
206 return FDT_ERR_BADOFFSET;
207 }
208 if (fdt_start + fdt_off_mem_rsvmap (fdt) > fdt_end)
209 return FDT_ERR_BADOFFSET;
210 return 0;
Runmin Wange74d8042016-07-19 18:09:07 -0700211}
212
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700213STATIC
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700214VOID
215UpdateGranuleInfo (VOID *fdt)
216{
217 EFI_STATUS Status = EFI_SUCCESS;
Bhanuprakash Modem7ee03122018-06-12 19:47:36 +0530218 INT32 GranuleNodeOffset;
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700219 UINT32 GranuleSize;
220 INT32 Ret;
221
Bhanuprakash Modem7ee03122018-06-12 19:47:36 +0530222 GranuleNodeOffset = fdt_path_offset (fdt, "/mem-offline");
223 if (GranuleNodeOffset < 0) {
224 DEBUG ((EFI_D_ERROR, "WARNING: Could not find mem-offline node.\n"));
225 return;
226 }
227
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700228 Status = GetGranuleSize (&GranuleSize);
229 if (EFI_ERROR (Status)) {
230 DEBUG ((EFI_D_ERROR,
231 "Update Granule Size failed!!! Status = %r\r\n",
232 Status));
233 return;
234 }
235
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700236 Ret = fdt_setprop_u32 (fdt, GranuleNodeOffset, "granule", GranuleSize);
237 if (Ret) {
238 DEBUG ((EFI_D_ERROR, "WARNING: Granule size update failed.\n"));
239 }
240}
241
242STATIC
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700243EFI_STATUS
Mayank Groverabfc3532018-05-03 14:52:32 +0530244QueryMemoryCellSize (IN VOID *Fdt, OUT UINT32 *MemoryCellLen)
245{
246 INT32 RootOffset;
247 INT32 PropLen;
248 UINT32 AddrCellSize = 0;
249 UINT32 SizeCellSize = 0;
250 UINT32 *Prop = NULL;
251
252 RootOffset = fdt_path_offset (Fdt, "/");
253 if (RootOffset < 0) {
254 DEBUG ((EFI_D_ERROR, "Error finding root offset\n"));
255 return EFI_NOT_FOUND;
256 }
257
258 /* Find address-cells size */
259 Prop = (UINT32 *) fdt_getprop (Fdt, RootOffset, "#address-cells", &PropLen);
260 if (Prop &&
261 PropLen > 0) {
262 AddrCellSize = fdt32_to_cpu (*Prop);
263 } else {
264 DEBUG ((EFI_D_ERROR, "Error finding #address-cells property\n"));
265 return EFI_NOT_FOUND;
266 }
267
268 /* Find size-cells size */
269 Prop =(UINT32 *) fdt_getprop (Fdt, RootOffset, "#size-cells", &PropLen);
270 if (Prop &&
271 PropLen > 0) {
272 SizeCellSize = fdt32_to_cpu (*Prop);
273 } else {
274 DEBUG ((EFI_D_ERROR, "Error finding #size-cells property\n"));
275 return EFI_NOT_FOUND;
276 }
277
278 if (AddrCellSize > DEFAULT_CELL_SIZE ||
279 SizeCellSize > DEFAULT_CELL_SIZE ||
280 SizeCellSize == 0 ||
281 AddrCellSize == 0) {
282 DEBUG ((EFI_D_ERROR, "Error unsupported cell size value: #address-cell %d" \
283 "#size-cell\n", AddrCellSize, SizeCellSize));
284 return EFI_INVALID_PARAMETER;
285 }
286
287 /* Make sure memory cell size and address cell size are same */
288 if (AddrCellSize == SizeCellSize) {
289 *MemoryCellLen = AddrCellSize;
290 } else {
291 DEBUG ((EFI_D_ERROR, "Mismatch memory address cell and size cell size\n"));
292 return EFI_INVALID_PARAMETER;
293 }
294
295 return EFI_SUCCESS;
296}
297
298STATIC
299EFI_STATUS
300AddMemMap (VOID *Fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800301{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700302 EFI_STATUS Status = EFI_NOT_FOUND;
303 INT32 ret = 0;
304 RamPartitionEntry *RamPartitions = NULL;
305 UINT32 NumPartitions = 0;
306 UINT32 i = 0;
Mayank Groverabfc3532018-05-03 14:52:32 +0530307 UINT32 MemoryCellLen = 0;
308
309 Status = QueryMemoryCellSize (Fdt, &MemoryCellLen);
310 if (EFI_ERROR (Status)) {
311 DEBUG ((EFI_D_ERROR, "ERROR: Not a valid memory node found!\n"));
312 return Status;
313 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800314
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700315 Status = GetRamPartitions (&RamPartitions, &NumPartitions);
316 if (EFI_ERROR (Status)) {
317 DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n", Status));
318 return Status;
319 }
320 if (!RamPartitions) {
321 DEBUG ((EFI_D_ERROR, "RamPartitions is NULL\n"));
322 return EFI_NOT_FOUND;
323 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800324
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700325 DEBUG ((EFI_D_INFO, "RAM Partitions\r\n"));
326 for (i = 0; i < NumPartitions; i++) {
327 DEBUG ((EFI_D_INFO, "Add Base: 0x%016lx Available Length: 0x%016lx \n",
328 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700329
Mayank Groverabfc3532018-05-03 14:52:32 +0530330 if (MemoryCellLen == 1) {
331 ret = dev_tree_add_mem_info (Fdt, MemNodeOffset, RamPartitions[i].Base,
332 RamPartitions[i].AvailableLength);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700333 } else {
Mayank Groverabfc3532018-05-03 14:52:32 +0530334 ret = dev_tree_add_mem_infoV64 (Fdt, MemNodeOffset,
335 RamPartitions[i].Base,
336 RamPartitions[i].AvailableLength);
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700337 }
338
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700339 if (ret) {
340 DEBUG ((EFI_D_ERROR, "Add Base: 0x%016lx Length: 0x%016lx Fail\n",
341 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
342 }
343 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800344
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700345 FreePool (RamPartitions);
346 RamPartitions = NULL;
347
348 return EFI_SUCCESS;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800349}
350
351/* Supporting function of UpdateDeviceTree()
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700352 * Function first gets the RAM partition table, then passes the pointer to
353 * AddMemMap() */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700354STATIC
355EFI_STATUS
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700356target_dev_tree_mem (VOID *fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800357{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700358 EFI_STATUS Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800359
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700360 /* Get Available memory from partition table */
361 Status = AddMemMap (fdt, MemNodeOffset, BootWith32Bit);
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700362 if (EFI_ERROR (Status)) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700363 DEBUG ((EFI_D_ERROR,
364 "Invalid memory configuration, check memory partition table: %r\n",
365 Status));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700366 goto out;
367 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800368
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700369 UpdateGranuleInfo (fdt);
370
371out:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700372 return Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800373}
374
375/* Supporting function of target_dev_tree_mem()
376 * Function to add the subsequent RAM partition info to the device tree */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700377INT32
378dev_tree_add_mem_info (VOID *fdt, UINT32 offset, UINT32 addr, UINT32 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800379{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700380 STATIC INT32 mem_info_cnt = 0;
381 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800382
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700383 if (!mem_info_cnt) {
384 /* Replace any other reg prop in the memory node. */
385 ret = fdt_setprop_u32 (fdt, offset, "reg", addr);
386 mem_info_cnt = 1;
387 } else {
388 /* Append the mem info to the reg prop for subsequent nodes. */
389 ret = fdt_appendprop_u32 (fdt, offset, "reg", addr);
390 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800391
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700392 if (ret) {
393 DEBUG (
394 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
395 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800396
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700397 ret = fdt_appendprop_u32 (fdt, offset, "reg", size);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800398
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700399 if (ret) {
400 DEBUG (
401 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
402 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800403
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700404 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800405}
406
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700407INT32
408dev_tree_add_mem_infoV64 (VOID *fdt, UINT32 offset, UINT64 addr, UINT64 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800409{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700410 STATIC INT32 mem_info_cnt = 0;
411 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800412
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700413 if (!mem_info_cnt) {
414 /* Replace any other reg prop in the memory node. */
415 ret = fdt_setprop_u64 (fdt, offset, "reg", addr);
416 mem_info_cnt = 1;
417 } else {
418 /* Append the mem info to the reg prop for subsequent nodes. */
419 ret = fdt_appendprop_u64 (fdt, offset, "reg", addr);
420 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800421
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700422 if (ret) {
423 DEBUG (
424 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
425 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800426
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700427 ret = fdt_appendprop_u64 (fdt, offset, "reg", size);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800428
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700429 if (ret) {
430 DEBUG (
431 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
432 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800433
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700434 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800435}
436
437/* Top level function that updates the device tree. */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700438EFI_STATUS
439UpdateDeviceTree (VOID *fdt,
440 CONST CHAR8 *cmdline,
441 VOID *ramdisk,
442 UINT32 RamDiskSize,
443 BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800444{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700445 INT32 ret = 0;
446 UINT32 offset;
447 UINT32 PaddSize = 0;
448 UINT64 KaslrSeed = 0;
449 EFI_STATUS Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800450
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700451 /* Check the device tree header */
452 ret = fdt_check_header (fdt) || fdt_check_header_ext (fdt);
453 if (ret) {
454 DEBUG ((EFI_D_ERROR, "ERROR: Invalid device tree header ...\n"));
455 return EFI_NOT_FOUND;
456 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800457
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700458 /* Add padding to make space for new nodes and properties. */
lijuangfd6fa912017-11-16 18:08:22 +0800459 PaddSize = ADD_OF (fdt_totalsize (fdt),
460 DTB_PAD_SIZE + AsciiStrLen (cmdline));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700461 if (!PaddSize) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530462 DEBUG ((EFI_D_ERROR, "ERROR: Integer Overflow: fdt size = %u\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700463 fdt_totalsize (fdt)));
464 return EFI_BAD_BUFFER_SIZE;
465 }
466 ret = fdt_open_into (fdt, fdt, PaddSize);
467 if (ret != 0) {
468 DEBUG ((EFI_D_ERROR, "ERROR: Failed to move/resize dtb buffer ...\n"));
469 return EFI_BAD_BUFFER_SIZE;
470 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800471
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700472 /* Get offset of the memory node */
473 ret = fdt_path_offset (fdt, "/memory");
474 if (ret < 0) {
475 DEBUG ((EFI_D_ERROR, "ERROR: Could not find memory node ...\n"));
476 return EFI_NOT_FOUND;
477 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800478
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700479 offset = ret;
480 Status = target_dev_tree_mem (fdt, offset, BootWith32Bit);
481 if (Status != EFI_SUCCESS) {
482 DEBUG ((EFI_D_ERROR, "ERROR: Cannot update memory node\n"));
483 return Status;
484 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800485
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700486 UpdateSplashMemInfo (fdt);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700487
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700488 /* Get offset of the chosen node */
489 ret = fdt_path_offset (fdt, "/chosen");
490 if (ret < 0) {
491 DEBUG ((EFI_D_ERROR, "ERROR: Could not find chosen node ...\n"));
492 return EFI_NOT_FOUND;
493 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800494
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700495 offset = ret;
496 if (cmdline) {
497 /* Adding the cmdline to the chosen node */
498 ret = fdt_appendprop_string (fdt, offset, (CONST char *)"bootargs",
499 (CONST VOID *)cmdline);
500 if (ret) {
501 DEBUG ((EFI_D_ERROR,
502 "ERROR: Cannot update chosen node [bootargs] - 0x%x\n", ret));
503 return EFI_LOAD_ERROR;
504 }
505 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800506
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700507 Status = GetKaslrSeed (&KaslrSeed);
508 if (Status == EFI_SUCCESS) {
509 /* Adding Kaslr Seed to the chosen node */
510 ret = fdt_appendprop_u64 (fdt, offset, (CONST char *)"kaslr-seed",
511 (UINT64)KaslrSeed);
512 if (ret) {
513 DEBUG ((EFI_D_INFO,
514 "ERROR: Cannot update chosen node [kaslr-seed] - 0x%x\n", ret));
515 } else {
516 DEBUG ((EFI_D_INFO, "kaslr-Seed is added to chosen node\n"));
517 }
518 } else {
519 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Kaslr Seed - %r\n", Status));
520 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800521
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700522 if (RamDiskSize) {
523 /* Adding the initrd-start to the chosen node */
524 ret = fdt_setprop_u64 (fdt, offset, "linux,initrd-start", (UINT64)ramdisk);
525 if (ret) {
526 DEBUG ((EFI_D_ERROR,
527 "ERROR: Cannot update chosen node [linux,initrd-start] - 0x%x\n",
528 ret));
529 return EFI_NOT_FOUND;
530 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800531
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700532 /* Adding the initrd-end to the chosen node */
533 ret = fdt_setprop_u64 (fdt, offset, "linux,initrd-end",
534 ((UINT64)ramdisk + RamDiskSize));
535 if (ret) {
536 DEBUG ((EFI_D_ERROR,
537 "ERROR: Cannot update chosen node [linux,initrd-end] - 0x%x\n",
538 ret));
539 return EFI_NOT_FOUND;
540 }
541 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530542
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700543 /* Update fstab node */
544 DEBUG ((EFI_D_VERBOSE, "Start DT fstab node update: %lu ms\n",
545 GetTimerCountms ()));
546 UpdateFstabNode (fdt);
547 DEBUG ((EFI_D_VERBOSE, "End DT fstab node update: %lu ms\n",
548 GetTimerCountms ()));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530549
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700550 fdt_pack (fdt);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800551
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700552 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800553}
Channagoud Kadabi9be68a72016-02-08 15:18:24 -0800554
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530555/* Update device tree for fstab node */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700556EFI_STATUS
557UpdateFstabNode (VOID *fdt)
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530558{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700559 INT32 ParentOffset = 0;
560 INT32 SubNodeOffset = 0;
561 CONST struct fdt_property *Prop = NULL;
562 INT32 PropLen = 0;
563 char *NodeName = NULL;
564 EFI_STATUS Status = EFI_SUCCESS;
565 CHAR8 *BootDevBuf = NULL;
566 CHAR8 *ReplaceStr = NULL;
567 CHAR8 *NextStr = NULL;
568 struct FstabNode Table = FstabTable;
569 UINT32 DevNodeBootDevLen = 0;
570 UINT32 Index = 0;
571 UINT32 PaddingEnd = 0;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530572
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700573 /* Find the parent node */
574 ParentOffset = fdt_path_offset (fdt, Table.ParentNode);
575 if (ParentOffset < 0) {
576 DEBUG ((EFI_D_VERBOSE, "Failed to Get parent node: fstab\terror: %d\n",
577 ParentOffset));
578 return EFI_NOT_FOUND;
579 }
580 DEBUG ((EFI_D_VERBOSE, "Node: %a found.\n",
581 fdt_get_name (fdt, ParentOffset, NULL)));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530582
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700583 /* Get boot device type */
584 BootDevBuf = AllocatePool (sizeof (CHAR8) * BOOT_DEV_MAX_LEN);
585 if (BootDevBuf == NULL) {
586 DEBUG ((EFI_D_ERROR, "Boot device buffer: Out of resources\n"));
587 return EFI_OUT_OF_RESOURCES;
588 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530589
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700590 Status = GetBootDevice (BootDevBuf, BOOT_DEV_MAX_LEN);
591 if (Status != EFI_SUCCESS) {
592 DEBUG ((EFI_D_ERROR, "Failed to get Boot Device: %r\n", Status));
593 FreePool (BootDevBuf);
594 BootDevBuf = NULL;
595 return Status;
596 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530597
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700598 /* Get properties of all sub nodes */
599 for (SubNodeOffset = fdt_first_subnode (fdt, ParentOffset);
600 SubNodeOffset >= 0;
601 SubNodeOffset = fdt_next_subnode (fdt, SubNodeOffset)) {
602 Prop = fdt_get_property (fdt, SubNodeOffset, Table.Property, &PropLen);
603 NodeName = (char *)(uintptr_t)fdt_get_name (fdt, SubNodeOffset, NULL);
604 if (!Prop) {
605 DEBUG ((EFI_D_VERBOSE, "Property:%a is not found for sub-node:%a\n",
606 Table.Property, NodeName));
607 } else {
608 DEBUG ((EFI_D_VERBOSE, "Property:%a found for sub-node:%a\tProperty:%a\n",
609 Table.Property, NodeName, Prop->data));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530610
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700611 /* Pointer to fdt 'dev' property string that needs to update based on the
612 * 'androidboot.bootdevice' */
613 ReplaceStr = (CHAR8 *)Prop->data;
614 ReplaceStr = AsciiStrStr (ReplaceStr, Table.DevicePathId);
615 if (!ReplaceStr) {
616 DEBUG ((EFI_D_VERBOSE, "Update property:%a value is not proper to "
617 "update for sub-node:%a\n",
618 Table.Property, NodeName));
619 continue;
620 }
621 ReplaceStr += AsciiStrLen (Table.DevicePathId);
622 NextStr = AsciiStrStr ((ReplaceStr + 1), "/");
623 DevNodeBootDevLen = NextStr - ReplaceStr;
624 if (DevNodeBootDevLen >= AsciiStrLen (BootDevBuf)) {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530625 gBS->CopyMem (ReplaceStr, BootDevBuf, AsciiStrLen (BootDevBuf));
626 PaddingEnd = DevNodeBootDevLen - AsciiStrLen (BootDevBuf);
627 /* Update the property with new value */
628 if (PaddingEnd) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700629 gBS->CopyMem (ReplaceStr + AsciiStrLen (BootDevBuf), NextStr,
630 AsciiStrLen (NextStr));
631 for (Index = 0; Index < PaddingEnd; Index++) {
632 ReplaceStr[AsciiStrLen (BootDevBuf) + AsciiStrLen (NextStr) +
633 Index] = ' ';
634 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530635 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700636 } else {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530637 DEBUG ((EFI_D_ERROR, "String length mismatch b/w DT Bootdevice string"
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700638 " (%d) and expected Bootdevice strings (%d)\n",
639 DevNodeBootDevLen, AsciiStrLen (BootDevBuf)));
640 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530641 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700642 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530643
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700644 FreePool (BootDevBuf);
645 BootDevBuf = NULL;
646 return Status;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530647}