blob: 7da504ee2e77a687e5f313d9e498f32017be8501 [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
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070042
Jeevan Shriram17f173d2017-10-24 22:11:07 -070043STATIC struct FstabNode FstabTable = {"/firmware/android/fstab", "dev",
44 "/soc/"};
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070045STATIC struct DisplaySplashBufferInfo splashBuf;
Jeevan Shriram17f173d2017-10-24 22:11:07 -070046STATIC UINTN splashBufSize = sizeof (splashBuf);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070047
Jeevan Shriram17f173d2017-10-24 22:11:07 -070048STATIC VOID
49PrintSplashMemInfo (CONST CHAR8 *data, INT32 datalen)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070050{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070051 UINT32 i, val[NUM_SPLASHMEM_PROP_ELEM] = {0};
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070052
Jeevan Shriram17f173d2017-10-24 22:11:07 -070053 for (i = 0; (i < NUM_SPLASHMEM_PROP_ELEM) && datalen; i++) {
54 memcpy (&val[i], data, sizeof (UINT32));
55 val[i] = fdt32_to_cpu (val[i]);
56 data += sizeof (UINT32);
57 datalen -= sizeof (UINT32);
58 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070059
Jeevan Shriram17f173d2017-10-24 22:11:07 -070060 DEBUG ((EFI_D_VERBOSE, "reg = <0x%08x 0x%08x 0x%08x 0x%08x>\n", val[0],
61 val[1], val[2], val[3]));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070062}
63
Jeevan Shriram17f173d2017-10-24 22:11:07 -070064STATIC EFI_STATUS
65GetKaslrSeed (UINT64 *KaslrSeed)
Runmin Wang8ecc3f62016-12-09 14:03:05 -080066{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070067 EFI_QCOM_RNG_PROTOCOL *RngIf;
68 EFI_STATUS Status;
69 EFI_GUID AlgoId;
70 UINTN AlgoIdSize = sizeof (EFI_GUID);
Runmin Wang8ecc3f62016-12-09 14:03:05 -080071
Jeevan Shriram17f173d2017-10-24 22:11:07 -070072 Status = gBS->LocateProtocol (&gQcomRngProtocolGuid, NULL, (VOID **)&RngIf);
73 if (Status != EFI_SUCCESS) {
74 DEBUG ((EFI_D_VERBOSE,
75 "Error locating PRNG protocol. Fail to generate Kaslr seed:%r\n",
76 Status));
77 return Status;
78 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -080079
Jeevan Shriram17f173d2017-10-24 22:11:07 -070080 Status = RngIf->GetInfo (RngIf, &AlgoIdSize, &AlgoId);
81 if (Status != EFI_SUCCESS) {
82 DEBUG ((EFI_D_VERBOSE,
83 "Error GetInfo for PRNG failed. Fail to generate Kaslr seed:%r\n",
84 Status));
85 return Status;
86 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -080087
Jeevan Shriram17f173d2017-10-24 22:11:07 -070088 Status = RngIf->GetRNG (RngIf, &AlgoId, sizeof (UINTN), (UINT8 *)KaslrSeed);
89 if (Status != EFI_SUCCESS) {
90 DEBUG (
91 (EFI_D_VERBOSE,
92 "Error getting PRNG random number. Fail to generate Kaslr seed:%r\n",
93 Status));
94 *KaslrSeed = 0;
95 return Status;
96 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -080097
Jeevan Shriram17f173d2017-10-24 22:11:07 -070098 return Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -080099}
100
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700101STATIC EFI_STATUS
102UpdateSplashMemInfo (VOID *fdt)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700103{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700104 EFI_STATUS Status;
105 CONST struct fdt_property *Prop = NULL;
106 INT32 PropLen = 0;
107 INT32 ret = 0;
108 UINT32 offset;
109 CHAR8 *tmp = NULL;
110 UINT32 CONST SplashMemPropSize = NUM_SPLASHMEM_PROP_ELEM * sizeof (UINT32);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700111
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700112 Status =
113 gRT->GetVariable ((CHAR16 *)L"DisplaySplashBufferInfo",
114 &gQcomTokenSpaceGuid, NULL, &splashBufSize, &splashBuf);
115 if (Status != EFI_SUCCESS) {
116 DEBUG ((EFI_D_ERROR, "Unable to get splash buffer info, %r\n", Status));
117 goto error;
118 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700119
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700120 DEBUG ((EFI_D_VERBOSE, "Version=%d\nAddr=0x%08x\nSize=0x%08x\n",
121 splashBuf.uVersion, splashBuf.uFrameAddr, splashBuf.uFrameSize));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700122
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700123 /* Get offset of the splash memory reservation node */
124 ret = fdt_path_offset (fdt, "/reserved-memory/splash_region");
125 if (ret < 0) {
126 DEBUG ((EFI_D_ERROR, "ERROR: Could not get splash memory region node\n"));
127 return EFI_NOT_FOUND;
128 }
129 offset = ret;
130 DEBUG ((EFI_D_VERBOSE, "FB mem node name: %a\n",
131 fdt_get_name (fdt, offset, NULL)));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700132
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700133 /* Get the property that specifies the splash memory details */
134 Prop = fdt_get_property (fdt, offset, "reg", &PropLen);
135 if (!Prop) {
136 DEBUG ((EFI_D_ERROR, "ERROR: Could not find the splash reg property\n"));
137 return EFI_NOT_FOUND;
138 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700139
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700140 /*
141 * The format of the "reg" field is as follows:
142 * <0x0 FBAddress 0x0 FBSize>
143 * The expected size of this property is 4 * sizeof(UINT32)
144 */
145 if (PropLen != SplashMemPropSize) {
146 DEBUG (
147 (EFI_D_ERROR,
148 "ERROR: splash mem reservation node size. Expected: %d, Actual: %d\n",
149 SplashMemPropSize, PropLen));
150 return EFI_BAD_BUFFER_SIZE;
151 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700152
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700153 DEBUG ((EFI_D_VERBOSE, "Splash memory region before updating:\n"));
154 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700155
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700156 /* First, update the FBAddress */
157 if (CHECK_ADD64 ((UINT64)Prop->data, sizeof (UINT32))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530158 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBAddress"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700159 return EFI_BAD_BUFFER_SIZE;
160 }
161 tmp = (CHAR8 *)Prop->data + sizeof (UINT32);
162 splashBuf.uFrameAddr = cpu_to_fdt32 (splashBuf.uFrameAddr);
163 memcpy (tmp, &splashBuf.uFrameAddr, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700164
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700165 /* Next, update the FBSize */
166 if (CHECK_ADD64 ((UINT64)tmp, (2 * sizeof (UINT32)))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530167 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBSize"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700168 return EFI_BAD_BUFFER_SIZE;
169 }
170 tmp += (2 * sizeof (UINT32));
171 splashBuf.uFrameSize = cpu_to_fdt32 (splashBuf.uFrameSize);
172 memcpy (tmp, &splashBuf.uFrameSize, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700173
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700174 /* Update the property value in place */
175 ret = fdt_setprop_inplace (fdt, offset, "reg", Prop->data, PropLen);
176 if (ret < 0) {
177 DEBUG ((EFI_D_ERROR, "ERROR: Could not update splash mem info\n"));
178 return EFI_NO_MAPPING;
179 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700180
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700181 DEBUG ((EFI_D_VERBOSE, "Splash memory region after updating:\n"));
182 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700183error:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700184 return Status;
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700185}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800186
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700187UINT32
188fdt_check_header_ext (VOID *fdt)
Runmin Wange74d8042016-07-19 18:09:07 -0700189{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700190 UINT64 fdt_start, fdt_end;
191 UINT32 sum;
192 fdt_start = (UINT64)fdt;
Runmin Wange74d8042016-07-19 18:09:07 -0700193
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700194 if (fdt_start + fdt_totalsize (fdt) <= fdt_start) {
195 return FDT_ERR_BADOFFSET;
196 }
197 fdt_end = fdt_start + fdt_totalsize (fdt);
Runmin Wange74d8042016-07-19 18:09:07 -0700198
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700199 if (!(sum = ADD_OF (fdt_off_dt_struct (fdt), fdt_size_dt_struct (fdt)))) {
200 return FDT_ERR_BADOFFSET;
201 } else {
202 if (CHECK_ADD64 (fdt_start, sum))
203 return FDT_ERR_BADOFFSET;
204 else if (fdt_start + sum > fdt_end)
205 return FDT_ERR_BADOFFSET;
206 }
207 if (!(sum = ADD_OF (fdt_off_dt_strings (fdt), fdt_size_dt_strings (fdt)))) {
208 return FDT_ERR_BADOFFSET;
209 } else {
210 if (CHECK_ADD64 (fdt_start, sum))
211 return FDT_ERR_BADOFFSET;
212 else if (fdt_start + sum > fdt_end)
213 return FDT_ERR_BADOFFSET;
214 }
215 if (fdt_start + fdt_off_mem_rsvmap (fdt) > fdt_end)
216 return FDT_ERR_BADOFFSET;
217 return 0;
Runmin Wange74d8042016-07-19 18:09:07 -0700218}
219
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700220STATIC
221EFI_STATUS
222AddMemMap (VOID *fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800223{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700224 EFI_STATUS Status = EFI_NOT_FOUND;
225 INT32 ret = 0;
226 RamPartitionEntry *RamPartitions = NULL;
227 UINT32 NumPartitions = 0;
228 UINT32 i = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800229
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700230 Status = GetRamPartitions (&RamPartitions, &NumPartitions);
231 if (EFI_ERROR (Status)) {
232 DEBUG ((EFI_D_ERROR, "Error returned from GetRamPartitions %r\n", Status));
233 return Status;
234 }
235 if (!RamPartitions) {
236 DEBUG ((EFI_D_ERROR, "RamPartitions is NULL\n"));
237 return EFI_NOT_FOUND;
238 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800239
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700240 DEBUG ((EFI_D_INFO, "RAM Partitions\r\n"));
241 for (i = 0; i < NumPartitions; i++) {
242 DEBUG ((EFI_D_INFO, "Add Base: 0x%016lx Available Length: 0x%016lx \n",
243 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700244
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700245 if (BootWith32Bit) {
246 ret = dev_tree_add_mem_info (fdt, MemNodeOffset, RamPartitions[i].Base,
247 RamPartitions[i].AvailableLength);
248 } else {
249 ret = dev_tree_add_mem_infoV64 (fdt, MemNodeOffset, RamPartitions[i].Base,
250 RamPartitions[i].AvailableLength);
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700251 }
252
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700253 if (ret) {
254 DEBUG ((EFI_D_ERROR, "Add Base: 0x%016lx Length: 0x%016lx Fail\n",
255 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
256 }
257 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800258
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700259 FreePool (RamPartitions);
260 RamPartitions = NULL;
261
262 return EFI_SUCCESS;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800263}
264
265/* Supporting function of UpdateDeviceTree()
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700266 * Function first gets the RAM partition table, then passes the pointer to
267 * AddMemMap() */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700268STATIC
269EFI_STATUS
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700270target_dev_tree_mem (VOID *fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800271{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700272 EFI_STATUS Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800273
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700274 /* Get Available memory from partition table */
275 Status = AddMemMap (fdt, MemNodeOffset, BootWith32Bit);
276 if (EFI_ERROR (Status))
277 DEBUG ((EFI_D_ERROR,
278 "Invalid memory configuration, check memory partition table: %r\n",
279 Status));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800280
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700281 return Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800282}
283
284/* Supporting function of target_dev_tree_mem()
285 * Function to add the subsequent RAM partition info to the device tree */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700286INT32
287dev_tree_add_mem_info (VOID *fdt, UINT32 offset, UINT32 addr, UINT32 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800288{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700289 STATIC INT32 mem_info_cnt = 0;
290 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800291
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700292 if (!mem_info_cnt) {
293 /* Replace any other reg prop in the memory node. */
294 ret = fdt_setprop_u32 (fdt, offset, "reg", addr);
295 mem_info_cnt = 1;
296 } else {
297 /* Append the mem info to the reg prop for subsequent nodes. */
298 ret = fdt_appendprop_u32 (fdt, offset, "reg", addr);
299 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800300
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700301 if (ret) {
302 DEBUG (
303 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
304 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800305
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700306 ret = fdt_appendprop_u32 (fdt, offset, "reg", size);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800307
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700308 if (ret) {
309 DEBUG (
310 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
311 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800312
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700313 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800314}
315
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700316INT32
317dev_tree_add_mem_infoV64 (VOID *fdt, UINT32 offset, UINT64 addr, UINT64 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800318{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700319 STATIC INT32 mem_info_cnt = 0;
320 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800321
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700322 if (!mem_info_cnt) {
323 /* Replace any other reg prop in the memory node. */
324 ret = fdt_setprop_u64 (fdt, offset, "reg", addr);
325 mem_info_cnt = 1;
326 } else {
327 /* Append the mem info to the reg prop for subsequent nodes. */
328 ret = fdt_appendprop_u64 (fdt, offset, "reg", addr);
329 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800330
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700331 if (ret) {
332 DEBUG (
333 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
334 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800335
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700336 ret = fdt_appendprop_u64 (fdt, offset, "reg", size);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800337
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700338 if (ret) {
339 DEBUG (
340 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
341 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800342
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700343 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800344}
345
346/* Top level function that updates the device tree. */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700347EFI_STATUS
348UpdateDeviceTree (VOID *fdt,
349 CONST CHAR8 *cmdline,
350 VOID *ramdisk,
351 UINT32 RamDiskSize,
352 BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800353{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700354 INT32 ret = 0;
355 UINT32 offset;
356 UINT32 PaddSize = 0;
357 UINT64 KaslrSeed = 0;
358 EFI_STATUS Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800359
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700360 /* Check the device tree header */
361 ret = fdt_check_header (fdt) || fdt_check_header_ext (fdt);
362 if (ret) {
363 DEBUG ((EFI_D_ERROR, "ERROR: Invalid device tree header ...\n"));
364 return EFI_NOT_FOUND;
365 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800366
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700367 /* Add padding to make space for new nodes and properties. */
lijuangfd6fa912017-11-16 18:08:22 +0800368 PaddSize = ADD_OF (fdt_totalsize (fdt),
369 DTB_PAD_SIZE + AsciiStrLen (cmdline));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700370 if (!PaddSize) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530371 DEBUG ((EFI_D_ERROR, "ERROR: Integer Overflow: fdt size = %u\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700372 fdt_totalsize (fdt)));
373 return EFI_BAD_BUFFER_SIZE;
374 }
375 ret = fdt_open_into (fdt, fdt, PaddSize);
376 if (ret != 0) {
377 DEBUG ((EFI_D_ERROR, "ERROR: Failed to move/resize dtb buffer ...\n"));
378 return EFI_BAD_BUFFER_SIZE;
379 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800380
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700381 /* Get offset of the memory node */
382 ret = fdt_path_offset (fdt, "/memory");
383 if (ret < 0) {
384 DEBUG ((EFI_D_ERROR, "ERROR: Could not find memory node ...\n"));
385 return EFI_NOT_FOUND;
386 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800387
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700388 offset = ret;
389 Status = target_dev_tree_mem (fdt, offset, BootWith32Bit);
390 if (Status != EFI_SUCCESS) {
391 DEBUG ((EFI_D_ERROR, "ERROR: Cannot update memory node\n"));
392 return Status;
393 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800394
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700395 UpdateSplashMemInfo (fdt);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700396
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700397 /* Get offset of the chosen node */
398 ret = fdt_path_offset (fdt, "/chosen");
399 if (ret < 0) {
400 DEBUG ((EFI_D_ERROR, "ERROR: Could not find chosen node ...\n"));
401 return EFI_NOT_FOUND;
402 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800403
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700404 offset = ret;
405 if (cmdline) {
406 /* Adding the cmdline to the chosen node */
407 ret = fdt_appendprop_string (fdt, offset, (CONST char *)"bootargs",
408 (CONST VOID *)cmdline);
409 if (ret) {
410 DEBUG ((EFI_D_ERROR,
411 "ERROR: Cannot update chosen node [bootargs] - 0x%x\n", ret));
412 return EFI_LOAD_ERROR;
413 }
414 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800415
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700416 Status = GetKaslrSeed (&KaslrSeed);
417 if (Status == EFI_SUCCESS) {
418 /* Adding Kaslr Seed to the chosen node */
419 ret = fdt_appendprop_u64 (fdt, offset, (CONST char *)"kaslr-seed",
420 (UINT64)KaslrSeed);
421 if (ret) {
422 DEBUG ((EFI_D_INFO,
423 "ERROR: Cannot update chosen node [kaslr-seed] - 0x%x\n", ret));
424 } else {
425 DEBUG ((EFI_D_INFO, "kaslr-Seed is added to chosen node\n"));
426 }
427 } else {
428 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Kaslr Seed - %r\n", Status));
429 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800430
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700431 if (RamDiskSize) {
432 /* Adding the initrd-start to the chosen node */
433 ret = fdt_setprop_u64 (fdt, offset, "linux,initrd-start", (UINT64)ramdisk);
434 if (ret) {
435 DEBUG ((EFI_D_ERROR,
436 "ERROR: Cannot update chosen node [linux,initrd-start] - 0x%x\n",
437 ret));
438 return EFI_NOT_FOUND;
439 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800440
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700441 /* Adding the initrd-end to the chosen node */
442 ret = fdt_setprop_u64 (fdt, offset, "linux,initrd-end",
443 ((UINT64)ramdisk + RamDiskSize));
444 if (ret) {
445 DEBUG ((EFI_D_ERROR,
446 "ERROR: Cannot update chosen node [linux,initrd-end] - 0x%x\n",
447 ret));
448 return EFI_NOT_FOUND;
449 }
450 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530451
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700452 /* Update fstab node */
453 DEBUG ((EFI_D_VERBOSE, "Start DT fstab node update: %lu ms\n",
454 GetTimerCountms ()));
455 UpdateFstabNode (fdt);
456 DEBUG ((EFI_D_VERBOSE, "End DT fstab node update: %lu ms\n",
457 GetTimerCountms ()));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530458
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700459 fdt_pack (fdt);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800460
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700461 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800462}
Channagoud Kadabi9be68a72016-02-08 15:18:24 -0800463
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530464/* Update device tree for fstab node */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700465EFI_STATUS
466UpdateFstabNode (VOID *fdt)
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530467{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700468 INT32 ParentOffset = 0;
469 INT32 SubNodeOffset = 0;
470 CONST struct fdt_property *Prop = NULL;
471 INT32 PropLen = 0;
472 char *NodeName = NULL;
473 EFI_STATUS Status = EFI_SUCCESS;
474 CHAR8 *BootDevBuf = NULL;
475 CHAR8 *ReplaceStr = NULL;
476 CHAR8 *NextStr = NULL;
477 struct FstabNode Table = FstabTable;
478 UINT32 DevNodeBootDevLen = 0;
479 UINT32 Index = 0;
480 UINT32 PaddingEnd = 0;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530481
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700482 /* Find the parent node */
483 ParentOffset = fdt_path_offset (fdt, Table.ParentNode);
484 if (ParentOffset < 0) {
485 DEBUG ((EFI_D_VERBOSE, "Failed to Get parent node: fstab\terror: %d\n",
486 ParentOffset));
487 return EFI_NOT_FOUND;
488 }
489 DEBUG ((EFI_D_VERBOSE, "Node: %a found.\n",
490 fdt_get_name (fdt, ParentOffset, NULL)));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530491
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700492 /* Get boot device type */
493 BootDevBuf = AllocatePool (sizeof (CHAR8) * BOOT_DEV_MAX_LEN);
494 if (BootDevBuf == NULL) {
495 DEBUG ((EFI_D_ERROR, "Boot device buffer: Out of resources\n"));
496 return EFI_OUT_OF_RESOURCES;
497 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530498
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700499 Status = GetBootDevice (BootDevBuf, BOOT_DEV_MAX_LEN);
500 if (Status != EFI_SUCCESS) {
501 DEBUG ((EFI_D_ERROR, "Failed to get Boot Device: %r\n", Status));
502 FreePool (BootDevBuf);
503 BootDevBuf = NULL;
504 return Status;
505 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530506
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700507 /* Get properties of all sub nodes */
508 for (SubNodeOffset = fdt_first_subnode (fdt, ParentOffset);
509 SubNodeOffset >= 0;
510 SubNodeOffset = fdt_next_subnode (fdt, SubNodeOffset)) {
511 Prop = fdt_get_property (fdt, SubNodeOffset, Table.Property, &PropLen);
512 NodeName = (char *)(uintptr_t)fdt_get_name (fdt, SubNodeOffset, NULL);
513 if (!Prop) {
514 DEBUG ((EFI_D_VERBOSE, "Property:%a is not found for sub-node:%a\n",
515 Table.Property, NodeName));
516 } else {
517 DEBUG ((EFI_D_VERBOSE, "Property:%a found for sub-node:%a\tProperty:%a\n",
518 Table.Property, NodeName, Prop->data));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530519
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700520 /* Pointer to fdt 'dev' property string that needs to update based on the
521 * 'androidboot.bootdevice' */
522 ReplaceStr = (CHAR8 *)Prop->data;
523 ReplaceStr = AsciiStrStr (ReplaceStr, Table.DevicePathId);
524 if (!ReplaceStr) {
525 DEBUG ((EFI_D_VERBOSE, "Update property:%a value is not proper to "
526 "update for sub-node:%a\n",
527 Table.Property, NodeName));
528 continue;
529 }
530 ReplaceStr += AsciiStrLen (Table.DevicePathId);
531 NextStr = AsciiStrStr ((ReplaceStr + 1), "/");
532 DevNodeBootDevLen = NextStr - ReplaceStr;
533 if (DevNodeBootDevLen >= AsciiStrLen (BootDevBuf)) {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530534 gBS->CopyMem (ReplaceStr, BootDevBuf, AsciiStrLen (BootDevBuf));
535 PaddingEnd = DevNodeBootDevLen - AsciiStrLen (BootDevBuf);
536 /* Update the property with new value */
537 if (PaddingEnd) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700538 gBS->CopyMem (ReplaceStr + AsciiStrLen (BootDevBuf), NextStr,
539 AsciiStrLen (NextStr));
540 for (Index = 0; Index < PaddingEnd; Index++) {
541 ReplaceStr[AsciiStrLen (BootDevBuf) + AsciiStrLen (NextStr) +
542 Index] = ' ';
543 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530544 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700545 } else {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530546 DEBUG ((EFI_D_ERROR, "String length mismatch b/w DT Bootdevice string"
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700547 " (%d) and expected Bootdevice strings (%d)\n",
548 DevNodeBootDevLen, AsciiStrLen (BootDevBuf)));
549 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530550 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700551 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530552
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700553 FreePool (BootDevBuf);
554 BootDevBuf = NULL;
555 return Status;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530556}