blob: 11b63fc28a13172c813b7e9e3a2d579263c8f65e [file] [log] [blame]
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +05301/* Copyright (c) 2015-2020, 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>
Mayank Grover2676fa42019-04-16 18:43:03 +053037#include <Library/LocateDeviceTree.h>
Mayank Grover546377b2019-04-12 15:52:10 +053038#include <Library/BootLinux.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070039#include <Protocol/EFIChipInfoTypes.h>
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070040#include <Protocol/EFIDDRGetConfig.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070041#include <Protocol/EFIRng.h>
Parth Dixit3f4e4aa2019-05-14 17:08:46 +053042#include <Library/PartialGoods.h>
lijuangc8803a62020-02-10 15:23:51 +080043#include <Library/FdtRw.h>
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080044
Jeevan Shriram17f173d2017-10-24 22:11:07 -070045#define NUM_SPLASHMEM_PROP_ELEM 4
Mayank Groverabfc3532018-05-03 14:52:32 +053046#define DEFAULT_CELL_SIZE 2
Elliot Berman78ecae42019-10-29 09:35:08 -070047#define NUM_RNG_SEED_WORDS 512
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070048
Jeevan Shriram17f173d2017-10-24 22:11:07 -070049STATIC struct FstabNode FstabTable = {"/firmware/android/fstab", "dev",
50 "/soc/"};
Mayank Grover546377b2019-04-12 15:52:10 +053051STATIC struct FstabNode DynamicFstabTable = {"/firmware/android/fstab",
52 "status",
53 ""};
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070054STATIC struct DisplaySplashBufferInfo splashBuf;
Jeevan Shriram17f173d2017-10-24 22:11:07 -070055STATIC UINTN splashBufSize = sizeof (splashBuf);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070056
Jeevan Shriram17f173d2017-10-24 22:11:07 -070057STATIC VOID
58PrintSplashMemInfo (CONST CHAR8 *data, INT32 datalen)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070059{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070060 UINT32 i, val[NUM_SPLASHMEM_PROP_ELEM] = {0};
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070061
Jeevan Shriram17f173d2017-10-24 22:11:07 -070062 for (i = 0; (i < NUM_SPLASHMEM_PROP_ELEM) && datalen; i++) {
63 memcpy (&val[i], data, sizeof (UINT32));
64 val[i] = fdt32_to_cpu (val[i]);
65 data += sizeof (UINT32);
66 datalen -= sizeof (UINT32);
67 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070068
Jeevan Shriram17f173d2017-10-24 22:11:07 -070069 DEBUG ((EFI_D_VERBOSE, "reg = <0x%08x 0x%08x 0x%08x 0x%08x>\n", val[0],
70 val[1], val[2], val[3]));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -070071}
72
Jeevan Shriram17f173d2017-10-24 22:11:07 -070073STATIC EFI_STATUS
Mukesh Ojha7495e912020-06-22 20:40:05 +053074ValidateDdrRankChannel (struct ddr_details_entry_info *DdrInfo)
75{
76 if (DdrInfo->num_channels > MAX_CHANNELS) {
77 DEBUG ((EFI_D_ERROR, "ERROR: Number of channels is over the limit\n"));
78 return EFI_INVALID_PARAMETER;
79 }
80
81 for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
82 if (DdrInfo->num_ranks[Chan] > MAX_RANKS) {
83 DEBUG ((EFI_D_ERROR, "ERROR: Number of ranks is over the limit\n"));
84 return EFI_INVALID_PARAMETER;
85 }
86 }
87
88 return EFI_SUCCESS;
89}
90
91STATIC EFI_STATUS
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +053092GetDDRInfo (struct ddr_details_entry_info *DdrInfo,
93 UINT64 *Revision)
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070094{
95 EFI_DDRGETINFO_PROTOCOL *DdrInfoIf;
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070096 EFI_STATUS Status;
97
98 Status = gBS->LocateProtocol (&gEfiDDRGetInfoProtocolGuid, NULL,
99 (VOID **)&DdrInfoIf);
100 if (Status != EFI_SUCCESS) {
101 DEBUG ((EFI_D_VERBOSE,
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530102 "INFO: Unable to get DDR Info protocol:%r\n",
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700103 Status));
104 return Status;
105 }
106
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530107 Status = DdrInfoIf->GetDDRDetails (DdrInfoIf, DdrInfo);
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700108 if (EFI_ERROR (Status)) {
Parth Dixit489de782019-04-22 17:18:21 +0530109 DEBUG ((EFI_D_ERROR, "INFO: GetDDR details failed\n"));
110 return Status;
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700111 }
Komal Bajajdd943e02020-05-05 18:22:39 +0530112
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530113 *Revision = DdrInfoIf->Revision;
114 DEBUG ((EFI_D_VERBOSE, "DDR Header Revision =0x%x\n", *Revision));
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700115 return Status;
116}
117
118STATIC EFI_STATUS
Elliot Berman78ecae42019-10-29 09:35:08 -0700119GetRandomSeed (UINT64 *RandomSeed)
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800120{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700121 EFI_QCOM_RNG_PROTOCOL *RngIf;
122 EFI_STATUS Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800123
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700124 Status = gBS->LocateProtocol (&gQcomRngProtocolGuid, NULL, (VOID **)&RngIf);
125 if (Status != EFI_SUCCESS) {
126 DEBUG ((EFI_D_VERBOSE,
Elliot Berman78ecae42019-10-29 09:35:08 -0700127 "Error locating PRNG protocol. Fail to generate random seed:%r\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700128 Status));
129 return Status;
130 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800131
Jeevan Shriramf039efb2018-08-24 12:42:23 -0700132 Status = RngIf->GetRNG (RngIf,
133 &gEfiRNGAlgRawGuid,
134 sizeof (UINTN),
Elliot Berman78ecae42019-10-29 09:35:08 -0700135 (UINT8 *)RandomSeed);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700136 if (Status != EFI_SUCCESS) {
137 DEBUG ((EFI_D_VERBOSE,
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700138 "Error getting PRNG random number. Fail to generate Kaslr seed:%r\n",
139 Status));
Elliot Berman78ecae42019-10-29 09:35:08 -0700140 *RandomSeed = 0;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700141 return Status;
142 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800143
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700144 return Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800145}
146
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700147STATIC EFI_STATUS
148UpdateSplashMemInfo (VOID *fdt)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700149{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700150 EFI_STATUS Status;
151 CONST struct fdt_property *Prop = NULL;
152 INT32 PropLen = 0;
153 INT32 ret = 0;
154 UINT32 offset;
155 CHAR8 *tmp = NULL;
156 UINT32 CONST SplashMemPropSize = NUM_SPLASHMEM_PROP_ELEM * sizeof (UINT32);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700157
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700158 Status =
159 gRT->GetVariable ((CHAR16 *)L"DisplaySplashBufferInfo",
160 &gQcomTokenSpaceGuid, NULL, &splashBufSize, &splashBuf);
161 if (Status != EFI_SUCCESS) {
162 DEBUG ((EFI_D_ERROR, "Unable to get splash buffer info, %r\n", Status));
163 goto error;
164 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700165
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700166 DEBUG ((EFI_D_VERBOSE, "Version=%d\nAddr=0x%08x\nSize=0x%08x\n",
167 splashBuf.uVersion, splashBuf.uFrameAddr, splashBuf.uFrameSize));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700168
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700169 /* Get offset of the splash memory reservation node */
lijuangc8803a62020-02-10 15:23:51 +0800170 ret = FdtPathOffset (fdt, "/reserved-memory/splash_region");
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700171 if (ret < 0) {
172 DEBUG ((EFI_D_ERROR, "ERROR: Could not get splash memory region node\n"));
173 return EFI_NOT_FOUND;
174 }
175 offset = ret;
176 DEBUG ((EFI_D_VERBOSE, "FB mem node name: %a\n",
177 fdt_get_name (fdt, offset, NULL)));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700178
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700179 /* Get the property that specifies the splash memory details */
180 Prop = fdt_get_property (fdt, offset, "reg", &PropLen);
181 if (!Prop) {
182 DEBUG ((EFI_D_ERROR, "ERROR: Could not find the splash reg property\n"));
183 return EFI_NOT_FOUND;
184 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700185
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700186 /*
187 * The format of the "reg" field is as follows:
188 * <0x0 FBAddress 0x0 FBSize>
189 * The expected size of this property is 4 * sizeof(UINT32)
190 */
191 if (PropLen != SplashMemPropSize) {
192 DEBUG (
193 (EFI_D_ERROR,
194 "ERROR: splash mem reservation node size. Expected: %d, Actual: %d\n",
195 SplashMemPropSize, PropLen));
196 return EFI_BAD_BUFFER_SIZE;
197 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700198
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700199 DEBUG ((EFI_D_VERBOSE, "Splash memory region before updating:\n"));
200 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700201
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700202 /* First, update the FBAddress */
203 if (CHECK_ADD64 ((UINT64)Prop->data, sizeof (UINT32))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530204 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBAddress"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700205 return EFI_BAD_BUFFER_SIZE;
206 }
207 tmp = (CHAR8 *)Prop->data + sizeof (UINT32);
208 splashBuf.uFrameAddr = cpu_to_fdt32 (splashBuf.uFrameAddr);
209 memcpy (tmp, &splashBuf.uFrameAddr, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700210
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700211 /* Next, update the FBSize */
212 if (CHECK_ADD64 ((UINT64)tmp, (2 * sizeof (UINT32)))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530213 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBSize"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700214 return EFI_BAD_BUFFER_SIZE;
215 }
216 tmp += (2 * sizeof (UINT32));
217 splashBuf.uFrameSize = cpu_to_fdt32 (splashBuf.uFrameSize);
218 memcpy (tmp, &splashBuf.uFrameSize, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700219
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700220 /* Update the property value in place */
221 ret = fdt_setprop_inplace (fdt, offset, "reg", Prop->data, PropLen);
222 if (ret < 0) {
223 DEBUG ((EFI_D_ERROR, "ERROR: Could not update splash mem info\n"));
224 return EFI_NO_MAPPING;
225 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700226
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700227 DEBUG ((EFI_D_VERBOSE, "Splash memory region after updating:\n"));
228 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700229error:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700230 return Status;
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700231}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800232
Yahui Wang6e86ac52020-07-13 17:51:17 +0800233STATIC EFI_STATUS
234UpdateDemuraRegion (VOID *fdt, CONST CHAR8 *Path,
235 UINT32 HFCAddr, UINT32 HFCSize)
236{
237 EFI_STATUS Status = EFI_SUCCESS;
238 UINT32 DemuraInfoSize = 4 * sizeof (UINT32);
239 CONST struct fdt_property *Prop = NULL;
240 INT32 PropLen = 0;
241 CHAR8 *tmp = NULL;
242 INT32 ret = 0;
243 UINT32 offset = 0;
244
245 if (Path != NULL)
246 {
247 ret = FdtPathOffset (fdt, Path);
248 if (ret < 0) {
249 /* Just return success if demura node not exists */
250 return EFI_SUCCESS;
251 }
252
253 offset = (UINT32)ret;
254 Prop = fdt_get_property (fdt, offset, "reg", &PropLen);
255
256 if (!Prop) {
257 DEBUG ((EFI_D_WARN, "Could not find the demura reg property\n"));
258 Status = EFI_NOT_FOUND;
259 } else if (PropLen < DemuraInfoSize) {
260 DEBUG ((EFI_D_WARN, "Invalid demura node size\n"));
261 Status = EFI_INVALID_PARAMETER;
262 } else {
263 /* First, update the demura HFC Address */
264 tmp = (CHAR8 *)Prop->data + sizeof (UINT32);
265 HFCAddr = cpu_to_fdt32 (HFCAddr);
266 memcpy (tmp, &HFCAddr, sizeof (UINT32));
267
268 /* Next, update the demura HFC Size */
269 tmp += (2 * sizeof (UINT32));
270 HFCSize = cpu_to_fdt32 (HFCSize);
271 memcpy (tmp, &HFCSize, sizeof (UINT32));
272
273 /* Update the property value in place */
274 ret = fdt_setprop_inplace (fdt, offset, "reg", Prop->data, PropLen);
275 if (ret < 0) {
276 DEBUG ((EFI_D_WARN, "Could not update demura info\n"));
277 Status = EFI_NO_MAPPING;
278 }
279 }
280 }
281
282 return Status;
283}
284
285STATIC EFI_STATUS
286UpdateDemuraPanelID (VOID *fdt, CONST CHAR8 *Path, UINT64 PanelID)
287{
288 EFI_STATUS Status = EFI_SUCCESS;
289 UINT32 PanelIDSize = sizeof (UINT64);
290 CONST struct fdt_property *Prop = NULL;
291 INT32 PropLen = 0;
292 CHAR8 *tmp = NULL;
293 INT32 ret = 0;
294 UINT32 offset = 0;
295
296 if (Path != NULL)
297 {
298 /* Get offset of the display node */
299 ret = FdtPathOffset (fdt, Path);
300 if (ret < 0) {
301 /* Just return success if display node not exists */
302 return EFI_SUCCESS;
303 }
304
305 offset = (UINT32)ret;
306 Prop = fdt_get_property (fdt, offset, "qcom,demura-panel-id", &PropLen);
307
308 if (!Prop) {
309 DEBUG ((EFI_D_WARN, "Could not find the panel id property\n"));
310 Status = EFI_NOT_FOUND;
311 } else if (PropLen < PanelIDSize) {
312 DEBUG ((EFI_D_WARN, "Invalid panel ID size\n"));
313 Status = EFI_INVALID_PARAMETER;
314 } else {
315 /* Update panel id */
316 tmp = (CHAR8 *)Prop->data;
317 PanelID = fdt64_to_cpu (PanelID);
318 memcpy (tmp, &PanelID, sizeof (UINT64));
319
320 /* Update the property value in place */
321 ret = fdt_setprop_inplace (fdt,
322 offset,
323 "qcom,demura-panel-id",
324 Prop->data,
325 PropLen);
326 if (ret < 0) {
327 DEBUG ((EFI_D_WARN, "Could not update demura panel id\n"));
328 Status = EFI_NO_MAPPING;
329 }
330 }
331 }
332
333 return Status;
334}
335
336STATIC EFI_STATUS
337UpdateDemuraInfo (VOID *fdt)
338{
339 EFI_STATUS Status = EFI_SUCCESS;
340 struct DisplayDemuraInfoType DemuraInfo;
341 UINTN DemuraInfoSize = sizeof (DemuraInfo);
342
343 memset (&DemuraInfo, 0, DemuraInfoSize);
344
345 Status = gRT->GetVariable ((CHAR16 *)L"DisplayDemuraInfo",
346 &gQcomTokenSpaceGuid,
347 NULL,
348 &DemuraInfoSize,
349 &DemuraInfo);
350 if ((Status == EFI_SUCCESS) &&
351 (DemuraInfo.Version > 0)) {
352 /* Update demura 0 region */
353 if ((DemuraInfo.Demura0HFCAddr != 0) &&
354 (DemuraInfo.Demura0HFCSize != 0)) {
355 UpdateDemuraRegion(fdt,
356 "/reserved-memory/demura_region_0",
357 DemuraInfo.Demura0HFCAddr,
358 DemuraInfo.Demura0HFCSize);
359 }
360
361 /* Update demura 1 region */
362 if ((DemuraInfo.Demura1HFCAddr != 0) &&
363 (DemuraInfo.Demura1HFCSize != 0)) {
364 UpdateDemuraRegion(fdt,
365 "/reserved-memory/demura_region_1",
366 DemuraInfo.Demura1HFCAddr,
367 DemuraInfo.Demura1HFCSize);
368 }
369
370 /* Update demura 0 panel id */
371 if (DemuraInfo.Demura0PanelID != 0) {
372 UpdateDemuraPanelID(fdt,
373 "/soc/qcom,dsi-display-primary",
374 DemuraInfo.Demura0PanelID);
375 }
376
377 /* Update demura 1 panel id */
378 if (DemuraInfo.Demura1PanelID != 0) {
379
380 UpdateDemuraPanelID(fdt,
381 "/soc/qcom,dsi-display-secondary",
382 DemuraInfo.Demura1PanelID);
383 }
384 }
385
386 return Status;
387}
388
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700389UINT32
390fdt_check_header_ext (VOID *fdt)
Runmin Wange74d8042016-07-19 18:09:07 -0700391{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700392 UINT64 fdt_start, fdt_end;
393 UINT32 sum;
394 fdt_start = (UINT64)fdt;
Runmin Wange74d8042016-07-19 18:09:07 -0700395
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700396 if (fdt_start + fdt_totalsize (fdt) <= fdt_start) {
397 return FDT_ERR_BADOFFSET;
398 }
399 fdt_end = fdt_start + fdt_totalsize (fdt);
Runmin Wange74d8042016-07-19 18:09:07 -0700400
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700401 if (!(sum = ADD_OF (fdt_off_dt_struct (fdt), fdt_size_dt_struct (fdt)))) {
402 return FDT_ERR_BADOFFSET;
403 } else {
404 if (CHECK_ADD64 (fdt_start, sum))
405 return FDT_ERR_BADOFFSET;
406 else if (fdt_start + sum > fdt_end)
407 return FDT_ERR_BADOFFSET;
408 }
409 if (!(sum = ADD_OF (fdt_off_dt_strings (fdt), fdt_size_dt_strings (fdt)))) {
410 return FDT_ERR_BADOFFSET;
411 } else {
412 if (CHECK_ADD64 (fdt_start, sum))
413 return FDT_ERR_BADOFFSET;
414 else if (fdt_start + sum > fdt_end)
415 return FDT_ERR_BADOFFSET;
416 }
417 if (fdt_start + fdt_off_mem_rsvmap (fdt) > fdt_end)
418 return FDT_ERR_BADOFFSET;
419 return 0;
Runmin Wange74d8042016-07-19 18:09:07 -0700420}
421
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700422STATIC
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700423VOID
424UpdateGranuleInfo (VOID *fdt)
425{
426 EFI_STATUS Status = EFI_SUCCESS;
Bhanuprakash Modem7ee03122018-06-12 19:47:36 +0530427 INT32 GranuleNodeOffset;
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700428 UINT32 GranuleSize;
429 INT32 Ret;
430
Parth Dixitfc028d92019-04-22 15:55:46 +0530431 Status = GetGranuleSize (&GranuleSize);
432 if (EFI_ERROR (Status)) {
433 DEBUG ((EFI_D_VERBOSE,
434 "Unable to get Granule Size, Status = %r\r\n",
435 Status));
Bhanuprakash Modem7ee03122018-06-12 19:47:36 +0530436 return;
437 }
438
lijuangc8803a62020-02-10 15:23:51 +0800439 GranuleNodeOffset = FdtPathOffset (fdt, "/mem-offline");
Parth Dixitfc028d92019-04-22 15:55:46 +0530440 if (GranuleNodeOffset < 0) {
441 DEBUG ((EFI_D_VERBOSE, "INFO: Could not find mem-offline node.\n"));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700442 return;
443 }
444
lijuangc8803a62020-02-10 15:23:51 +0800445 FdtPropUpdateFunc (fdt, GranuleNodeOffset, "granule",
446 GranuleSize, fdt_setprop_u32, Ret);
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700447 if (Ret) {
Parth Dixitfc028d92019-04-22 15:55:46 +0530448 DEBUG ((EFI_D_ERROR, "INFO: Granule size update failed.\n"));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700449 }
450}
451
452STATIC
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700453EFI_STATUS
Mayank Groverabfc3532018-05-03 14:52:32 +0530454QueryMemoryCellSize (IN VOID *Fdt, OUT UINT32 *MemoryCellLen)
455{
456 INT32 RootOffset;
457 INT32 PropLen;
458 UINT32 AddrCellSize = 0;
459 UINT32 SizeCellSize = 0;
460 UINT32 *Prop = NULL;
461
462 RootOffset = fdt_path_offset (Fdt, "/");
463 if (RootOffset < 0) {
464 DEBUG ((EFI_D_ERROR, "Error finding root offset\n"));
465 return EFI_NOT_FOUND;
466 }
467
468 /* Find address-cells size */
469 Prop = (UINT32 *) fdt_getprop (Fdt, RootOffset, "#address-cells", &PropLen);
470 if (Prop &&
471 PropLen > 0) {
472 AddrCellSize = fdt32_to_cpu (*Prop);
473 } else {
474 DEBUG ((EFI_D_ERROR, "Error finding #address-cells property\n"));
475 return EFI_NOT_FOUND;
476 }
477
478 /* Find size-cells size */
479 Prop =(UINT32 *) fdt_getprop (Fdt, RootOffset, "#size-cells", &PropLen);
480 if (Prop &&
481 PropLen > 0) {
482 SizeCellSize = fdt32_to_cpu (*Prop);
483 } else {
484 DEBUG ((EFI_D_ERROR, "Error finding #size-cells property\n"));
485 return EFI_NOT_FOUND;
486 }
487
488 if (AddrCellSize > DEFAULT_CELL_SIZE ||
489 SizeCellSize > DEFAULT_CELL_SIZE ||
490 SizeCellSize == 0 ||
491 AddrCellSize == 0) {
492 DEBUG ((EFI_D_ERROR, "Error unsupported cell size value: #address-cell %d" \
493 "#size-cell\n", AddrCellSize, SizeCellSize));
494 return EFI_INVALID_PARAMETER;
495 }
496
497 /* Make sure memory cell size and address cell size are same */
498 if (AddrCellSize == SizeCellSize) {
499 *MemoryCellLen = AddrCellSize;
500 } else {
501 DEBUG ((EFI_D_ERROR, "Mismatch memory address cell and size cell size\n"));
502 return EFI_INVALID_PARAMETER;
503 }
504
505 return EFI_SUCCESS;
506}
507
508STATIC
509EFI_STATUS
510AddMemMap (VOID *Fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800511{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700512 EFI_STATUS Status = EFI_NOT_FOUND;
513 INT32 ret = 0;
514 RamPartitionEntry *RamPartitions = NULL;
515 UINT32 NumPartitions = 0;
516 UINT32 i = 0;
Mayank Groverabfc3532018-05-03 14:52:32 +0530517 UINT32 MemoryCellLen = 0;
518
519 Status = QueryMemoryCellSize (Fdt, &MemoryCellLen);
520 if (EFI_ERROR (Status)) {
521 DEBUG ((EFI_D_ERROR, "ERROR: Not a valid memory node found!\n"));
522 return Status;
523 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800524
Chandra Sai Chidipudiecc62632020-01-24 15:20:50 +0530525 Status = ReadRamPartitions (&RamPartitions, &NumPartitions);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700526 if (EFI_ERROR (Status)) {
Chandra Sai Chidipudiecc62632020-01-24 15:20:50 +0530527 DEBUG ((EFI_D_ERROR, "Error returned from ReadRamPartitions %r\n", Status));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700528 return Status;
529 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800530
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700531 DEBUG ((EFI_D_INFO, "RAM Partitions\r\n"));
532 for (i = 0; i < NumPartitions; i++) {
533 DEBUG ((EFI_D_INFO, "Add Base: 0x%016lx Available Length: 0x%016lx \n",
534 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700535
Mayank Groverabfc3532018-05-03 14:52:32 +0530536 if (MemoryCellLen == 1) {
537 ret = dev_tree_add_mem_info (Fdt, MemNodeOffset, RamPartitions[i].Base,
538 RamPartitions[i].AvailableLength);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700539 } else {
Mayank Groverabfc3532018-05-03 14:52:32 +0530540 ret = dev_tree_add_mem_infoV64 (Fdt, MemNodeOffset,
541 RamPartitions[i].Base,
542 RamPartitions[i].AvailableLength);
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700543 }
544
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700545 if (ret) {
546 DEBUG ((EFI_D_ERROR, "Add Base: 0x%016lx Length: 0x%016lx Fail\n",
547 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
548 }
549 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800550
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700551 FreePool (RamPartitions);
552 RamPartitions = NULL;
Chandra Sai Chidipudiecc62632020-01-24 15:20:50 +0530553 RamPartitionEntries = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700554
555 return EFI_SUCCESS;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800556}
557
558/* Supporting function of UpdateDeviceTree()
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700559 * Function first gets the RAM partition table, then passes the pointer to
560 * AddMemMap() */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700561STATIC
562EFI_STATUS
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700563target_dev_tree_mem (VOID *fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800564{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700565 EFI_STATUS Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800566
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700567 /* Get Available memory from partition table */
568 Status = AddMemMap (fdt, MemNodeOffset, BootWith32Bit);
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700569 if (EFI_ERROR (Status)) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700570 DEBUG ((EFI_D_ERROR,
571 "Invalid memory configuration, check memory partition table: %r\n",
572 Status));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700573 goto out;
574 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800575
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700576 UpdateGranuleInfo (fdt);
577
578out:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700579 return Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800580}
581
582/* Supporting function of target_dev_tree_mem()
583 * Function to add the subsequent RAM partition info to the device tree */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700584INT32
585dev_tree_add_mem_info (VOID *fdt, UINT32 offset, UINT32 addr, UINT32 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800586{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700587 STATIC INT32 mem_info_cnt = 0;
588 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800589
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700590 if (!mem_info_cnt) {
591 /* Replace any other reg prop in the memory node. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700592 mem_info_cnt = 1;
lijuangc8803a62020-02-10 15:23:51 +0800593 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_setprop_u32, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700594 } else {
595 /* Append the mem info to the reg prop for subsequent nodes. */
lijuangc8803a62020-02-10 15:23:51 +0800596 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_appendprop_u32, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700597 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800598
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700599 if (ret) {
600 DEBUG (
601 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
602 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800603
lijuangc8803a62020-02-10 15:23:51 +0800604 FdtPropUpdateFunc (fdt, offset, "reg", size, fdt_appendprop_u32, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700605 if (ret) {
606 DEBUG (
607 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
608 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800609
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700610 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800611}
612
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700613INT32
614dev_tree_add_mem_infoV64 (VOID *fdt, UINT32 offset, UINT64 addr, UINT64 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800615{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700616 STATIC INT32 mem_info_cnt = 0;
617 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800618
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700619 if (!mem_info_cnt) {
620 /* Replace any other reg prop in the memory node. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700621 mem_info_cnt = 1;
lijuangc8803a62020-02-10 15:23:51 +0800622 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_setprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700623 } else {
624 /* Append the mem info to the reg prop for subsequent nodes. */
lijuangc8803a62020-02-10 15:23:51 +0800625 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_appendprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700626 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800627
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700628 if (ret) {
629 DEBUG (
630 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
631 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800632
lijuangc8803a62020-02-10 15:23:51 +0800633 FdtPropUpdateFunc (fdt, offset, "reg", size, fdt_appendprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700634 if (ret) {
635 DEBUG (
636 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
637 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800638
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700639 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800640}
641
642/* Top level function that updates the device tree. */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700643EFI_STATUS
644UpdateDeviceTree (VOID *fdt,
645 CONST CHAR8 *cmdline,
646 VOID *ramdisk,
647 UINT32 RamDiskSize,
648 BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800649{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700650 INT32 ret = 0;
651 UINT32 offset;
652 UINT32 PaddSize = 0;
Elliot Berman78ecae42019-10-29 09:35:08 -0700653 UINT64 RandomSeed = 0;
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700654 UINT8 DdrDeviceType;
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530655 /* Single space reserved for chan(0-9) */
656 CHAR8 FdtRankProp[] = "ddr_device_rank_ch ";
657 /* Single spaces reserved for chan(0-9), rank(0-9) */
658 CHAR8 FdtHbbProp[] = "ddr_device_hbb_ch _rank ";
659 struct ddr_details_entry_info *DdrInfo;
660 UINT64 Revision;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700661 EFI_STATUS Status;
lijuang768a4452019-09-24 18:37:42 +0800662 UINT64 UpdateDTStartTime = GetTimerCountms ();
Elliot Berman78ecae42019-10-29 09:35:08 -0700663 UINT32 Index;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800664
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700665 /* Check the device tree header */
666 ret = fdt_check_header (fdt) || fdt_check_header_ext (fdt);
667 if (ret) {
668 DEBUG ((EFI_D_ERROR, "ERROR: Invalid device tree header ...\n"));
669 return EFI_NOT_FOUND;
670 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800671
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700672 /* Add padding to make space for new nodes and properties. */
lijuangfd6fa912017-11-16 18:08:22 +0800673 PaddSize = ADD_OF (fdt_totalsize (fdt),
674 DTB_PAD_SIZE + AsciiStrLen (cmdline));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700675 if (!PaddSize) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530676 DEBUG ((EFI_D_ERROR, "ERROR: Integer Overflow: fdt size = %u\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700677 fdt_totalsize (fdt)));
678 return EFI_BAD_BUFFER_SIZE;
679 }
680 ret = fdt_open_into (fdt, fdt, PaddSize);
681 if (ret != 0) {
682 DEBUG ((EFI_D_ERROR, "ERROR: Failed to move/resize dtb buffer ...\n"));
683 return EFI_BAD_BUFFER_SIZE;
684 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800685
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700686 /* Get offset of the memory node */
lijuangc8803a62020-02-10 15:23:51 +0800687 ret = FdtPathOffset (fdt, "/memory");
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700688 if (ret < 0) {
689 DEBUG ((EFI_D_ERROR, "ERROR: Could not find memory node ...\n"));
690 return EFI_NOT_FOUND;
691 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800692
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700693 offset = ret;
694 Status = target_dev_tree_mem (fdt, offset, BootWith32Bit);
695 if (Status != EFI_SUCCESS) {
696 DEBUG ((EFI_D_ERROR, "ERROR: Cannot update memory node\n"));
697 return Status;
698 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800699
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530700 DdrInfo = AllocateZeroPool (sizeof (struct ddr_details_entry_info));
701 if (DdrInfo == NULL) {
702 DEBUG ((EFI_D_ERROR, "DDR Info Buffer: Out of resources\n"));
703 return EFI_OUT_OF_RESOURCES;
704 }
705 Status = GetDDRInfo (DdrInfo, &Revision);
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700706 if (Status == EFI_SUCCESS) {
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530707 DdrDeviceType = DdrInfo->device_type;
708 DEBUG ((EFI_D_VERBOSE, "DDR deviceType:%d\n", DdrDeviceType));
709
lijuangc8803a62020-02-10 15:23:51 +0800710 FdtPropUpdateFunc (fdt, offset, (CONST char *)"ddr_device_type",
711 (UINT32)DdrDeviceType, fdt_appendprop_u32, ret);
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700712 if (ret) {
713 DEBUG ((EFI_D_ERROR,
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530714 "ERROR: Cannot update memory node [ddr_device_type]:0x%x\n",
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700715 ret));
716 } else {
717 DEBUG ((EFI_D_VERBOSE, "ddr_device_type is added to memory node\n"));
718 }
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530719
720 if (Revision < EFI_DDRGETINFO_PROTOCOL_REVISION) {
721 DEBUG ((EFI_D_VERBOSE,
722 "ddr_device_rank, HBB not supported in Revision=0x%x\n",
723 Revision));
724 } else {
Mukesh Ojha7495e912020-06-22 20:40:05 +0530725 Status = ValidateDdrRankChannel (DdrInfo);
726 if (Status != EFI_SUCCESS) {
727 goto OutofUpdateRankChannel;
728 }
729
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530730 DEBUG ((EFI_D_VERBOSE, "DdrInfo->num_channels:%d\n",
731 DdrInfo->num_channels));
732 for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
733 DEBUG ((EFI_D_VERBOSE, "ddr_device_rank_ch%d:%d\n",
734 Chan, DdrInfo->num_ranks[Chan]));
735 AsciiSPrint (FdtRankProp, sizeof (FdtRankProp),
736 "ddr_device_rank_ch%d", Chan);
lijuangc8803a62020-02-10 15:23:51 +0800737 FdtPropUpdateFunc (fdt, offset, (CONST char *)FdtRankProp,
738 (UINT32)DdrInfo->num_ranks[Chan],
739 fdt_appendprop_u32, ret);
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530740 if (ret) {
741 DEBUG ((EFI_D_ERROR,
742 "ERROR: Cannot update memory node ddr_device_rank_ch%d:0x%x\n",
743 Chan, ret));
744 } else {
745 DEBUG ((EFI_D_VERBOSE, "ddr_device_rank_ch%d added to memory node\n",
746 Chan));
747 }
748 for (UINT8 Rank = 0; Rank < DdrInfo->num_ranks[Chan]; Rank++) {
749 DEBUG ((EFI_D_VERBOSE, "ddr_device_hbb_ch%d_rank%d:%d\n",
750 Chan, Rank, DdrInfo->hbb[Chan][Rank]));
751 AsciiSPrint (FdtHbbProp, sizeof (FdtHbbProp),
752 "ddr_device_hbb_ch%d_rank%d", Chan, Rank);
lijuangc8803a62020-02-10 15:23:51 +0800753 FdtPropUpdateFunc (fdt, offset, (CONST char *)FdtHbbProp,
754 (UINT32)DdrInfo->hbb[Chan][Rank],
755 fdt_appendprop_u32, ret);
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530756 if (ret) {
757 DEBUG ((EFI_D_ERROR,
758 "ERROR: Cannot update memory node ddr_device_hbb_ch%d_rank%d:0x%x\n",
759 Chan, Rank, ret));
760 } else {
761 DEBUG ((EFI_D_VERBOSE,
762 "ddr_device_hbb_ch%d_rank%d added to memory node\n",
763 Chan, Rank));
764 }
765 }
766 }
767 }
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700768 }
769
Mukesh Ojha7495e912020-06-22 20:40:05 +0530770OutofUpdateRankChannel:
771
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700772 UpdateSplashMemInfo (fdt);
Yahui Wang6e86ac52020-07-13 17:51:17 +0800773 UpdateDemuraInfo (fdt);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700774
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700775 /* Get offset of the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800776 ret = FdtPathOffset (fdt, "/chosen");
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700777 if (ret < 0) {
778 DEBUG ((EFI_D_ERROR, "ERROR: Could not find chosen node ...\n"));
779 return EFI_NOT_FOUND;
780 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800781
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700782 offset = ret;
783 if (cmdline) {
784 /* Adding the cmdline to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800785 FdtPropUpdateFunc (fdt, offset, (CONST char *)"bootargs",
786 (CONST VOID *)cmdline, fdt_appendprop_string, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700787 if (ret) {
788 DEBUG ((EFI_D_ERROR,
789 "ERROR: Cannot update chosen node [bootargs] - 0x%x\n", ret));
790 return EFI_LOAD_ERROR;
791 }
792 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800793
Elliot Berman78ecae42019-10-29 09:35:08 -0700794 for (Index = 0; Index < NUM_RNG_SEED_WORDS / sizeof (UINT64); Index++) {
795 Status = GetRandomSeed (&RandomSeed);
796 if (Status == EFI_SUCCESS) {
797
798 /* Adding the RNG seed to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800799 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"rng-seed",
800 (UINT64)RandomSeed, fdt_appendprop_u64, ret);
Elliot Berman78ecae42019-10-29 09:35:08 -0700801 if (ret) {
802 DEBUG ((EFI_D_ERROR,
803 "ERROR: Cannot update chosen node [rng-seed] - 0x%x\n", ret));
804 break;
805 }
806 } else {
807 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Random Seed - %r\n", Status));
808 break;
809 }
810 }
811
812 Status = GetRandomSeed (&RandomSeed);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700813 if (Status == EFI_SUCCESS) {
814 /* Adding Kaslr Seed to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800815 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"kaslr-seed",
816 (UINT64)RandomSeed, fdt_appendprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700817 if (ret) {
818 DEBUG ((EFI_D_INFO,
819 "ERROR: Cannot update chosen node [kaslr-seed] - 0x%x\n", ret));
820 } else {
lijuangf2eb1fa2019-09-23 14:10:20 +0800821 DEBUG ((EFI_D_VERBOSE, "kaslr-Seed is added to chosen node\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700822 }
823 } else {
824 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Kaslr Seed - %r\n", Status));
825 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800826
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700827 if (RamDiskSize) {
828 /* Adding the initrd-start to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800829 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"linux,initrd-start",
830 (UINT64)ramdisk, fdt_setprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700831 if (ret) {
832 DEBUG ((EFI_D_ERROR,
833 "ERROR: Cannot update chosen node [linux,initrd-start] - 0x%x\n",
834 ret));
835 return EFI_NOT_FOUND;
836 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800837
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700838 /* Adding the initrd-end to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800839 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"linux,initrd-end",
840 (UINT64)ramdisk + RamDiskSize, fdt_setprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700841 if (ret) {
842 DEBUG ((EFI_D_ERROR,
843 "ERROR: Cannot update chosen node [linux,initrd-end] - 0x%x\n",
844 ret));
845 return EFI_NOT_FOUND;
846 }
847 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530848
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700849 /* Update fstab node */
850 DEBUG ((EFI_D_VERBOSE, "Start DT fstab node update: %lu ms\n",
851 GetTimerCountms ()));
852 UpdateFstabNode (fdt);
853 DEBUG ((EFI_D_VERBOSE, "End DT fstab node update: %lu ms\n",
854 GetTimerCountms ()));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530855
Parth Dixit3f4e4aa2019-05-14 17:08:46 +0530856 /* Check partial goods*/
857 if (FixedPcdGetBool (EnablePartialGoods)) {
858 ret = UpdatePartialGoodsNode (fdt);
859 if (ret != EFI_SUCCESS) {
860 DEBUG ((EFI_D_ERROR,
861 "Failed to update device tree for partial goods, Status=%r\n",
862 ret));
863 return ret;
864 }
865 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700866 fdt_pack (fdt);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800867
lijuang768a4452019-09-24 18:37:42 +0800868 DEBUG ((EFI_D_INFO, "Update Device Tree total time: %lu ms \n",
869 GetTimerCountms () - UpdateDTStartTime));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700870 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800871}
Channagoud Kadabi9be68a72016-02-08 15:18:24 -0800872
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530873/* Update device tree for fstab node */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700874EFI_STATUS
875UpdateFstabNode (VOID *fdt)
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530876{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700877 INT32 ParentOffset = 0;
878 INT32 SubNodeOffset = 0;
879 CONST struct fdt_property *Prop = NULL;
880 INT32 PropLen = 0;
881 char *NodeName = NULL;
882 EFI_STATUS Status = EFI_SUCCESS;
883 CHAR8 *BootDevBuf = NULL;
884 CHAR8 *ReplaceStr = NULL;
885 CHAR8 *NextStr = NULL;
Mayank Grover546377b2019-04-12 15:52:10 +0530886 struct FstabNode Table = IsDynamicPartitionSupport () ? DynamicFstabTable
887 : FstabTable;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700888 UINT32 DevNodeBootDevLen = 0;
889 UINT32 Index = 0;
890 UINT32 PaddingEnd = 0;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530891
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700892 /* Find the parent node */
lijuangc8803a62020-02-10 15:23:51 +0800893 ParentOffset = FdtPathOffset (fdt, Table.ParentNode);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700894 if (ParentOffset < 0) {
895 DEBUG ((EFI_D_VERBOSE, "Failed to Get parent node: fstab\terror: %d\n",
896 ParentOffset));
897 return EFI_NOT_FOUND;
898 }
899 DEBUG ((EFI_D_VERBOSE, "Node: %a found.\n",
900 fdt_get_name (fdt, ParentOffset, NULL)));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530901
Mayank Grover546377b2019-04-12 15:52:10 +0530902 if (!IsDynamicPartitionSupport ()) {
903 /* Get boot device type */
904 BootDevBuf = AllocateZeroPool (sizeof (CHAR8) * BOOT_DEV_MAX_LEN);
905 if (BootDevBuf == NULL) {
906 DEBUG ((EFI_D_ERROR, "Boot device buffer: Out of resources\n"));
907 return EFI_OUT_OF_RESOURCES;
908 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530909
Mayank Grover546377b2019-04-12 15:52:10 +0530910 Status = GetBootDevice (BootDevBuf, BOOT_DEV_MAX_LEN);
911 if (Status != EFI_SUCCESS) {
912 DEBUG ((EFI_D_ERROR, "Failed to get Boot Device: %r\n", Status));
913 FreePool (BootDevBuf);
914 BootDevBuf = NULL;
915 return Status;
916 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700917 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530918
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700919 /* Get properties of all sub nodes */
920 for (SubNodeOffset = fdt_first_subnode (fdt, ParentOffset);
921 SubNodeOffset >= 0;
922 SubNodeOffset = fdt_next_subnode (fdt, SubNodeOffset)) {
923 Prop = fdt_get_property (fdt, SubNodeOffset, Table.Property, &PropLen);
924 NodeName = (char *)(uintptr_t)fdt_get_name (fdt, SubNodeOffset, NULL);
925 if (!Prop) {
926 DEBUG ((EFI_D_VERBOSE, "Property:%a is not found for sub-node:%a\n",
927 Table.Property, NodeName));
928 } else {
929 DEBUG ((EFI_D_VERBOSE, "Property:%a found for sub-node:%a\tProperty:%a\n",
930 Table.Property, NodeName, Prop->data));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530931
Mayank Grover546377b2019-04-12 15:52:10 +0530932 /* For Dynamic partition support disable firmware fstab nodes. */
933 if (IsDynamicPartitionSupport ()) {
934 DEBUG ((EFI_D_VERBOSE, "Disabling node status :%a\n", NodeName));
lijuangc8803a62020-02-10 15:23:51 +0800935 Status = FdtSetProp (fdt, SubNodeOffset, Table.Property,
936 (CONST VOID *)"disabled",
937 (AsciiStrLen ("disabled") + 1));
Mayank Grover546377b2019-04-12 15:52:10 +0530938 if (Status) {
939 DEBUG ((EFI_D_ERROR, "ERROR: Failed to disable Node: %a\n", NodeName));
940 }
941 continue;
942 }
943
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700944 /* Pointer to fdt 'dev' property string that needs to update based on the
945 * 'androidboot.bootdevice' */
946 ReplaceStr = (CHAR8 *)Prop->data;
947 ReplaceStr = AsciiStrStr (ReplaceStr, Table.DevicePathId);
948 if (!ReplaceStr) {
949 DEBUG ((EFI_D_VERBOSE, "Update property:%a value is not proper to "
950 "update for sub-node:%a\n",
951 Table.Property, NodeName));
952 continue;
953 }
954 ReplaceStr += AsciiStrLen (Table.DevicePathId);
955 NextStr = AsciiStrStr ((ReplaceStr + 1), "/");
956 DevNodeBootDevLen = NextStr - ReplaceStr;
957 if (DevNodeBootDevLen >= AsciiStrLen (BootDevBuf)) {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530958 gBS->CopyMem (ReplaceStr, BootDevBuf, AsciiStrLen (BootDevBuf));
959 PaddingEnd = DevNodeBootDevLen - AsciiStrLen (BootDevBuf);
960 /* Update the property with new value */
961 if (PaddingEnd) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700962 gBS->CopyMem (ReplaceStr + AsciiStrLen (BootDevBuf), NextStr,
963 AsciiStrLen (NextStr));
964 for (Index = 0; Index < PaddingEnd; Index++) {
965 ReplaceStr[AsciiStrLen (BootDevBuf) + AsciiStrLen (NextStr) +
966 Index] = ' ';
967 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530968 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700969 } else {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530970 DEBUG ((EFI_D_ERROR, "String length mismatch b/w DT Bootdevice string"
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700971 " (%d) and expected Bootdevice strings (%d)\n",
972 DevNodeBootDevLen, AsciiStrLen (BootDevBuf)));
973 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530974 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700975 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530976
Mayank Grover546377b2019-04-12 15:52:10 +0530977 if (BootDevBuf) {
978 FreePool (BootDevBuf);
979 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700980 BootDevBuf = NULL;
981 return Status;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530982}