blob: cf2ca6fb2dc848604d6ccf9745d8013ba26c3a8c [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
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +053074GetDDRInfo (struct ddr_details_entry_info *DdrInfo,
75 UINT64 *Revision)
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070076{
77 EFI_DDRGETINFO_PROTOCOL *DdrInfoIf;
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070078 EFI_STATUS Status;
79
80 Status = gBS->LocateProtocol (&gEfiDDRGetInfoProtocolGuid, NULL,
81 (VOID **)&DdrInfoIf);
82 if (Status != EFI_SUCCESS) {
83 DEBUG ((EFI_D_VERBOSE,
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +053084 "INFO: Unable to get DDR Info protocol:%r\n",
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070085 Status));
86 return Status;
87 }
88
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +053089 Status = DdrInfoIf->GetDDRDetails (DdrInfoIf, DdrInfo);
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070090 if (EFI_ERROR (Status)) {
Parth Dixit489de782019-04-22 17:18:21 +053091 DEBUG ((EFI_D_ERROR, "INFO: GetDDR details failed\n"));
92 return Status;
Jeevan Shriramf8fa2912018-11-02 13:16:47 -070093 }
Komal Bajajdd943e02020-05-05 18:22:39 +053094
95 if (DdrInfo->num_channels > MAX_CHANNELS) {
96 DEBUG ((EFI_D_ERROR, "ERROR: Number of channels is over the limit\n"));
97 return EFI_INVALID_PARAMETER;
98 }
99
100 for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
101 if (DdrInfo->num_ranks[Chan] > MAX_RANKS) {
102 DEBUG ((EFI_D_ERROR, "ERROR: Number of ranks is over the limit\n"));
103 return EFI_INVALID_PARAMETER;
104 }
105 }
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530106 *Revision = DdrInfoIf->Revision;
107 DEBUG ((EFI_D_VERBOSE, "DDR Header Revision =0x%x\n", *Revision));
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700108 return Status;
109}
110
111STATIC EFI_STATUS
Elliot Berman78ecae42019-10-29 09:35:08 -0700112GetRandomSeed (UINT64 *RandomSeed)
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800113{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700114 EFI_QCOM_RNG_PROTOCOL *RngIf;
115 EFI_STATUS Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800116
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700117 Status = gBS->LocateProtocol (&gQcomRngProtocolGuid, NULL, (VOID **)&RngIf);
118 if (Status != EFI_SUCCESS) {
119 DEBUG ((EFI_D_VERBOSE,
Elliot Berman78ecae42019-10-29 09:35:08 -0700120 "Error locating PRNG protocol. Fail to generate random seed:%r\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700121 Status));
122 return Status;
123 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800124
Jeevan Shriramf039efb2018-08-24 12:42:23 -0700125 Status = RngIf->GetRNG (RngIf,
126 &gEfiRNGAlgRawGuid,
127 sizeof (UINTN),
Elliot Berman78ecae42019-10-29 09:35:08 -0700128 (UINT8 *)RandomSeed);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700129 if (Status != EFI_SUCCESS) {
130 DEBUG ((EFI_D_VERBOSE,
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700131 "Error getting PRNG random number. Fail to generate Kaslr seed:%r\n",
132 Status));
Elliot Berman78ecae42019-10-29 09:35:08 -0700133 *RandomSeed = 0;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700134 return Status;
135 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800136
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700137 return Status;
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800138}
139
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700140STATIC EFI_STATUS
141UpdateSplashMemInfo (VOID *fdt)
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700142{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700143 EFI_STATUS Status;
144 CONST struct fdt_property *Prop = NULL;
145 INT32 PropLen = 0;
146 INT32 ret = 0;
147 UINT32 offset;
148 CHAR8 *tmp = NULL;
149 UINT32 CONST SplashMemPropSize = NUM_SPLASHMEM_PROP_ELEM * sizeof (UINT32);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700150
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700151 Status =
152 gRT->GetVariable ((CHAR16 *)L"DisplaySplashBufferInfo",
153 &gQcomTokenSpaceGuid, NULL, &splashBufSize, &splashBuf);
154 if (Status != EFI_SUCCESS) {
155 DEBUG ((EFI_D_ERROR, "Unable to get splash buffer info, %r\n", Status));
156 goto error;
157 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700158
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700159 DEBUG ((EFI_D_VERBOSE, "Version=%d\nAddr=0x%08x\nSize=0x%08x\n",
160 splashBuf.uVersion, splashBuf.uFrameAddr, splashBuf.uFrameSize));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700161
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700162 /* Get offset of the splash memory reservation node */
lijuangc8803a62020-02-10 15:23:51 +0800163 ret = FdtPathOffset (fdt, "/reserved-memory/splash_region");
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700164 if (ret < 0) {
165 DEBUG ((EFI_D_ERROR, "ERROR: Could not get splash memory region node\n"));
166 return EFI_NOT_FOUND;
167 }
168 offset = ret;
169 DEBUG ((EFI_D_VERBOSE, "FB mem node name: %a\n",
170 fdt_get_name (fdt, offset, NULL)));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700171
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700172 /* Get the property that specifies the splash memory details */
173 Prop = fdt_get_property (fdt, offset, "reg", &PropLen);
174 if (!Prop) {
175 DEBUG ((EFI_D_ERROR, "ERROR: Could not find the splash reg property\n"));
176 return EFI_NOT_FOUND;
177 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700178
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700179 /*
180 * The format of the "reg" field is as follows:
181 * <0x0 FBAddress 0x0 FBSize>
182 * The expected size of this property is 4 * sizeof(UINT32)
183 */
184 if (PropLen != SplashMemPropSize) {
185 DEBUG (
186 (EFI_D_ERROR,
187 "ERROR: splash mem reservation node size. Expected: %d, Actual: %d\n",
188 SplashMemPropSize, PropLen));
189 return EFI_BAD_BUFFER_SIZE;
190 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700191
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700192 DEBUG ((EFI_D_VERBOSE, "Splash memory region before updating:\n"));
193 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700194
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700195 /* First, update the FBAddress */
196 if (CHECK_ADD64 ((UINT64)Prop->data, sizeof (UINT32))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530197 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBAddress"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700198 return EFI_BAD_BUFFER_SIZE;
199 }
200 tmp = (CHAR8 *)Prop->data + sizeof (UINT32);
201 splashBuf.uFrameAddr = cpu_to_fdt32 (splashBuf.uFrameAddr);
202 memcpy (tmp, &splashBuf.uFrameAddr, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700203
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700204 /* Next, update the FBSize */
205 if (CHECK_ADD64 ((UINT64)tmp, (2 * sizeof (UINT32)))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530206 DEBUG ((EFI_D_ERROR, "ERROR: integer Overflow while updating FBSize"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700207 return EFI_BAD_BUFFER_SIZE;
208 }
209 tmp += (2 * sizeof (UINT32));
210 splashBuf.uFrameSize = cpu_to_fdt32 (splashBuf.uFrameSize);
211 memcpy (tmp, &splashBuf.uFrameSize, sizeof (UINT32));
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700212
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700213 /* Update the property value in place */
214 ret = fdt_setprop_inplace (fdt, offset, "reg", Prop->data, PropLen);
215 if (ret < 0) {
216 DEBUG ((EFI_D_ERROR, "ERROR: Could not update splash mem info\n"));
217 return EFI_NO_MAPPING;
218 }
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700219
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700220 DEBUG ((EFI_D_VERBOSE, "Splash memory region after updating:\n"));
221 PrintSplashMemInfo (Prop->data, PropLen);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700222error:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700223 return Status;
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700224}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800225
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700226UINT32
227fdt_check_header_ext (VOID *fdt)
Runmin Wange74d8042016-07-19 18:09:07 -0700228{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700229 UINT64 fdt_start, fdt_end;
230 UINT32 sum;
231 fdt_start = (UINT64)fdt;
Runmin Wange74d8042016-07-19 18:09:07 -0700232
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700233 if (fdt_start + fdt_totalsize (fdt) <= fdt_start) {
234 return FDT_ERR_BADOFFSET;
235 }
236 fdt_end = fdt_start + fdt_totalsize (fdt);
Runmin Wange74d8042016-07-19 18:09:07 -0700237
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700238 if (!(sum = ADD_OF (fdt_off_dt_struct (fdt), fdt_size_dt_struct (fdt)))) {
239 return FDT_ERR_BADOFFSET;
240 } else {
241 if (CHECK_ADD64 (fdt_start, sum))
242 return FDT_ERR_BADOFFSET;
243 else if (fdt_start + sum > fdt_end)
244 return FDT_ERR_BADOFFSET;
245 }
246 if (!(sum = ADD_OF (fdt_off_dt_strings (fdt), fdt_size_dt_strings (fdt)))) {
247 return FDT_ERR_BADOFFSET;
248 } else {
249 if (CHECK_ADD64 (fdt_start, sum))
250 return FDT_ERR_BADOFFSET;
251 else if (fdt_start + sum > fdt_end)
252 return FDT_ERR_BADOFFSET;
253 }
254 if (fdt_start + fdt_off_mem_rsvmap (fdt) > fdt_end)
255 return FDT_ERR_BADOFFSET;
256 return 0;
Runmin Wange74d8042016-07-19 18:09:07 -0700257}
258
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700259STATIC
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700260VOID
261UpdateGranuleInfo (VOID *fdt)
262{
263 EFI_STATUS Status = EFI_SUCCESS;
Bhanuprakash Modem7ee03122018-06-12 19:47:36 +0530264 INT32 GranuleNodeOffset;
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700265 UINT32 GranuleSize;
266 INT32 Ret;
267
Parth Dixitfc028d92019-04-22 15:55:46 +0530268 Status = GetGranuleSize (&GranuleSize);
269 if (EFI_ERROR (Status)) {
270 DEBUG ((EFI_D_VERBOSE,
271 "Unable to get Granule Size, Status = %r\r\n",
272 Status));
Bhanuprakash Modem7ee03122018-06-12 19:47:36 +0530273 return;
274 }
275
lijuangc8803a62020-02-10 15:23:51 +0800276 GranuleNodeOffset = FdtPathOffset (fdt, "/mem-offline");
Parth Dixitfc028d92019-04-22 15:55:46 +0530277 if (GranuleNodeOffset < 0) {
278 DEBUG ((EFI_D_VERBOSE, "INFO: Could not find mem-offline node.\n"));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700279 return;
280 }
281
lijuangc8803a62020-02-10 15:23:51 +0800282 FdtPropUpdateFunc (fdt, GranuleNodeOffset, "granule",
283 GranuleSize, fdt_setprop_u32, Ret);
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700284 if (Ret) {
Parth Dixitfc028d92019-04-22 15:55:46 +0530285 DEBUG ((EFI_D_ERROR, "INFO: Granule size update failed.\n"));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700286 }
287}
288
289STATIC
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700290EFI_STATUS
Mayank Groverabfc3532018-05-03 14:52:32 +0530291QueryMemoryCellSize (IN VOID *Fdt, OUT UINT32 *MemoryCellLen)
292{
293 INT32 RootOffset;
294 INT32 PropLen;
295 UINT32 AddrCellSize = 0;
296 UINT32 SizeCellSize = 0;
297 UINT32 *Prop = NULL;
298
299 RootOffset = fdt_path_offset (Fdt, "/");
300 if (RootOffset < 0) {
301 DEBUG ((EFI_D_ERROR, "Error finding root offset\n"));
302 return EFI_NOT_FOUND;
303 }
304
305 /* Find address-cells size */
306 Prop = (UINT32 *) fdt_getprop (Fdt, RootOffset, "#address-cells", &PropLen);
307 if (Prop &&
308 PropLen > 0) {
309 AddrCellSize = fdt32_to_cpu (*Prop);
310 } else {
311 DEBUG ((EFI_D_ERROR, "Error finding #address-cells property\n"));
312 return EFI_NOT_FOUND;
313 }
314
315 /* Find size-cells size */
316 Prop =(UINT32 *) fdt_getprop (Fdt, RootOffset, "#size-cells", &PropLen);
317 if (Prop &&
318 PropLen > 0) {
319 SizeCellSize = fdt32_to_cpu (*Prop);
320 } else {
321 DEBUG ((EFI_D_ERROR, "Error finding #size-cells property\n"));
322 return EFI_NOT_FOUND;
323 }
324
325 if (AddrCellSize > DEFAULT_CELL_SIZE ||
326 SizeCellSize > DEFAULT_CELL_SIZE ||
327 SizeCellSize == 0 ||
328 AddrCellSize == 0) {
329 DEBUG ((EFI_D_ERROR, "Error unsupported cell size value: #address-cell %d" \
330 "#size-cell\n", AddrCellSize, SizeCellSize));
331 return EFI_INVALID_PARAMETER;
332 }
333
334 /* Make sure memory cell size and address cell size are same */
335 if (AddrCellSize == SizeCellSize) {
336 *MemoryCellLen = AddrCellSize;
337 } else {
338 DEBUG ((EFI_D_ERROR, "Mismatch memory address cell and size cell size\n"));
339 return EFI_INVALID_PARAMETER;
340 }
341
342 return EFI_SUCCESS;
343}
344
345STATIC
346EFI_STATUS
347AddMemMap (VOID *Fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800348{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700349 EFI_STATUS Status = EFI_NOT_FOUND;
350 INT32 ret = 0;
351 RamPartitionEntry *RamPartitions = NULL;
352 UINT32 NumPartitions = 0;
353 UINT32 i = 0;
Mayank Groverabfc3532018-05-03 14:52:32 +0530354 UINT32 MemoryCellLen = 0;
355
356 Status = QueryMemoryCellSize (Fdt, &MemoryCellLen);
357 if (EFI_ERROR (Status)) {
358 DEBUG ((EFI_D_ERROR, "ERROR: Not a valid memory node found!\n"));
359 return Status;
360 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800361
Chandra Sai Chidipudiecc62632020-01-24 15:20:50 +0530362 Status = ReadRamPartitions (&RamPartitions, &NumPartitions);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700363 if (EFI_ERROR (Status)) {
Chandra Sai Chidipudiecc62632020-01-24 15:20:50 +0530364 DEBUG ((EFI_D_ERROR, "Error returned from ReadRamPartitions %r\n", Status));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700365 return Status;
366 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800367
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700368 DEBUG ((EFI_D_INFO, "RAM Partitions\r\n"));
369 for (i = 0; i < NumPartitions; i++) {
370 DEBUG ((EFI_D_INFO, "Add Base: 0x%016lx Available Length: 0x%016lx \n",
371 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700372
Mayank Groverabfc3532018-05-03 14:52:32 +0530373 if (MemoryCellLen == 1) {
374 ret = dev_tree_add_mem_info (Fdt, MemNodeOffset, RamPartitions[i].Base,
375 RamPartitions[i].AvailableLength);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700376 } else {
Mayank Groverabfc3532018-05-03 14:52:32 +0530377 ret = dev_tree_add_mem_infoV64 (Fdt, MemNodeOffset,
378 RamPartitions[i].Base,
379 RamPartitions[i].AvailableLength);
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700380 }
381
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700382 if (ret) {
383 DEBUG ((EFI_D_ERROR, "Add Base: 0x%016lx Length: 0x%016lx Fail\n",
384 RamPartitions[i].Base, RamPartitions[i].AvailableLength));
385 }
386 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800387
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700388 FreePool (RamPartitions);
389 RamPartitions = NULL;
Chandra Sai Chidipudiecc62632020-01-24 15:20:50 +0530390 RamPartitionEntries = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700391
392 return EFI_SUCCESS;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800393}
394
395/* Supporting function of UpdateDeviceTree()
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700396 * Function first gets the RAM partition table, then passes the pointer to
397 * AddMemMap() */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700398STATIC
399EFI_STATUS
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700400target_dev_tree_mem (VOID *fdt, UINT32 MemNodeOffset, BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800401{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700402 EFI_STATUS Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800403
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700404 /* Get Available memory from partition table */
405 Status = AddMemMap (fdt, MemNodeOffset, BootWith32Bit);
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700406 if (EFI_ERROR (Status)) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700407 DEBUG ((EFI_D_ERROR,
408 "Invalid memory configuration, check memory partition table: %r\n",
409 Status));
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700410 goto out;
411 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800412
Jeevan Shriram067bbb52018-05-08 17:48:47 -0700413 UpdateGranuleInfo (fdt);
414
415out:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700416 return Status;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800417}
418
419/* Supporting function of target_dev_tree_mem()
420 * Function to add the subsequent RAM partition info to the device tree */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700421INT32
422dev_tree_add_mem_info (VOID *fdt, UINT32 offset, UINT32 addr, UINT32 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800423{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700424 STATIC INT32 mem_info_cnt = 0;
425 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800426
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700427 if (!mem_info_cnt) {
428 /* Replace any other reg prop in the memory node. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700429 mem_info_cnt = 1;
lijuangc8803a62020-02-10 15:23:51 +0800430 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_setprop_u32, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700431 } else {
432 /* Append the mem info to the reg prop for subsequent nodes. */
lijuangc8803a62020-02-10 15:23:51 +0800433 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_appendprop_u32, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700434 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800435
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700436 if (ret) {
437 DEBUG (
438 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
439 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800440
lijuangc8803a62020-02-10 15:23:51 +0800441 FdtPropUpdateFunc (fdt, offset, "reg", size, fdt_appendprop_u32, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700442 if (ret) {
443 DEBUG (
444 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
445 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800446
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700447 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800448}
449
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700450INT32
451dev_tree_add_mem_infoV64 (VOID *fdt, UINT32 offset, UINT64 addr, UINT64 size)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800452{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700453 STATIC INT32 mem_info_cnt = 0;
454 INT32 ret = 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800455
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700456 if (!mem_info_cnt) {
457 /* Replace any other reg prop in the memory node. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700458 mem_info_cnt = 1;
lijuangc8803a62020-02-10 15:23:51 +0800459 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_setprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700460 } else {
461 /* Append the mem info to the reg prop for subsequent nodes. */
lijuangc8803a62020-02-10 15:23:51 +0800462 FdtPropUpdateFunc (fdt, offset, "reg", addr, fdt_appendprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700463 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800464
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700465 if (ret) {
466 DEBUG (
467 (EFI_D_ERROR, "Failed to add the memory information addr: %d\n", ret));
468 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800469
lijuangc8803a62020-02-10 15:23:51 +0800470 FdtPropUpdateFunc (fdt, offset, "reg", size, fdt_appendprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700471 if (ret) {
472 DEBUG (
473 (EFI_D_ERROR, "Failed to add the memory information size: %d\n", ret));
474 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800475
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700476 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800477}
478
479/* Top level function that updates the device tree. */
Jeevan Shriram27c8faa2017-09-27 12:05:53 -0700480EFI_STATUS
481UpdateDeviceTree (VOID *fdt,
482 CONST CHAR8 *cmdline,
483 VOID *ramdisk,
484 UINT32 RamDiskSize,
485 BOOLEAN BootWith32Bit)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800486{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700487 INT32 ret = 0;
488 UINT32 offset;
489 UINT32 PaddSize = 0;
Elliot Berman78ecae42019-10-29 09:35:08 -0700490 UINT64 RandomSeed = 0;
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700491 UINT8 DdrDeviceType;
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530492 /* Single space reserved for chan(0-9) */
493 CHAR8 FdtRankProp[] = "ddr_device_rank_ch ";
494 /* Single spaces reserved for chan(0-9), rank(0-9) */
495 CHAR8 FdtHbbProp[] = "ddr_device_hbb_ch _rank ";
496 struct ddr_details_entry_info *DdrInfo;
497 UINT64 Revision;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700498 EFI_STATUS Status;
lijuang768a4452019-09-24 18:37:42 +0800499 UINT64 UpdateDTStartTime = GetTimerCountms ();
Elliot Berman78ecae42019-10-29 09:35:08 -0700500 UINT32 Index;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800501
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700502 /* Check the device tree header */
503 ret = fdt_check_header (fdt) || fdt_check_header_ext (fdt);
504 if (ret) {
505 DEBUG ((EFI_D_ERROR, "ERROR: Invalid device tree header ...\n"));
506 return EFI_NOT_FOUND;
507 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800508
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700509 /* Add padding to make space for new nodes and properties. */
lijuangfd6fa912017-11-16 18:08:22 +0800510 PaddSize = ADD_OF (fdt_totalsize (fdt),
511 DTB_PAD_SIZE + AsciiStrLen (cmdline));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700512 if (!PaddSize) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530513 DEBUG ((EFI_D_ERROR, "ERROR: Integer Overflow: fdt size = %u\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700514 fdt_totalsize (fdt)));
515 return EFI_BAD_BUFFER_SIZE;
516 }
517 ret = fdt_open_into (fdt, fdt, PaddSize);
518 if (ret != 0) {
519 DEBUG ((EFI_D_ERROR, "ERROR: Failed to move/resize dtb buffer ...\n"));
520 return EFI_BAD_BUFFER_SIZE;
521 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800522
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700523 /* Get offset of the memory node */
lijuangc8803a62020-02-10 15:23:51 +0800524 ret = FdtPathOffset (fdt, "/memory");
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700525 if (ret < 0) {
526 DEBUG ((EFI_D_ERROR, "ERROR: Could not find memory node ...\n"));
527 return EFI_NOT_FOUND;
528 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800529
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700530 offset = ret;
531 Status = target_dev_tree_mem (fdt, offset, BootWith32Bit);
532 if (Status != EFI_SUCCESS) {
533 DEBUG ((EFI_D_ERROR, "ERROR: Cannot update memory node\n"));
534 return Status;
535 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800536
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530537 DdrInfo = AllocateZeroPool (sizeof (struct ddr_details_entry_info));
538 if (DdrInfo == NULL) {
539 DEBUG ((EFI_D_ERROR, "DDR Info Buffer: Out of resources\n"));
540 return EFI_OUT_OF_RESOURCES;
541 }
542 Status = GetDDRInfo (DdrInfo, &Revision);
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700543 if (Status == EFI_SUCCESS) {
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530544 DdrDeviceType = DdrInfo->device_type;
545 DEBUG ((EFI_D_VERBOSE, "DDR deviceType:%d\n", DdrDeviceType));
546
lijuangc8803a62020-02-10 15:23:51 +0800547 FdtPropUpdateFunc (fdt, offset, (CONST char *)"ddr_device_type",
548 (UINT32)DdrDeviceType, fdt_appendprop_u32, ret);
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700549 if (ret) {
550 DEBUG ((EFI_D_ERROR,
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530551 "ERROR: Cannot update memory node [ddr_device_type]:0x%x\n",
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700552 ret));
553 } else {
554 DEBUG ((EFI_D_VERBOSE, "ddr_device_type is added to memory node\n"));
555 }
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530556
557 if (Revision < EFI_DDRGETINFO_PROTOCOL_REVISION) {
558 DEBUG ((EFI_D_VERBOSE,
559 "ddr_device_rank, HBB not supported in Revision=0x%x\n",
560 Revision));
561 } else {
562 DEBUG ((EFI_D_VERBOSE, "DdrInfo->num_channels:%d\n",
563 DdrInfo->num_channels));
564 for (UINT8 Chan = 0; Chan < DdrInfo->num_channels; Chan++) {
565 DEBUG ((EFI_D_VERBOSE, "ddr_device_rank_ch%d:%d\n",
566 Chan, DdrInfo->num_ranks[Chan]));
567 AsciiSPrint (FdtRankProp, sizeof (FdtRankProp),
568 "ddr_device_rank_ch%d", Chan);
lijuangc8803a62020-02-10 15:23:51 +0800569 FdtPropUpdateFunc (fdt, offset, (CONST char *)FdtRankProp,
570 (UINT32)DdrInfo->num_ranks[Chan],
571 fdt_appendprop_u32, ret);
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530572 if (ret) {
573 DEBUG ((EFI_D_ERROR,
574 "ERROR: Cannot update memory node ddr_device_rank_ch%d:0x%x\n",
575 Chan, ret));
576 } else {
577 DEBUG ((EFI_D_VERBOSE, "ddr_device_rank_ch%d added to memory node\n",
578 Chan));
579 }
580 for (UINT8 Rank = 0; Rank < DdrInfo->num_ranks[Chan]; Rank++) {
581 DEBUG ((EFI_D_VERBOSE, "ddr_device_hbb_ch%d_rank%d:%d\n",
582 Chan, Rank, DdrInfo->hbb[Chan][Rank]));
583 AsciiSPrint (FdtHbbProp, sizeof (FdtHbbProp),
584 "ddr_device_hbb_ch%d_rank%d", Chan, Rank);
lijuangc8803a62020-02-10 15:23:51 +0800585 FdtPropUpdateFunc (fdt, offset, (CONST char *)FdtHbbProp,
586 (UINT32)DdrInfo->hbb[Chan][Rank],
587 fdt_appendprop_u32, ret);
Kaushal Kumarf6e9aa52019-11-19 18:52:38 +0530588 if (ret) {
589 DEBUG ((EFI_D_ERROR,
590 "ERROR: Cannot update memory node ddr_device_hbb_ch%d_rank%d:0x%x\n",
591 Chan, Rank, ret));
592 } else {
593 DEBUG ((EFI_D_VERBOSE,
594 "ddr_device_hbb_ch%d_rank%d added to memory node\n",
595 Chan, Rank));
596 }
597 }
598 }
599 }
Jeevan Shriramf8fa2912018-11-02 13:16:47 -0700600 }
601
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700602 UpdateSplashMemInfo (fdt);
Aravind Venkateswaranc0048032016-07-22 14:28:03 -0700603
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700604 /* Get offset of the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800605 ret = FdtPathOffset (fdt, "/chosen");
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700606 if (ret < 0) {
607 DEBUG ((EFI_D_ERROR, "ERROR: Could not find chosen node ...\n"));
608 return EFI_NOT_FOUND;
609 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800610
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700611 offset = ret;
612 if (cmdline) {
613 /* Adding the cmdline to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800614 FdtPropUpdateFunc (fdt, offset, (CONST char *)"bootargs",
615 (CONST VOID *)cmdline, fdt_appendprop_string, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700616 if (ret) {
617 DEBUG ((EFI_D_ERROR,
618 "ERROR: Cannot update chosen node [bootargs] - 0x%x\n", ret));
619 return EFI_LOAD_ERROR;
620 }
621 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800622
Elliot Berman78ecae42019-10-29 09:35:08 -0700623 for (Index = 0; Index < NUM_RNG_SEED_WORDS / sizeof (UINT64); Index++) {
624 Status = GetRandomSeed (&RandomSeed);
625 if (Status == EFI_SUCCESS) {
626
627 /* Adding the RNG seed to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800628 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"rng-seed",
629 (UINT64)RandomSeed, fdt_appendprop_u64, ret);
Elliot Berman78ecae42019-10-29 09:35:08 -0700630 if (ret) {
631 DEBUG ((EFI_D_ERROR,
632 "ERROR: Cannot update chosen node [rng-seed] - 0x%x\n", ret));
633 break;
634 }
635 } else {
636 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Random Seed - %r\n", Status));
637 break;
638 }
639 }
640
641 Status = GetRandomSeed (&RandomSeed);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700642 if (Status == EFI_SUCCESS) {
643 /* Adding Kaslr Seed to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800644 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"kaslr-seed",
645 (UINT64)RandomSeed, fdt_appendprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700646 if (ret) {
647 DEBUG ((EFI_D_INFO,
648 "ERROR: Cannot update chosen node [kaslr-seed] - 0x%x\n", ret));
649 } else {
lijuangf2eb1fa2019-09-23 14:10:20 +0800650 DEBUG ((EFI_D_VERBOSE, "kaslr-Seed is added to chosen node\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700651 }
652 } else {
653 DEBUG ((EFI_D_INFO, "ERROR: Cannot generate Kaslr Seed - %r\n", Status));
654 }
Runmin Wang8ecc3f62016-12-09 14:03:05 -0800655
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700656 if (RamDiskSize) {
657 /* Adding the initrd-start to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800658 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"linux,initrd-start",
659 (UINT64)ramdisk, fdt_setprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700660 if (ret) {
661 DEBUG ((EFI_D_ERROR,
662 "ERROR: Cannot update chosen node [linux,initrd-start] - 0x%x\n",
663 ret));
664 return EFI_NOT_FOUND;
665 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800666
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700667 /* Adding the initrd-end to the chosen node */
lijuangc8803a62020-02-10 15:23:51 +0800668 FdtPropUpdateFunc (fdt, offset, (CONST CHAR8 *)"linux,initrd-end",
669 (UINT64)ramdisk + RamDiskSize, fdt_setprop_u64, ret);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700670 if (ret) {
671 DEBUG ((EFI_D_ERROR,
672 "ERROR: Cannot update chosen node [linux,initrd-end] - 0x%x\n",
673 ret));
674 return EFI_NOT_FOUND;
675 }
676 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530677
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700678 /* Update fstab node */
679 DEBUG ((EFI_D_VERBOSE, "Start DT fstab node update: %lu ms\n",
680 GetTimerCountms ()));
681 UpdateFstabNode (fdt);
682 DEBUG ((EFI_D_VERBOSE, "End DT fstab node update: %lu ms\n",
683 GetTimerCountms ()));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530684
Parth Dixit3f4e4aa2019-05-14 17:08:46 +0530685 /* Check partial goods*/
686 if (FixedPcdGetBool (EnablePartialGoods)) {
687 ret = UpdatePartialGoodsNode (fdt);
688 if (ret != EFI_SUCCESS) {
689 DEBUG ((EFI_D_ERROR,
690 "Failed to update device tree for partial goods, Status=%r\n",
691 ret));
692 return ret;
693 }
694 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700695 fdt_pack (fdt);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800696
lijuang768a4452019-09-24 18:37:42 +0800697 DEBUG ((EFI_D_INFO, "Update Device Tree total time: %lu ms \n",
698 GetTimerCountms () - UpdateDTStartTime));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700699 return ret;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800700}
Channagoud Kadabi9be68a72016-02-08 15:18:24 -0800701
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530702/* Update device tree for fstab node */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700703EFI_STATUS
704UpdateFstabNode (VOID *fdt)
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530705{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700706 INT32 ParentOffset = 0;
707 INT32 SubNodeOffset = 0;
708 CONST struct fdt_property *Prop = NULL;
709 INT32 PropLen = 0;
710 char *NodeName = NULL;
711 EFI_STATUS Status = EFI_SUCCESS;
712 CHAR8 *BootDevBuf = NULL;
713 CHAR8 *ReplaceStr = NULL;
714 CHAR8 *NextStr = NULL;
Mayank Grover546377b2019-04-12 15:52:10 +0530715 struct FstabNode Table = IsDynamicPartitionSupport () ? DynamicFstabTable
716 : FstabTable;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700717 UINT32 DevNodeBootDevLen = 0;
718 UINT32 Index = 0;
719 UINT32 PaddingEnd = 0;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530720
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700721 /* Find the parent node */
lijuangc8803a62020-02-10 15:23:51 +0800722 ParentOffset = FdtPathOffset (fdt, Table.ParentNode);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700723 if (ParentOffset < 0) {
724 DEBUG ((EFI_D_VERBOSE, "Failed to Get parent node: fstab\terror: %d\n",
725 ParentOffset));
726 return EFI_NOT_FOUND;
727 }
728 DEBUG ((EFI_D_VERBOSE, "Node: %a found.\n",
729 fdt_get_name (fdt, ParentOffset, NULL)));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530730
Mayank Grover546377b2019-04-12 15:52:10 +0530731 if (!IsDynamicPartitionSupport ()) {
732 /* Get boot device type */
733 BootDevBuf = AllocateZeroPool (sizeof (CHAR8) * BOOT_DEV_MAX_LEN);
734 if (BootDevBuf == NULL) {
735 DEBUG ((EFI_D_ERROR, "Boot device buffer: Out of resources\n"));
736 return EFI_OUT_OF_RESOURCES;
737 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530738
Mayank Grover546377b2019-04-12 15:52:10 +0530739 Status = GetBootDevice (BootDevBuf, BOOT_DEV_MAX_LEN);
740 if (Status != EFI_SUCCESS) {
741 DEBUG ((EFI_D_ERROR, "Failed to get Boot Device: %r\n", Status));
742 FreePool (BootDevBuf);
743 BootDevBuf = NULL;
744 return Status;
745 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700746 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530747
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700748 /* Get properties of all sub nodes */
749 for (SubNodeOffset = fdt_first_subnode (fdt, ParentOffset);
750 SubNodeOffset >= 0;
751 SubNodeOffset = fdt_next_subnode (fdt, SubNodeOffset)) {
752 Prop = fdt_get_property (fdt, SubNodeOffset, Table.Property, &PropLen);
753 NodeName = (char *)(uintptr_t)fdt_get_name (fdt, SubNodeOffset, NULL);
754 if (!Prop) {
755 DEBUG ((EFI_D_VERBOSE, "Property:%a is not found for sub-node:%a\n",
756 Table.Property, NodeName));
757 } else {
758 DEBUG ((EFI_D_VERBOSE, "Property:%a found for sub-node:%a\tProperty:%a\n",
759 Table.Property, NodeName, Prop->data));
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530760
Mayank Grover546377b2019-04-12 15:52:10 +0530761 /* For Dynamic partition support disable firmware fstab nodes. */
762 if (IsDynamicPartitionSupport ()) {
763 DEBUG ((EFI_D_VERBOSE, "Disabling node status :%a\n", NodeName));
lijuangc8803a62020-02-10 15:23:51 +0800764 Status = FdtSetProp (fdt, SubNodeOffset, Table.Property,
765 (CONST VOID *)"disabled",
766 (AsciiStrLen ("disabled") + 1));
Mayank Grover546377b2019-04-12 15:52:10 +0530767 if (Status) {
768 DEBUG ((EFI_D_ERROR, "ERROR: Failed to disable Node: %a\n", NodeName));
769 }
770 continue;
771 }
772
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700773 /* Pointer to fdt 'dev' property string that needs to update based on the
774 * 'androidboot.bootdevice' */
775 ReplaceStr = (CHAR8 *)Prop->data;
776 ReplaceStr = AsciiStrStr (ReplaceStr, Table.DevicePathId);
777 if (!ReplaceStr) {
778 DEBUG ((EFI_D_VERBOSE, "Update property:%a value is not proper to "
779 "update for sub-node:%a\n",
780 Table.Property, NodeName));
781 continue;
782 }
783 ReplaceStr += AsciiStrLen (Table.DevicePathId);
784 NextStr = AsciiStrStr ((ReplaceStr + 1), "/");
785 DevNodeBootDevLen = NextStr - ReplaceStr;
786 if (DevNodeBootDevLen >= AsciiStrLen (BootDevBuf)) {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530787 gBS->CopyMem (ReplaceStr, BootDevBuf, AsciiStrLen (BootDevBuf));
788 PaddingEnd = DevNodeBootDevLen - AsciiStrLen (BootDevBuf);
789 /* Update the property with new value */
790 if (PaddingEnd) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700791 gBS->CopyMem (ReplaceStr + AsciiStrLen (BootDevBuf), NextStr,
792 AsciiStrLen (NextStr));
793 for (Index = 0; Index < PaddingEnd; Index++) {
794 ReplaceStr[AsciiStrLen (BootDevBuf) + AsciiStrLen (NextStr) +
795 Index] = ' ';
796 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530797 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700798 } else {
Mukesh Ojha323c9402017-10-03 23:49:05 +0530799 DEBUG ((EFI_D_ERROR, "String length mismatch b/w DT Bootdevice string"
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700800 " (%d) and expected Bootdevice strings (%d)\n",
801 DevNodeBootDevLen, AsciiStrLen (BootDevBuf)));
802 }
Mukesh Ojha323c9402017-10-03 23:49:05 +0530803 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700804 }
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530805
Mayank Grover546377b2019-04-12 15:52:10 +0530806 if (BootDevBuf) {
807 FreePool (BootDevBuf);
808 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700809 BootDevBuf = NULL;
810 return Status;
Bhanuprakash Modem0450e9b2017-06-09 11:58:51 +0530811}