blob: cb4ed9b486a91f57338e9978d0972006a975cfca [file] [log] [blame]
Lijuan Gao1259da72021-03-05 10:39:12 +08001/* Copyright (c) 2012-2021, 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#include "LocateDeviceTree.h"
Runmin Wange74d8042016-07-19 18:09:07 -070030#include "UpdateDeviceTree.h"
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053031#include <Library/Board.h>
Jeevan Shriram17f173d2017-10-24 22:11:07 -070032#include <Library/BootLinux.h>
33#include <Library/PartitionTableUpdate.h>
34#include <Library/Rtic.h>
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080035// Variables to initialize board data
36
Jeevan Shriram17f173d2017-10-24 22:11:07 -070037STATIC int
38platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
39 struct dt_entry_node *dt_list);
40STATIC struct dt_entry *
41platform_dt_match_best (struct dt_entry_node *dt_list);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080042
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +053043STATIC BOOLEAN DtboNeed = TRUE;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053044
lijuang6fa55c02018-06-22 19:19:26 +080045STATIC INT32 DtboIdx = INVALID_PTN;
46INT32 GetDtboIdx (VOID)
47{
48 return DtboIdx;
49}
50
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -070051STATIC INT32 DtbIdx = INVALID_PTN;
52INT32 GetDtbIdx (VOID)
53{
54 return DtbIdx;
55}
56
lijuangf0bbcad2017-08-16 16:59:18 +080057BOOLEAN GetDtboNeeded (VOID)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053058{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070059 return DtboNeed;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053060}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080061/* Add function to allocate dt entry list, used for recording
62 * the entry which conform to platform_dt_absolute_match()
63 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -070064static struct dt_entry_node *dt_entry_list_init (VOID)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080065{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070066 struct dt_entry_node *dt_node_member = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080067
Jeevan Shriram17f173d2017-10-24 22:11:07 -070068 dt_node_member =
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +053069 (struct dt_entry_node *)AllocateZeroPool (sizeof (struct dt_entry_node));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080070
Jeevan Shriram17f173d2017-10-24 22:11:07 -070071 if (!dt_node_member) {
72 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_node_member\n"));
73 return NULL;
74 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080075
Jeevan Shriram17f173d2017-10-24 22:11:07 -070076 list_clear_node (&dt_node_member->node);
77 dt_node_member->dt_entry_m =
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +053078 (struct dt_entry *)AllocateZeroPool (sizeof (struct dt_entry));
Jeevan Shriram17f173d2017-10-24 22:11:07 -070079 if (!dt_node_member->dt_entry_m) {
80 DEBUG ((EFI_D_ERROR,
81 "Failed to allocate memory for dt_node_member->dt_entry_m\n"));
82 FreePool (dt_node_member);
83 dt_node_member = NULL;
84 return NULL;
85 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080086
Jeevan Shriram17f173d2017-10-24 22:11:07 -070087 return dt_node_member;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080088}
89
Jeevan Shriram17f173d2017-10-24 22:11:07 -070090static VOID
91insert_dt_entry_in_queue (struct dt_entry_node *dt_list,
92 struct dt_entry_node *dt_node_member)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080093{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070094 list_add_tail (&dt_list->node, &dt_node_member->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080095}
96
Jeevan Shriram17f173d2017-10-24 22:11:07 -070097static VOID
98dt_entry_list_delete (struct dt_entry_node *dt_node_member)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080099{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700100 if (list_in_list (&dt_node_member->node)) {
101 list_delete (&dt_node_member->node);
102 FreePool (dt_node_member->dt_entry_m);
103 dt_node_member->dt_entry_m = NULL;
104 FreePool (dt_node_member);
105 dt_node_member = NULL;
106 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800107}
108
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700109static BOOLEAN
110DeviceTreeCompatible (VOID *dtb,
111 UINT32 dtb_size,
112 struct dt_entry_node *dtb_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800113{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700114 int root_offset;
115 const VOID *prop = NULL;
116 const char *plat_prop = NULL;
117 const char *board_prop = NULL;
118 const char *pmic_prop = NULL;
119 char *model = NULL;
120 struct dt_entry *dt_entry_array = NULL;
121 struct board_id *board_data = NULL;
122 struct plat_id *platform_data = NULL;
123 struct pmic_id *pmic_data = NULL;
124 int len;
125 int len_board_id;
126 int len_plat_id;
127 int min_plat_id_len = 0;
128 int len_pmic_id;
129 UINT32 dtb_ver;
jianzhoue687ba82017-11-27 16:08:51 +0800130 UINT64 NumEntries = 0;
131 UINT64 i;
132 UINT32 j, k, n;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700133 UINT32 msm_data_count;
134 UINT32 board_data_count;
135 UINT32 pmic_data_count;
136 BOOLEAN Result = FALSE;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700137 static UINT32 DtbCount;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800138
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700139 root_offset = fdt_path_offset (dtb, "/");
140 if (root_offset < 0)
141 return FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800142
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700143 prop = fdt_getprop (dtb, root_offset, "model", &len);
144 if (prop && len > 0) {
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530145 model = (char *)AllocateZeroPool (sizeof (char) * len);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700146 if (!model) {
147 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for model\n"));
148 return FALSE;
149 }
150 AsciiStrnCpyS (model, (sizeof (CHAR8) * len), prop, len);
151 } else {
152 DEBUG ((EFI_D_ERROR, "model does not exist in device tree\n"));
153 }
154 /* Find the pmic-id prop from DTB , if pmic-id is present then
155 * the DTB is version 3, otherwise find the board-id prop from DTB ,
156 * if board-id is present then the DTB is version 2 */
157 pmic_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,pmic-id",
158 &len_pmic_id);
159 board_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,board-id",
160 &len_board_id);
161 if (pmic_prop && (len_pmic_id > 0) && board_prop && (len_board_id > 0)) {
162 if ((len_pmic_id % PMIC_ID_SIZE) || (len_board_id % BOARD_ID_SIZE)) {
163 DEBUG ((EFI_D_ERROR, "qcom,pmic-id (%d) or qcom,board-id(%d) in device "
164 "tree is not a multiple of (%d %d)\n",
165 len_pmic_id, len_board_id, PMIC_ID_SIZE, BOARD_ID_SIZE));
166 goto Exit;
167 }
168 dtb_ver = DEV_TREE_VERSION_V3;
169 min_plat_id_len = PLAT_ID_SIZE;
170 } else if (board_prop && len_board_id > 0) {
171 if (len_board_id % BOARD_ID_SIZE) {
172 DEBUG ((EFI_D_ERROR,
Elliot Bermanbc287262020-01-16 09:46:53 -0800173 "qcom,board-id (%d) in device tree is not a multiple of (%d)\n",
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700174 len_board_id, BOARD_ID_SIZE));
175 goto Exit;
176 }
177 dtb_ver = DEV_TREE_VERSION_V2;
178 min_plat_id_len = PLAT_ID_SIZE;
179 } else {
180 dtb_ver = DEV_TREE_VERSION_V1;
181 min_plat_id_len = DT_ENTRY_V1_SIZE;
182 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800183
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700184 /* Get the msm-id prop from DTB */
185 plat_prop =
186 (const char *)fdt_getprop (dtb, root_offset, "qcom,msm-id", &len_plat_id);
187 if (!plat_prop || len_plat_id <= 0) {
188 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id entry not found\n"));
189 goto Exit;
190 } else if (len_plat_id % min_plat_id_len) {
191 DEBUG ((EFI_D_ERROR,
192 "qcom, msm-id in device tree is (%d) not a multiple of (%d)\n",
193 len_plat_id, min_plat_id_len));
194 goto Exit;
195 }
196 if (dtb_ver == DEV_TREE_VERSION_V2 || dtb_ver == DEV_TREE_VERSION_V3) {
197 board_data_count = (len_board_id / BOARD_ID_SIZE);
198 msm_data_count = (len_plat_id / PLAT_ID_SIZE);
199 /* If dtb version is v2.0, the pmic_data_count will be <= 0 */
200 pmic_data_count = (len_pmic_id / PMIC_ID_SIZE);
201
202 /* If we are using dtb v3.0, then we have split board, msm & pmic data in
203 * the DTB
204 * If we are using dtb v2.0, then we have split board & msmdata in the DTB
205 */
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530206 board_data = (struct board_id *)AllocateZeroPool (
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700207 sizeof (struct board_id) * (len_board_id / BOARD_ID_SIZE));
208 if (!board_data) {
209 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for board_data\n"));
210 goto Exit;
211 }
212
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530213 platform_data = (struct plat_id *)AllocateZeroPool (
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700214 sizeof (struct plat_id) * (len_plat_id / PLAT_ID_SIZE));
215 if (!platform_data) {
216 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for platform_data\n"));
217 goto Exit;
218 }
219 if (dtb_ver == DEV_TREE_VERSION_V3) {
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530220 pmic_data = (struct pmic_id *)AllocateZeroPool (sizeof (struct pmic_id) *
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700221 (len_pmic_id / PMIC_ID_SIZE));
222 if (!pmic_data) {
223 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for pmic_data\n"));
lijuang46df8442017-09-28 19:06:36 +0800224 goto Exit;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700225 }
226 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800227
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700228 /* Extract board data from DTB */
229 for (i = 0; i < board_data_count; i++) {
230 board_data[i].variant_id =
231 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id);
232 board_data[i].platform_subtype =
233 fdt32_to_cpu (((struct board_id *)board_prop)->platform_subtype);
234 /* For V2/V3 version of DTBs we have platform version field as part
235 * of variant ID, in such case the subtype will be mentioned as 0x0
236 * As the qcom, board-id = <0xSSPMPmPH, 0x0>
237 * SS -- Subtype
238 * PM -- Platform major version
239 * Pm -- Platform minor version
240 * PH -- Platform hardware CDP/MTP
241 * In such case to make it compatible with LK algorithm move the subtype
242 * from variant_id to subtype field
243 */
244 if (board_data[i].platform_subtype == 0)
245 board_data[i].platform_subtype =
246 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id) >> 0x18;
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +0530247
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700248 len_board_id -= sizeof (struct board_id);
249 board_prop += sizeof (struct board_id);
250 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800251
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700252 /* Extract platform data from DTB */
253 for (i = 0; i < msm_data_count; i++) {
254 platform_data[i].platform_id =
255 fdt32_to_cpu (((struct plat_id *)plat_prop)->platform_id);
256 platform_data[i].soc_rev =
257 fdt32_to_cpu (((struct plat_id *)plat_prop)->soc_rev);
258 len_plat_id -= sizeof (struct plat_id);
259 plat_prop += sizeof (struct plat_id);
260 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800261
jianzhoue687ba82017-11-27 16:08:51 +0800262 if ((pmic_data_count != 0) &&
263 (MAX_UINT64 / pmic_data_count < (msm_data_count * board_data_count))) {
264 DEBUG ((EFI_D_ERROR, "NumEntries exceeds MAX_UINT64\n"));
265 goto Exit;
266 }
267
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700268 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
269 /* Extract pmic data from DTB */
270 for (i = 0; i < pmic_data_count; i++) {
271 pmic_data[i].pmic_version[0] =
272 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[0]);
273 pmic_data[i].pmic_version[1] =
274 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[1]);
275 pmic_data[i].pmic_version[2] =
276 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[2]);
277 pmic_data[i].pmic_version[3] =
278 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[3]);
279 len_pmic_id -= sizeof (struct pmic_id);
280 pmic_prop += sizeof (struct pmic_id);
281 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800282
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700283 /* We need to merge board & platform data into dt entry structure */
jianzhoue687ba82017-11-27 16:08:51 +0800284 NumEntries = (uint64_t)msm_data_count * board_data_count *
285 pmic_data_count;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700286 } else {
287 /* We need to merge board & platform data into dt entry structure */
jianzhoue687ba82017-11-27 16:08:51 +0800288 NumEntries = (uint64_t)msm_data_count * board_data_count;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700289 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800290
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530291 dt_entry_array = (struct dt_entry *)AllocateZeroPool (
292 sizeof (struct dt_entry) *
293 NumEntries);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700294 if (!dt_entry_array) {
295 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_entry_array\n"));
296 goto Exit;
297 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800298
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700299 /* If we have '<X>; <Y>; <Z>' as platform data & '<A>; <B>; <C>' as board
300 * data.
301 * Then dt entry should look like
302 * <X ,A >;<X, B>;<X, C>;
303 * <Y ,A >;<Y, B>;<Y, C>;
304 * <Z ,A >;<Z, B>;<Z, C>;
305 */
306 k = 0;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700307 DtbCount++;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700308 for (i = 0; i < msm_data_count; i++) {
309 for (j = 0; j < board_data_count; j++) {
310 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
311 for (n = 0; n < pmic_data_count; n++) {
312 dt_entry_array[k].platform_id = platform_data[i].platform_id;
313 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
314 dt_entry_array[k].variant_id = board_data[j].variant_id;
315 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
316 dt_entry_array[k].pmic_rev[0] = pmic_data[n].pmic_version[0];
317 dt_entry_array[k].pmic_rev[1] = pmic_data[n].pmic_version[1];
318 dt_entry_array[k].pmic_rev[2] = pmic_data[n].pmic_version[2];
319 dt_entry_array[k].pmic_rev[3] = pmic_data[n].pmic_version[3];
320 dt_entry_array[k].offset = (UINT64)dtb;
321 dt_entry_array[k].size = dtb_size;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700322 dt_entry_array[k].Idx = DtbCount;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700323 k++;
324 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800325
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700326 } else {
327 dt_entry_array[k].platform_id = platform_data[i].platform_id;
328 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
329 dt_entry_array[k].variant_id = board_data[j].variant_id;
330 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
331 dt_entry_array[k].pmic_rev[0] = BoardPmicTarget (0);
332 dt_entry_array[k].pmic_rev[1] = BoardPmicTarget (1);
333 dt_entry_array[k].pmic_rev[2] = BoardPmicTarget (2);
334 dt_entry_array[k].pmic_rev[3] = BoardPmicTarget (3);
335 dt_entry_array[k].offset = (UINT64)dtb;
336 dt_entry_array[k].size = dtb_size;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700337 dt_entry_array[k].Idx = DtbCount;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700338 k++;
lijuang46df8442017-09-28 19:06:36 +0800339 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700340 }
341 }
342
jianzhoue687ba82017-11-27 16:08:51 +0800343 for (i = 0; i < NumEntries; i++) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700344 if (platform_dt_absolute_match (&(dt_entry_array[i]), dtb_list)) {
345 DEBUG ((EFI_D_VERBOSE, "Device tree exact match the board: <0x%x 0x%x "
346 "0x%x 0x%x> == <0x%x 0x%x 0x%x 0x%x>\n",
347 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
348 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
349 BoardPlatformRawChipId (), BoardPlatformType (),
350 BoardPlatformChipVersion (), BoardPlatformSubType ()));
351 } else {
352 DEBUG ((EFI_D_VERBOSE, "Device tree's msm_id doesn't match the board: "
353 "<0x%x 0x%x 0x%x 0x%x> != <0x%x 0x%x 0x%x "
354 "0x%x>\n",
355 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
356 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
357 BoardPlatformRawChipId (), BoardPlatformType (),
358 BoardPlatformChipVersion (), BoardPlatformSubType ()));
359 }
360 }
361 Result = TRUE;
362 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800363
lijuang46df8442017-09-28 19:06:36 +0800364Exit:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700365 if (board_data) {
366 FreePool (board_data);
367 board_data = NULL;
368 }
369 if (platform_data) {
370 FreePool (platform_data);
371 platform_data = NULL;
372 }
373 if (pmic_data) {
374 FreePool (pmic_data);
375 pmic_data = NULL;
376 }
377 if (dt_entry_array) {
378 FreePool (dt_entry_array);
379 dt_entry_array = NULL;
380 }
381 if (model) {
382 FreePool (model);
383 model = NULL;
384 }
lijuang46df8442017-09-28 19:06:36 +0800385
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700386 return Result;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800387}
388
389/*
390 * Will relocate the DTB to the tags addr if the device tree is found and return
391 * its address
392 *
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700393 * For Header Version 2, the arguments Kernel and KernelSize will be
394 * the entire bootimage and the bootimage size.
395 *
396 * Arguments: kernel - Start address of the kernel/bootimage
397 * loaded in RAM
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800398 * tags - Start address of the tags loaded in RAM
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700399 * kernel_size - Size of the kernel/bootimage in bytes
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800400 *
401 * Return Value: DTB address : If appended device tree is found
402 * 'NULL' : Otherwise
403 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700404VOID *
405DeviceTreeAppended (VOID *kernel,
406 UINT32 kernel_size,
407 UINT32 dtb_offset,
408 VOID *tags)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800409{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700410 EFI_STATUS Status;
411 uintptr_t kernel_end = (uintptr_t)kernel + kernel_size;
412 VOID *dtb = NULL;
413 VOID *bestmatch_tag = NULL;
414 UINT64 RamdiskLoadAddr;
415 UINT64 BaseMemory = 0;
416 struct dt_entry *best_match_dt_entry = NULL;
417 UINT32 bestmatch_tag_size;
418 struct dt_entry_node *dt_entry_queue = NULL;
419 struct dt_entry_node *dt_node_tmp1 = NULL;
420 struct dt_entry_node *dt_node_tmp2 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800421
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700422 /* Initialize the dtb entry node*/
423 dt_entry_queue =
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530424 (struct dt_entry_node *)AllocateZeroPool (sizeof (struct dt_entry_node));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700425 if (!dt_entry_queue) {
426 DEBUG ((EFI_D_ERROR, "Out of memory\n"));
427 return NULL;
428 }
Jeevan Shrirame07dd432016-08-22 11:05:06 -0700429
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700430 list_initialize (&dt_entry_queue->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800431
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700432 if (!dtb_offset) {
433 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
434 goto out;
435 }
Runmin Wang7db42962016-06-27 14:35:35 -0700436
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700437 if (((uintptr_t)kernel + (uintptr_t)dtb_offset) < (uintptr_t)kernel) {
438 goto out;
439 }
440 dtb = kernel + dtb_offset;
441 while (((uintptr_t)dtb + sizeof (struct fdt_header)) <
442 (uintptr_t)kernel_end) {
443 struct fdt_header dtb_hdr;
444 UINT32 dtb_size;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800445
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700446 /* the DTB could be unaligned, so extract the header,
447 * and operate on it separately */
448 gBS->CopyMem (&dtb_hdr, dtb, sizeof (struct fdt_header));
449 if (fdt_check_header ((const VOID *)&dtb_hdr) != 0 ||
450 fdt_check_header_ext ((VOID *)&dtb_hdr) != 0 ||
451 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) <
452 (uintptr_t)dtb) ||
453 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) >
454 (uintptr_t)kernel_end))
455 break;
456 dtb_size = fdt_totalsize (&dtb_hdr);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800457
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700458 if (!DeviceTreeCompatible (dtb, dtb_size, dt_entry_queue)) {
459 DEBUG ((EFI_D_VERBOSE, "Error while DTB parse continue with next DTB\n"));
460 if (!GetRticDtb (dtb))
461 DEBUG ((EFI_D_VERBOSE,
462 "Error while DTB parsing RTIC prop continue with next DTB\n"));
463 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530464
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700465 /* goto the next device tree if any */
466 dtb += dtb_size;
467 }
468 best_match_dt_entry = platform_dt_match_best (dt_entry_queue);
469 if (best_match_dt_entry) {
470 bestmatch_tag = (VOID *)best_match_dt_entry->offset;
471 bestmatch_tag_size = best_match_dt_entry->size;
472 DEBUG ((EFI_D_INFO, "Best match DTB tags "
473 "%u/%08x/0x%08x/%x/%x/%x/%x/%x/(offset)0x%08x/"
474 "(size)0x%08x\n",
475 best_match_dt_entry->platform_id, best_match_dt_entry->variant_id,
476 best_match_dt_entry->board_hw_subtype, best_match_dt_entry->soc_rev,
477 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
478 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
479 best_match_dt_entry->offset, best_match_dt_entry->size));
480 DEBUG ((EFI_D_INFO, "Using pmic info 0x%0x/0x%x/0x%x/0x%0x for device "
481 "0x%0x/0x%x/0x%x/0x%0x\n",
482 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
483 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
484 BoardPmicTarget (0), BoardPmicTarget (1), BoardPmicTarget (2),
485 BoardPmicTarget (3)));
486 }
487 /* free queue's memory */
488 list_for_every_entry (&dt_entry_queue->node, dt_node_tmp1, dt_node, node)
489 {
490 if (!dt_node_tmp1) {
491 DEBUG ((EFI_D_VERBOSE, "Current node is the end\n"));
492 break;
493 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800494
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700495 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
496 dt_entry_list_delete (dt_node_tmp1);
497 dt_node_tmp1 = dt_node_tmp2;
498 }
lijuangf71a4842017-07-27 19:26:31 +0800499
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700500 if (bestmatch_tag) {
501 Status = BaseMem (&BaseMemory);
502 if (Status != EFI_SUCCESS) {
503 DEBUG ((EFI_D_ERROR, "Unable to find Base memory for DDR %r\n", Status));
504 FreePool (dt_entry_queue);
505 dt_entry_queue = NULL;
506 goto out;
507 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800508
Venkata Narendra Kumar Gutta00f46852018-11-29 12:38:08 -0800509 RamdiskLoadAddr = SetandGetLoadAddr (NULL, LOAD_ADDR_RAMDISK);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700510 if ((RamdiskLoadAddr - (UINT64)tags) > RamdiskLoadAddr) {
511 DEBUG ((EFI_D_ERROR, "Tags address is not valid\n"));
512 goto out;
513 }
514 if ((RamdiskLoadAddr - (UINT64)tags) < bestmatch_tag_size) {
515 DEBUG ((EFI_D_ERROR, "Tag size is over the limit\n"));
516 goto out;
517 }
518 gBS->CopyMem (tags, bestmatch_tag, bestmatch_tag_size);
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700519 DtbIdx = best_match_dt_entry->Idx;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700520 /* clear out the old DTB magic so kernel doesn't find it */
521 *((UINT32 *)(kernel + dtb_offset)) = 0;
lijuang46df8442017-09-28 19:06:36 +0800522 FreePool (dt_entry_queue);
523 dt_entry_queue = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700524
525 return tags;
526 }
527
528 DEBUG (
529 (EFI_D_ERROR,
530 "DTB offset is incorrect, kernel image does not have appended DTB\n"));
531
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700532out:
533 FreePool (dt_entry_queue);
534 dt_entry_queue = NULL;
535 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800536}
537
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700538STATIC BOOLEAN
Lijuan Gao1259da72021-03-05 10:39:12 +0800539CheckAllBitsSet (UINT64 DtMatchVal)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530540{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700541 return (DtMatchVal & ALL_BITS_SET) == (ALL_BITS_SET);
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530542}
543
Mukesh Ojhafa815352017-11-08 14:43:41 +0530544STATIC VOID
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530545ReadBestPmicMatch (CONST CHAR8 *PmicProp, INT32 PmicMaxIdx,
546 UINT32 PmicEntCount, PmicIdInfo *BestPmicInfo)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530547{
548 UINT32 PmicEntIdx;
549 UINT32 Idx;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530550 PmicIdInfo CurPmicInfo;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530551
Mayank Groverb0076932021-04-30 10:52:45 +0530552 /* Initialize with NONE_MATCH */
553 BestPmicInfo->DtMatchVal = BIT (NONE_MATCH);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530554 for (PmicEntIdx = 0; PmicEntIdx < PmicEntCount; PmicEntIdx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530555 memset (&CurPmicInfo, 0, sizeof (PmicIdInfo));
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530556 for (Idx = 0; Idx < PmicMaxIdx; Idx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530557 CurPmicInfo.DtPmicModel[Idx] =
Mukesh Ojhafa815352017-11-08 14:43:41 +0530558 fdt32_to_cpu (((struct pmic_id *)PmicProp)->pmic_version[Idx]);
559
560 DEBUG ((EFI_D_VERBOSE, "pmic_data[%u].:%x\n", Idx,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530561 CurPmicInfo.DtPmicModel[Idx]));
562 CurPmicInfo.DtPmicRev[Idx] =
563 CurPmicInfo.DtPmicModel[Idx] & PMIC_REV_MASK;
564 CurPmicInfo.DtPmicModel[Idx] =
565 CurPmicInfo.DtPmicModel[Idx] & PMIC_MODEL_MASK;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530566
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530567 if ((CurPmicInfo.DtPmicModel[Idx]) ==
Mukesh Ojhafa815352017-11-08 14:43:41 +0530568 BoardPmicModel (Idx)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530569 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530570 BIT ((PMIC_MATCH_EXACT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530571 } else if (CurPmicInfo.DtPmicModel[Idx] == 0) {
572 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530573 BIT ((PMIC_MATCH_DEFAULT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
574 } else {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530575 CurPmicInfo.DtMatchVal = BIT (NONE_MATCH);
Mayank Groverb0076932021-04-30 10:52:45 +0530576 DEBUG ((EFI_D_VERBOSE, "Pmic model does not match Idx(%u)\n", Idx));
577 goto next;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530578 }
579
Lijuan Gao1259da72021-03-05 10:39:12 +0800580 /* first match the first four pmic revision */
581 if (Idx < PMIC_IDX4) {
582 if (CurPmicInfo.DtPmicRev[Idx] == (BoardPmicTarget (Idx)
583 & PMIC_REV_MASK)) {
584 CurPmicInfo.DtMatchVal |=
585 BIT ((PMIC_MATCH_EXACT_REV_IDX0 + Idx * PMIC_SHIFT_IDX));
586 } else if (CurPmicInfo.DtPmicRev[Idx] <
587 (BoardPmicTarget (Idx) & PMIC_REV_MASK)) {
588 CurPmicInfo.DtMatchVal |= BIT ((PMIC_MATCH_BEST_REV_IDX0 +
589 Idx * PMIC_SHIFT_IDX));
590 } else {
591 DEBUG ((EFI_D_VERBOSE, "Pmic revision does not match\n"));
Mayank Groverb0076932021-04-30 10:52:45 +0530592 goto next;
Lijuan Gao1259da72021-03-05 10:39:12 +0800593 }
Mukesh Ojhafa815352017-11-08 14:43:41 +0530594 }
595 }
596
Lijuan Gao1259da72021-03-05 10:39:12 +0800597 DEBUG ((EFI_D_VERBOSE, "BestPmicInfo.DtMatchVal : 0x%llx"
598 " CurPmicInfo[%u]->DtMatchVal : 0x%llx\n", BestPmicInfo->DtMatchVal,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530599 PmicEntIdx, CurPmicInfo.DtMatchVal));
600 if (BestPmicInfo->DtMatchVal < CurPmicInfo.DtMatchVal) {
601 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530602 sizeof (struct PmicIdInfo));
603 } else if (BestPmicInfo->DtMatchVal ==
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530604 CurPmicInfo.DtMatchVal) {
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530605 for (Idx = 0; Idx < PmicMaxIdx; Idx++) {
606 if (BestPmicInfo->DtPmicRev[Idx] < CurPmicInfo.DtPmicRev[Idx]) {
607 gBS->CopyMem (BestPmicInfo, &CurPmicInfo, sizeof (struct PmicIdInfo));
608 }
Mukesh Ojhafa815352017-11-08 14:43:41 +0530609 }
610 }
Mayank Groverb0076932021-04-30 10:52:45 +0530611next:
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530612 PmicProp += sizeof (UINT32) * PmicMaxIdx;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530613 }
614}
615
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800616STATIC EFI_STATUS GetPlatformMatchDtb (DtInfo * CurDtbInfo,
617 CONST CHAR8 *PlatProp,
618 INT32 LenPlatId,
619 INT32 MinPlatIdLen)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530620{
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530621
lijuangf6b1c5f2018-03-20 13:15:47 +0800622 if (CurDtbInfo == NULL) {
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800623 DEBUG ((EFI_D_VERBOSE, "Input parameters null\n"));
624 return EFI_INVALID_PARAMETER;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700625 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530626
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700627 if (PlatProp && (LenPlatId > 0) && (!(LenPlatId % MinPlatIdLen))) {
628 /*Compare msm-id of the dtb vs Board*/
629 CurDtbInfo->DtPlatformId =
630 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id);
631 DEBUG ((EFI_D_VERBOSE, "Boardsocid = %x, Dtsocid = %x\n",
632 (BoardPlatformRawChipId () & SOC_MASK),
633 (CurDtbInfo->DtPlatformId & SOC_MASK)));
634 if ((BoardPlatformRawChipId () & SOC_MASK) ==
635 (CurDtbInfo->DtPlatformId & SOC_MASK)) {
636 CurDtbInfo->DtMatchVal |= BIT (SOC_MATCH);
637 } else {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530638 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id does not match\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700639 /* If it's neither exact nor default match don't select dtb */
640 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800641 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700642 }
643 /*Compare soc rev of the dtb vs Board*/
644 CurDtbInfo->DtSocRev = fdt32_to_cpu (((struct plat_id *)PlatProp)->soc_rev);
645 DEBUG ((EFI_D_VERBOSE, "BoardSocRev = %x, DtSocRev =%x\n",
646 BoardPlatformChipVersion (), CurDtbInfo->DtSocRev));
647 if (CurDtbInfo->DtSocRev == BoardPlatformChipVersion ()) {
648 CurDtbInfo->DtMatchVal |= BIT (VERSION_EXACT_MATCH);
649 } else if (CurDtbInfo->DtSocRev < BoardPlatformChipVersion ()) {
650 CurDtbInfo->DtMatchVal |= BIT (VERSION_BEST_MATCH);
651 } else if (CurDtbInfo->DtSocRev) {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530652 DEBUG ((EFI_D_VERBOSE, "soc version does not match\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700653 }
654 /*Compare Foundry Id of the dtb vs Board*/
655 CurDtbInfo->DtFoundryId =
656 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id) &
657 FOUNDRY_ID_MASK;
658 DEBUG ((EFI_D_VERBOSE, "BoardFoundry = %x, DtFoundry = %x\n",
659 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT),
660 CurDtbInfo->DtFoundryId));
661 if (CurDtbInfo->DtFoundryId ==
662 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT)) {
663 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_EXACT_MATCH);
664 } else if (CurDtbInfo->DtFoundryId == 0) {
665 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_DEFAULT_MATCH);
666 } else {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530667 DEBUG ((EFI_D_VERBOSE, "soc foundry does not match\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700668 /* If it's neither exact nor default match don't select dtb */
669 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800670 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700671 }
672 } else {
673 DEBUG ((EFI_D_VERBOSE, "qcom, msm-id does not exist (or) is"
674 " (%d) not a multiple of (%d)\n",
675 LenPlatId, MinPlatIdLen));
676 }
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800677 return EFI_SUCCESS;
678}
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530679
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800680STATIC EFI_STATUS GetBoardMatchDtb (DtInfo *CurDtbInfo,
681 CONST CHAR8 *BoardProp,
682 INT32 LenBoardId)
683{
lijuangf6b1c5f2018-03-20 13:15:47 +0800684 if (CurDtbInfo == NULL) {
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800685 DEBUG ((EFI_D_VERBOSE, "Input parameters null\n"));
686 return EFI_INVALID_PARAMETER;
687 }
688
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700689 if (BoardProp && (LenBoardId > 0) && (!(LenBoardId % BOARD_ID_SIZE))) {
690 CurDtbInfo->DtVariantId =
691 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id);
692 CurDtbInfo->DtPlatformSubtype =
693 fdt32_to_cpu (((struct board_id *)BoardProp)->platform_subtype);
694 if (CurDtbInfo->DtPlatformSubtype == 0) {
695 CurDtbInfo->DtPlatformSubtype =
696 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id) >>
697 PLATFORM_SUBTYPE_SHIFT_ID;
698 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530699
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700700 DEBUG ((EFI_D_VERBOSE, "BoardVariant = %x, DtVariant = %x\n",
701 BoardPlatformType (), CurDtbInfo->DtVariantId));
702 CurDtbInfo->DtVariantMajor = CurDtbInfo->DtVariantId & VARIANT_MAJOR_MASK;
703 CurDtbInfo->DtVariantMinor = CurDtbInfo->DtVariantId & VARIANT_MINOR_MASK;
704 CurDtbInfo->DtVariantId = CurDtbInfo->DtVariantId & VARIANT_MASK;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530705
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700706 if (CurDtbInfo->DtVariantId == BoardPlatformType ()) {
707 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MATCH);
708 } else if (CurDtbInfo->DtVariantId) {
709 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not"
710 " match\n"));
711 /* If it's neither exact nor default match don't select dtb */
712 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800713 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700714 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530715
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700716 if (CurDtbInfo->DtVariantMajor == (BoardTargetId () & VARIANT_MAJOR_MASK)) {
717 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_EXACT_MATCH);
718 } else if (CurDtbInfo->DtVariantMajor <
719 (BoardTargetId () & VARIANT_MAJOR_MASK)) {
720 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_BEST_MATCH);
721 } else if (CurDtbInfo->DtVariantMajor) {
722 DEBUG ((EFI_D_VERBOSE, "qcom,board-id major version "
723 "does not match\n"));
724 }
Parth Dixitd4887652017-09-13 22:28:52 +0530725
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700726 if (CurDtbInfo->DtVariantMinor == (BoardTargetId () & VARIANT_MINOR_MASK)) {
727 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_EXACT_MATCH);
728 } else if (CurDtbInfo->DtVariantMinor <
729 (BoardTargetId () & VARIANT_MINOR_MASK)) {
730 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_BEST_MATCH);
731 } else if (CurDtbInfo->DtVariantMinor) {
732 DEBUG ((EFI_D_VERBOSE, "qcom,board-id minor version "
733 "does not match\n"));
734 }
Parth Dixitd4887652017-09-13 22:28:52 +0530735
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700736 DEBUG ((EFI_D_VERBOSE, "BoardSubtype = %x, DtSubType = %x\n",
737 BoardPlatformSubType (), CurDtbInfo->DtPlatformSubtype));
Chandra Sai Chidipudi64ced632020-01-22 12:25:28 +0530738 if ((CurDtbInfo->DtPlatformSubtype & PLATFORM_SUBTYPE_MASK) ==
739 BoardPlatformSubType ()) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700740 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_EXACT_MATCH);
Chandra Sai Chidipudi64ced632020-01-22 12:25:28 +0530741 } else if ((CurDtbInfo->DtPlatformSubtype & PLATFORM_SUBTYPE_MASK) == 0) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700742 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_DEFAULT_MATCH);
jianzhou254e1e02017-11-01 14:52:02 +0800743 } else {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700744 DEBUG ((EFI_D_VERBOSE, "subtype-id doesnot match\n"));
745 /* If it's neither exact nor default match don't select dtb */
746 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800747 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700748 }
Chandra Sai Chidipudi64ced632020-01-22 12:25:28 +0530749
750 if ((CurDtbInfo->DtPlatformSubtype & DDR_MASK) ==
751 (BoardPlatformHlosSubType() & DDR_MASK)) {
752 CurDtbInfo->DtMatchVal |= BIT (DDR_MATCH);
753 } else {
754 DEBUG ((EFI_D_VERBOSE, "ddr size does not match\n"));
755 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700756 } else {
757 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not exist (or) (%d) "
758 "is not a multiple of (%d)\n",
759 LenBoardId, BOARD_ID_SIZE));
760 }
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800761 return EFI_SUCCESS;
762}
763
764/* Dt selection table for quick reference
765 | SNO | Dt Property | CDT Property | Exact | Best | Default |
766 |-----+---------------+-----------------+-------+------+---------+
767 | | qcom, msm-id | | | | |
768 | | | PlatformId | Y | N | N |
769 | | | SocRev | N | Y | N |
770 | | | FoundryId | Y | N | 0 |
771 | | qcom,board-id | | | | |
772 | | | VariantId | Y | N | N |
773 | | | VariantMajor | N | Y | N |
774 | | | VariantMinor | N | Y | N |
775 | | | PlatformSubtype | Y | N | 0 |
776 | | qcom,pmic-id | | | | |
777 | | | PmicModelId | Y | N | 0 |
778 | | | PmicMetalRev | N | Y | N |
779 | | | PmicLayerRev | N | Y | N |
780 | | | PmicVariantRev | N | Y | N |
781*/
lijuang6fa55c02018-06-22 19:19:26 +0800782STATIC BOOLEAN
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800783ReadDtbFindMatch (DtInfo *CurDtbInfo, DtInfo *BestDtbInfo, UINT32 ExactMatch)
784{
785 EFI_STATUS Status;
786 CONST CHAR8 *PlatProp = NULL;
787 CONST CHAR8 *BoardProp = NULL;
788 CONST CHAR8 *PmicProp = NULL;
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530789 CONST CHAR8 *PmicPropSz = NULL;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800790 INT32 LenBoardId;
791 INT32 LenPlatId;
792 INT32 LenPmicId;
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530793 INT32 LenPmicIdSz;
794 INT32 PmicMaxIdx;
795 INT32 PmicEntSz;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800796 INT32 MinPlatIdLen = PLAT_ID_SIZE;
797 INT32 RootOffset = 0;
798 VOID *Dtb = CurDtbInfo->Dtb;
799 UINT32 Idx;
800 UINT32 PmicEntCount;
Bhanuprakash Modem64333302018-09-10 18:58:11 +0530801 UINT32 MsmDataCount;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800802 PmicIdInfo BestPmicInfo;
lijuang6fa55c02018-06-22 19:19:26 +0800803 BOOLEAN FindBestMatch = FALSE;
Bhanuprakash Modem64333302018-09-10 18:58:11 +0530804 DtInfo TempDtbInfo = *CurDtbInfo;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800805
806 memset (&BestPmicInfo, 0, sizeof (PmicIdInfo));
807 /*Ensure MatchVal to 0 initially*/
808 CurDtbInfo->DtMatchVal = 0;
809 RootOffset = fdt_path_offset (Dtb, "/");
810 if (RootOffset < 0) {
811 DEBUG ((EFI_D_ERROR, "Unable to locate root node\n"));
lijuang6fa55c02018-06-22 19:19:26 +0800812 return FALSE;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800813 }
814
815 /* Get the msm-id prop from DTB */
816 PlatProp = (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,msm-id",
817 &LenPlatId);
Bhanuprakash Modem64333302018-09-10 18:58:11 +0530818 if (PlatProp &&
819 (LenPlatId > 0) &&
820 (!(LenPlatId % MinPlatIdLen))) {
821 /*
822 For Multiple soc-id's, save the best SocRev match DT in temp and search
823 for the exact match. If exact match is not found, use best match DT from
824 temp.
825 */
826 MsmDataCount = (LenPlatId / MinPlatIdLen);
827
828 /* Ensure to reset the match value */
829 TempDtbInfo.DtMatchVal = NONE_MATCH;
830
831 for (Idx = 0; Idx < MsmDataCount; Idx++) {
832 /* Ensure MatchVal should be 0 for every match */
833 CurDtbInfo->DtMatchVal = NONE_MATCH;
834 Status = GetPlatformMatchDtb (CurDtbInfo,
835 PlatProp,
836 LenPlatId,
837 MinPlatIdLen);
838 if (Status == EFI_SUCCESS &&
839 CurDtbInfo->DtMatchVal > TempDtbInfo.DtMatchVal) {
840 TempDtbInfo = *CurDtbInfo;
841 }
842 LenPlatId -= PLAT_ID_SIZE;
843 PlatProp += PLAT_ID_SIZE;
844 }
845
846 *CurDtbInfo = TempDtbInfo;
847
848 if (CurDtbInfo->DtMatchVal == NONE_MATCH) {
849 DEBUG ((EFI_D_VERBOSE, "Platform dt prop search failed.\n"));
850 goto cleanup;
851 }
852 } else {
853 DEBUG ((EFI_D_VERBOSE, "qcom, msm-id does not exist (or) is"
854 " (%d) not a multiple of (%d)\n",
855 LenPlatId, MinPlatIdLen));
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800856 }
857
858 /* Get the properties like variant id, subtype from Dtb then compare the
859 * dtb vs Board*/
860 BoardProp = (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,board-id",
861 &LenBoardId);
862 Status = GetBoardMatchDtb (CurDtbInfo, BoardProp, LenBoardId);
863 if (Status != EFI_SUCCESS) {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530864 DEBUG ((EFI_D_VERBOSE, "Board dt prop search failed.\n"));
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800865 goto cleanup;
866 }
Parth Dixitd4887652017-09-13 22:28:52 +0530867
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700868 /*Get the pmic property from Dtb then compare the dtb vs Board*/
869 PmicProp =
870 (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,pmic-id", &LenPmicId);
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530871
872 if ((PmicProp) &&
873 (LenPmicId > 0)) {
874 PmicPropSz =
875 (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,pmic-id-size",
876 &LenPmicIdSz);
877 if ((PmicPropSz) &&
878 (LenPmicIdSz > 0)) {
879 PmicMaxIdx = (fdt32_to_cpu (*((UINT32 *)PmicPropSz)));
880 } else {
881 /* By default support four pmic, qcom,pmic-id = <a, b, c, d>*/
882 PmicMaxIdx = PMIC_IDX4;
883 }
884
885 PmicEntSz = PmicMaxIdx * sizeof (UINT32);
886 if (LenPmicId % PmicEntSz) {
887 DEBUG ((EFI_D_VERBOSE,
888 "LenPmicId(%d) is not multiple of PmicEntSz(%d)\n",
889 LenPmicId, PmicEntSz));
890 goto cleanup;
891 }
892
893 PmicEntCount = LenPmicId / PmicEntSz;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530894 /* Get the best match pmic */
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530895 ReadBestPmicMatch (PmicProp, PmicMaxIdx, PmicEntCount, &BestPmicInfo);
Mayank Groverb0076932021-04-30 10:52:45 +0530896 if (BestPmicInfo.DtMatchVal == BIT (NONE_MATCH)) {
897 CurDtbInfo->DtMatchVal = NONE_MATCH;
898 } else {
899 CurDtbInfo->DtMatchVal |= BestPmicInfo.DtMatchVal;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530900
Mayank Groverb0076932021-04-30 10:52:45 +0530901 for (Idx = 0; Idx < PmicMaxIdx; Idx++) {
902 CurDtbInfo->DtPmicModel[Idx] = BestPmicInfo.DtPmicModel[Idx];
903 CurDtbInfo->DtPmicRev[Idx] = BestPmicInfo.DtPmicRev[Idx];
904 }
905
906 DEBUG ((EFI_D_VERBOSE, "CurDtbInfo->DtMatchVal : 0x%llx "
907 "BestPmicInfo.DtMatchVal :0x%llx\n", CurDtbInfo->DtMatchVal,
908 BestPmicInfo.DtMatchVal));
909 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700910 } else {
Mayank Groverc8ad1e72020-12-02 15:14:00 +0530911 DEBUG ((EFI_D_VERBOSE, "qcom,pmic-id does not exit\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700912 }
Parth Dixitd4887652017-09-13 22:28:52 +0530913
914cleanup:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700915 if (CurDtbInfo->DtMatchVal & BIT (ExactMatch)) {
916 if (BestDtbInfo->DtMatchVal < CurDtbInfo->DtMatchVal) {
917 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
lijuang6fa55c02018-06-22 19:19:26 +0800918 FindBestMatch = TRUE;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700919 } else if (BestDtbInfo->DtMatchVal == CurDtbInfo->DtMatchVal) {
lijuang6fa55c02018-06-22 19:19:26 +0800920 FindBestMatch = TRUE;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700921 if (BestDtbInfo->DtSocRev < CurDtbInfo->DtSocRev) {
922 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
923 } else if (BestDtbInfo->DtVariantMajor < CurDtbInfo->DtVariantMajor) {
924 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
925 } else if (BestDtbInfo->DtVariantMinor < CurDtbInfo->DtVariantMinor) {
926 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
927 } else if (BestDtbInfo->DtPmicRev[0] < CurDtbInfo->DtPmicRev[0]) {
928 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
929 } else if (BestDtbInfo->DtPmicRev[1] < CurDtbInfo->DtPmicRev[1]) {
930 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
931 } else if (BestDtbInfo->DtPmicRev[2] < CurDtbInfo->DtPmicRev[2]) {
932 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
933 } else if (BestDtbInfo->DtPmicRev[3] < CurDtbInfo->DtPmicRev[3]) {
934 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
lijuang6fa55c02018-06-22 19:19:26 +0800935 } else {
936 FindBestMatch = FALSE;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700937 }
938 }
939 }
lijuang6fa55c02018-06-22 19:19:26 +0800940
941 return FindBestMatch;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700942}
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700943/*
944 * For Header Version 2, the arguments Kernel and KernelSize will be
945 * the entire bootimage and the bootimage size.
Raghavendra Rao Anantac3668a22020-01-13 18:20:02 -0800946 * For Header Version 3, Kernel holds the base of the vendor_boot
Raghavendra Rao Ananta9ba062d2019-10-12 11:26:33 -0700947 * image and KernelSize holds its size.
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700948 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700949VOID *
950GetSocDtb (VOID *Kernel, UINT32 KernelSize, UINT32 DtbOffset, VOID *DtbLoadAddr)
951{
952 uintptr_t KernelEnd = (uintptr_t)Kernel + KernelSize;
953 VOID *Dtb = NULL;
954 struct fdt_header DtbHdr;
955 UINT32 DtbSize = 0;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700956 INT32 DtbCount = 0;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700957 DtInfo CurDtbInfo = {0};
958 DtInfo BestDtbInfo = {0};
959 if (!DtbOffset) {
960 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
961 return NULL;
962 }
963
964 if (((uintptr_t)Kernel + (uintptr_t)DtbOffset) < (uintptr_t)Kernel) {
965 return NULL;
966 }
967 Dtb = Kernel + DtbOffset;
968 while (((uintptr_t)Dtb + sizeof (struct fdt_header)) < (uintptr_t)KernelEnd) {
969 /* the DTB could be unaligned, so extract the header,
970 * and operate on it separately */
971 gBS->CopyMem (&DtbHdr, Dtb, sizeof (struct fdt_header));
972 DtbSize = fdt_totalsize ((const VOID *)&DtbHdr);
973 if (fdt_check_header ((const VOID *)&DtbHdr) != 0 ||
974 fdt_check_header_ext ((VOID *)&DtbHdr) != 0 ||
975 ((uintptr_t)Dtb + DtbSize < (uintptr_t)Dtb) ||
976 ((uintptr_t)Dtb + DtbSize > (uintptr_t)KernelEnd))
977 break;
978
979 CurDtbInfo.Dtb = Dtb;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -0700980 if (ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, SOC_MATCH)) {
981 DtbIdx = DtbCount;
982 }
983
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700984 if (CurDtbInfo.DtMatchVal) {
985 if (CurDtbInfo.DtMatchVal & BIT (SOC_MATCH)) {
986 if (CheckAllBitsSet (CurDtbInfo.DtMatchVal)) {
987 DEBUG ((EFI_D_VERBOSE, "Exact DTB match"
988 " found. DTBO search is not "
989 "required\n"));
990 DtboNeed = FALSE;
Parth Dixitd4887652017-09-13 22:28:52 +0530991 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700992 }
993 } else {
994 if (!GetRticDtb (Dtb)) {
995 DEBUG ((EFI_D_VERBOSE, "Error while DTB parsing"
996 " RTIC prop continue with next DTB\n"));
997 }
998 }
999
1000 DEBUG ((EFI_D_VERBOSE, "Bestmatch = %x\n", BestDtbInfo.DtMatchVal));
1001 Dtb += DtbSize;
Prakruthi Deepak Heragu9c385aa2019-03-20 10:54:29 -07001002 DtbCount++;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001003 }
1004
1005 if (!BestDtbInfo.Dtb) {
1006 DEBUG ((EFI_D_ERROR, "No match found for Soc Dtb type\n"));
1007 return NULL;
1008 }
1009
1010 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301011}
1012
Mayank Grover98dcd672019-02-05 14:46:25 +05301013/*
1014 Function to extract Dtb from user dtbo partition.
1015*/
1016EFI_STATUS
1017GetOvrdDtb ( VOID **DtboImgBuffer)
1018{
1019 struct DtboTableHdr *DtboTableHdr = NULL;
1020 struct DtboTableEntry *DtboTableEntry = NULL;
1021 VOID *OvrdDtb = NULL;
1022 UINT32 DtboTableEntriesCount = 0;
1023 UINT32 DtboTableEntryOffset = 0;
1024 EFI_STATUS Status = EFI_SUCCESS;
1025 UINT32 DtboImgSz = 0;
1026 CHAR16 PtnName[MAX_GPT_NAME_SIZE] = {0};
1027
1028 /** Get size of user_dtbo partition **/
1029 UINT32 BlkIOAttrib = 0;
1030 PartiSelectFilter HandleFilter;
1031 UINT32 MaxHandles = 1;
1032 EFI_BLOCK_IO_PROTOCOL *BlockIo = NULL;
1033 HandleInfo HandleInfoList[1];
1034
1035 GUARD ( StrnCpyS (PtnName,
1036 MAX_GPT_NAME_SIZE,
1037 (CONST CHAR16 *)L"user_dtbo",
1038 (UINTN)StrLen (L"user_dtbo")));
1039
1040 BlkIOAttrib |= BLK_IO_SEL_PARTITIONED_MBR;
1041 BlkIOAttrib |= BLK_IO_SEL_PARTITIONED_GPT;
1042 BlkIOAttrib |= BLK_IO_SEL_MEDIA_TYPE_NON_REMOVABLE;
1043 BlkIOAttrib |= BLK_IO_SEL_MATCH_PARTITION_LABEL;
1044
1045 HandleFilter.RootDeviceType = NULL;
1046 HandleFilter.PartitionLabel = NULL;
1047 HandleFilter.VolumeName = NULL;
1048 HandleFilter.PartitionLabel = PtnName;
1049
1050 Status =
1051 GetBlkIOHandles (BlkIOAttrib, &HandleFilter, HandleInfoList, &MaxHandles);
1052 if (Status != EFI_SUCCESS ||
1053 MaxHandles != 1) {
1054 DEBUG ((EFI_D_ERROR,
1055 "Override DTB: GetBlkIOHandles failed loading user_dtbo!\n"));
1056 Status = EFI_LOAD_ERROR;
1057 goto err;
1058 }
1059
1060 BlockIo = HandleInfoList[0].BlkIo;
Lijuan Gaobe74b9e2020-09-21 20:29:27 +08001061 DtboImgSz = GetPartitionSize (BlockIo);
1062 if (!DtboImgSz) {
1063 Status = EFI_BAD_BUFFER_SIZE;
1064 goto err;
1065 }
Mayank Grover98dcd672019-02-05 14:46:25 +05301066 *DtboImgBuffer = AllocateZeroPool (DtboImgSz);
1067 if (*DtboImgBuffer == NULL) {
1068 DEBUG ((EFI_D_ERROR, "Override DTB: Buffer allocation failure\n"));
1069 Status = EFI_OUT_OF_RESOURCES;
1070 goto err;
1071 }
1072
1073 /** Load user_dtbo image. **/
1074 Status = LoadImageFromPartition (*DtboImgBuffer, &DtboImgSz, PtnName);
1075 if (Status != EFI_SUCCESS) {
1076 DEBUG ((EFI_D_ERROR, "Override DTB: DtboImgBuffer loading falied\n"));
1077 return Status;
1078 }
1079
1080 DtboTableHdr = (struct DtboTableHdr *)*DtboImgBuffer;
1081 DtboTableEntryOffset = fdt32_to_cpu (DtboTableHdr->DtEntryOffset);
1082 if (CHECK_ADD64 ((UINT64)*DtboImgBuffer, DtboTableEntryOffset)) {
1083 DEBUG ((EFI_D_ERROR,
1084 "Override DTB: Integer overflow detected Dtbo address\n"));
1085 Status = EFI_INVALID_PARAMETER;
1086 goto err;
1087 }
1088
1089 DtboTableEntry =
1090 (struct DtboTableEntry *)(*DtboImgBuffer + DtboTableEntryOffset);
1091 if (!DtboTableEntry) {
1092 DEBUG ((EFI_D_ERROR, "Override DTB: No proper DtTable\n"));
1093 Status = EFI_INVALID_PARAMETER;
1094 goto err;
1095 }
1096
1097 // Support only one dtb in user dtbo image.
1098 DtboTableEntriesCount = fdt32_to_cpu (DtboTableHdr->DtEntryCount);
1099 if (DtboTableEntriesCount > 1) {
1100 DEBUG ((EFI_D_ERROR,
1101 "Override DTB: Exceeding maximum supported dtb count in Image\n"));
1102 Status = EFI_INVALID_PARAMETER;
1103 goto err;
1104 }
1105
1106 OvrdDtb = *DtboImgBuffer + fdt32_to_cpu (DtboTableEntry->DtOffset);
1107 if (fdt_check_header (OvrdDtb) ||
1108 fdt_check_header_ext (OvrdDtb)) {
1109 DEBUG ((EFI_D_ERROR, "Override DTB: No Valid DTB in image\n"));
1110 Status = EFI_INVALID_PARAMETER;
1111 goto err;
1112 }
1113 *DtboImgBuffer = OvrdDtb;
1114 return Status;
1115
1116err:
1117 if (*DtboImgBuffer) {
1118 FreePool (*DtboImgBuffer);
1119 }
1120 return Status;
1121}
1122
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001123VOID *
1124GetBoardDtb (BootInfo *Info, VOID *DtboImgBuffer)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301125{
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001126 struct DtboTableHdr *DtboTableHdr = DtboImgBuffer;
1127 struct DtboTableEntry *DtboTableEntry = NULL;
1128 UINT32 DtboCount = 0;
1129 VOID *BoardDtb = NULL;
1130 UINT32 DtboTableEntriesCount = 0;
1131 UINT32 FirstDtboTableEntryOffset = 0;
1132 DtInfo CurDtbInfo = {0};
1133 DtInfo BestDtbInfo = {0};
lijuang6fa55c02018-06-22 19:19:26 +08001134 BOOLEAN FindBestDtb = FALSE;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301135
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001136 if (!DtboImgBuffer) {
1137 DEBUG ((EFI_D_ERROR, "Dtbo Img buffer is NULL\n"));
1138 return NULL;
1139 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301140
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001141 FirstDtboTableEntryOffset = fdt32_to_cpu (DtboTableHdr->DtEntryOffset);
1142 if (CHECK_ADD64 ((UINT64)DtboImgBuffer, FirstDtboTableEntryOffset)) {
1143 DEBUG ((EFI_D_ERROR, "Integer overflow deteced with Dtbo address\n"));
1144 return NULL;
1145 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301146
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001147 DtboTableEntry =
1148 (struct DtboTableEntry *)(DtboImgBuffer + FirstDtboTableEntryOffset);
1149 if (!DtboTableEntry) {
1150 DEBUG ((EFI_D_ERROR, "No proper DtTable\n"));
1151 return NULL;
1152 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +05301153
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001154 DtboTableEntriesCount = fdt32_to_cpu (DtboTableHdr->DtEntryCount);
1155 for (DtboCount = 0; DtboCount < DtboTableEntriesCount; DtboCount++) {
1156 if (CHECK_ADD64 ((UINT64)DtboImgBuffer,
1157 fdt32_to_cpu (DtboTableEntry->DtOffset))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +05301158 DEBUG ((EFI_D_ERROR, "Integer overflow detected with Dtbo address\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001159 return NULL;
1160 }
1161 BoardDtb = DtboImgBuffer + fdt32_to_cpu (DtboTableEntry->DtOffset);
1162 if (fdt_check_header (BoardDtb) || fdt_check_header_ext (BoardDtb)) {
1163 DEBUG ((EFI_D_ERROR, "No Valid Dtb\n"));
1164 break;
1165 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +05301166
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001167 CurDtbInfo.Dtb = BoardDtb;
lijuang6fa55c02018-06-22 19:19:26 +08001168 FindBestDtb = ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, VARIANT_MATCH);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001169 DEBUG ((EFI_D_VERBOSE, "Dtbo count = %u LocalBoardDtMatch = %x"
1170 "\n",
1171 DtboCount, CurDtbInfo.DtMatchVal));
lijuang6fa55c02018-06-22 19:19:26 +08001172
1173 if (FindBestDtb) {
1174 DtboIdx = DtboCount;
1175 }
1176
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001177 DtboTableEntry++;
1178 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301179
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001180 if (!BestDtbInfo.Dtb) {
1181 DEBUG ((EFI_D_ERROR, "Unable to find the Board Dtb\n"));
1182 return NULL;
1183 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301184
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001185 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301186}
1187
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001188/* Returns 0 if the device tree is valid. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001189int
1190DeviceTreeValidate (UINT8 *DeviceTreeBuff,
1191 UINT32 PageSize,
1192 UINT32 *DeviceTreeSize)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001193{
lijuangc336a292017-08-22 19:48:49 +08001194 UINT32 dt_entry_size;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001195 UINT64 hdr_size;
1196 struct dt_table *table;
1197 if (DeviceTreeSize) {
1198 table = (struct dt_table *)DeviceTreeBuff;
1199 if (table->magic != DEV_TREE_MAGIC) {
1200 // bad magic in device tree table
1201 return -1;
1202 }
1203 if (table->version == DEV_TREE_VERSION_V1) {
1204 dt_entry_size = sizeof (struct dt_entry_v1);
1205 } else if (table->version == DEV_TREE_VERSION_V2) {
1206 dt_entry_size = sizeof (struct dt_entry_v2);
1207 } else if (table->version == DEV_TREE_VERSION_V3) {
1208 dt_entry_size = sizeof (struct dt_entry);
1209 } else {
1210 // unsupported dt version
1211 return -1;
1212 }
1213 hdr_size =
1214 ((UINT64)table->num_entries * dt_entry_size) + DEV_TREE_HEADER_SIZE;
1215 // hdr_size = ROUNDUP(hdr_size, PageSize);
1216 hdr_size = EFI_SIZE_TO_PAGES (hdr_size);
1217 if (hdr_size > MAX_UINT64)
1218 return -1;
1219 else
1220 *DeviceTreeSize = hdr_size & MAX_UINT64;
1221 // dt_entry_ptr = (struct dt_entry *)((CHAR8 *)table +
1222 // DEV_TREE_HEADER_SIZE);
1223 // table_ptr = dt_entry_ptr;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001224
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001225 DEBUG ((EFI_D_ERROR, "DT Total number of entries: %d, DTB version: %d\n",
1226 table->num_entries, table->version));
1227 }
1228 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001229}
1230
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001231STATIC int
1232platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
1233 struct dt_entry_node *dt_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001234{
Chandra Sai Chidipudi64ced632020-01-22 12:25:28 +05301235 UINT32 cur_dt_hlos_ddr;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001236 UINT32 cur_dt_hw_platform;
1237 UINT32 cur_dt_hw_subtype;
1238 UINT32 cur_dt_msm_id;
1239 dt_node *dt_node_tmp = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001240
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001241 /* Platform-id
1242 * bit no |31 24|23 16|15 0|
1243 * |reserved|foundry-id|msm-id|
1244 */
1245 cur_dt_msm_id = (cur_dt_entry->platform_id & 0x0000ffff);
1246 cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
1247 cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001248
Chandra Sai Chidipudi64ced632020-01-22 12:25:28 +05301249 /* Bits 10:8 contain ddr information */
1250 cur_dt_hlos_ddr = (cur_dt_entry->board_hw_subtype & 0x700);
1251
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001252 /* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
1253 * soc, board major/minor, pmic major/minor must less than board info
1254 * 2. find the matched DTB then return 1
1255 * 3. otherwise return 0
1256 */
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001257
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001258 if ((cur_dt_msm_id == (BoardPlatformRawChipId () & 0x0000ffff)) &&
1259 (cur_dt_hw_platform == BoardPlatformType ()) &&
1260 (cur_dt_hw_subtype == BoardPlatformSubType ()) &&
Chandra Sai Chidipudi64ced632020-01-22 12:25:28 +05301261 (cur_dt_hlos_ddr == (BoardPlatformHlosSubType() & 0x700)) &&
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001262 (cur_dt_entry->soc_rev <= BoardPlatformChipVersion ()) &&
1263 ((cur_dt_entry->variant_id & 0x00ffff00) <=
1264 (BoardTargetId () & 0x00ffff00)) &&
1265 (cur_dt_entry->pmic_rev[0] <= BoardPmicTarget (0)) &&
1266 (cur_dt_entry->pmic_rev[1] <= BoardPmicTarget (1)) &&
1267 (cur_dt_entry->pmic_rev[2] <= BoardPmicTarget (2)) &&
1268 (cur_dt_entry->pmic_rev[3] <= BoardPmicTarget (3))) {
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001269
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001270 dt_node_tmp = dt_entry_list_init ();
1271 if (!dt_node_tmp) {
1272 DEBUG ((EFI_D_ERROR, "dt_node_tmp is NULL\n"));
1273 return 0;
1274 }
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +05301275
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001276 gBS->CopyMem ((VOID *)dt_node_tmp->dt_entry_m, (VOID *)cur_dt_entry,
1277 sizeof (struct dt_entry));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001278
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001279 DEBUG (
1280 (EFI_D_VERBOSE,
1281 "Add DTB entry 0x%x/%08x/0x%08x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
1282 dt_node_tmp->dt_entry_m->platform_id,
1283 dt_node_tmp->dt_entry_m->variant_id,
1284 dt_node_tmp->dt_entry_m->board_hw_subtype,
1285 dt_node_tmp->dt_entry_m->soc_rev, dt_node_tmp->dt_entry_m->pmic_rev[0],
1286 dt_node_tmp->dt_entry_m->pmic_rev[1],
1287 dt_node_tmp->dt_entry_m->pmic_rev[2],
1288 dt_node_tmp->dt_entry_m->pmic_rev[3], dt_node_tmp->dt_entry_m->offset,
1289 dt_node_tmp->dt_entry_m->size));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001290
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001291 insert_dt_entry_in_queue (dt_list, dt_node_tmp);
1292 return 1;
1293 }
1294 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001295}
1296
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001297int
1298platform_dt_absolute_compat_match (struct dt_entry_node *dt_list,
1299 UINT32 dtb_info)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001300{
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001301 struct dt_entry_node *dt_node_tmp1 = NULL;
1302 struct dt_entry_node *dt_node_tmp2 = NULL;
1303 UINT32 current_info = 0;
1304 UINT32 board_info = 0;
1305 UINT32 best_info = 0;
1306 UINT32 current_pmic_model[4] = {0, 0, 0, 0};
1307 UINT32 board_pmic_model[4] = {0, 0, 0, 0};
1308 UINT32 best_pmic_model[4] = {0, 0, 0, 0};
1309 UINT32 delete_current_dt = 0;
1310 UINT32 i;
1311
1312 /* start to select the exact entry
1313 * default to exact match 0, if find current DTB entry info is the same as
1314 * board info,
1315 * then exact match board info.
1316 */
1317 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1318 {
1319 if (!dt_node_tmp1) {
1320 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1321 break;
1322 }
1323 switch (dtb_info) {
1324 case DTB_FOUNDRY:
1325 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1326 board_info = BoardPlatformFoundryId () << 16;
1327 break;
Chandra Sai Chidipudi3b1450c2020-02-07 15:06:15 +05301328 case DTB_DDR:
1329 current_info = ((dt_node_tmp1->dt_entry_m->board_hw_subtype) & 0x700);
1330 board_info = (BoardPlatformHlosSubType () & 0x700);
1331 break;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001332 case DTB_PMIC_MODEL:
1333 for (i = 0; i < 4; i++) {
1334 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1335 board_pmic_model[i] = BoardPmicModel (i);
1336 }
1337 break;
1338 default:
1339 DEBUG ((EFI_D_ERROR,
1340 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1341 return 0;
1342 }
1343
1344 if (dtb_info == DTB_PMIC_MODEL) {
1345 if ((current_pmic_model[0] == board_pmic_model[0]) &&
1346 (current_pmic_model[1] == board_pmic_model[1]) &&
1347 (current_pmic_model[2] == board_pmic_model[2]) &&
1348 (current_pmic_model[3] == board_pmic_model[3])) {
1349
1350 for (i = 0; i < 4; i++) {
1351 best_pmic_model[i] = current_pmic_model[i];
1352 }
1353 break;
1354 }
1355 } else {
1356 if (current_info == board_info) {
1357 best_info = current_info;
1358 break;
1359 }
1360 }
1361 }
1362
1363 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1364 {
1365 if (!dt_node_tmp1) {
1366 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1367 break;
1368 }
1369 switch (dtb_info) {
1370 case DTB_FOUNDRY:
1371 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1372 break;
Chandra Sai Chidipudi3b1450c2020-02-07 15:06:15 +05301373 case DTB_DDR:
1374 current_info = ((dt_node_tmp1->dt_entry_m->board_hw_subtype) & 0x700);
1375 break;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001376 case DTB_PMIC_MODEL:
1377 for (i = 0; i < 4; i++) {
1378 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1379 }
1380 break;
1381 default:
1382 DEBUG ((EFI_D_ERROR,
1383 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1384 return 0;
1385 }
1386
1387 if (dtb_info == DTB_PMIC_MODEL) {
1388 if ((current_pmic_model[0] != best_pmic_model[0]) ||
1389 (current_pmic_model[1] != best_pmic_model[1]) ||
1390 (current_pmic_model[2] != best_pmic_model[2]) ||
1391 (current_pmic_model[3] != best_pmic_model[3])) {
1392
1393 delete_current_dt = 1;
1394 }
1395 } else {
1396 if (current_info != best_info) {
1397 delete_current_dt = 1;
1398 }
1399 }
1400
1401 if (delete_current_dt) {
1402 DEBUG (
1403 (EFI_D_VERBOSE,
1404 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1405 dt_node_tmp1->dt_entry_m->platform_id,
1406 dt_node_tmp1->dt_entry_m->variant_id,
1407 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1408 dt_node_tmp1->dt_entry_m->soc_rev,
1409 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1410 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1411 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1412 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1413 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1414
1415 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1416 dt_entry_list_delete (dt_node_tmp1);
1417 dt_node_tmp1 = dt_node_tmp2;
1418 delete_current_dt = 0;
1419 }
1420 }
1421
1422 return 1;
1423}
1424
1425int
1426update_dtb_entry_node (struct dt_entry_node *dt_list, UINT32 dtb_info)
1427{
1428 struct dt_entry_node *dt_node_tmp1 = NULL;
1429 struct dt_entry_node *dt_node_tmp2 = NULL;
1430 UINT32 current_info = 0;
1431 UINT32 board_info = 0;
1432 UINT32 best_info = 0;
1433
1434 /* start to select the best entry*/
1435 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1436 {
1437 if (!dt_node_tmp1) {
1438 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1439 break;
1440 }
1441 switch (dtb_info) {
1442 case DTB_SOC:
1443 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1444 board_info = BoardPlatformChipVersion ();
1445 break;
1446 case DTB_MAJOR_MINOR:
1447 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1448 board_info = BoardTargetId () & 0x00ffff00;
1449 break;
1450 case DTB_PMIC0:
1451 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1452 board_info = BoardPmicTarget (0);
1453 break;
1454 case DTB_PMIC1:
1455 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1456 board_info = BoardPmicTarget (1);
1457 break;
1458 case DTB_PMIC2:
1459 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1460 board_info = BoardPmicTarget (2);
1461 break;
1462 case DTB_PMIC3:
1463 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1464 board_info = BoardPmicTarget (3);
1465 break;
1466 default:
1467 DEBUG ((EFI_D_ERROR,
1468 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1469 return 0;
1470 }
1471
1472 if (current_info == board_info) {
1473 best_info = current_info;
1474 break;
1475 }
1476 if ((current_info < board_info) && (current_info > best_info)) {
1477 best_info = current_info;
1478 }
1479 if (current_info < best_info) {
1480 DEBUG (
1481 (EFI_D_ERROR,
1482 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1483 dt_node_tmp1->dt_entry_m->platform_id,
1484 dt_node_tmp1->dt_entry_m->variant_id,
1485 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1486 dt_node_tmp1->dt_entry_m->soc_rev,
1487 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1488 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1489 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1490 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1491 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1492
1493 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1494 dt_entry_list_delete (dt_node_tmp1);
1495 dt_node_tmp1 = dt_node_tmp2;
1496 }
1497 }
1498
1499 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1500 {
1501 if (!dt_node_tmp1) {
1502 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1503 break;
1504 }
1505 switch (dtb_info) {
1506 case DTB_SOC:
1507 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1508 break;
1509 case DTB_MAJOR_MINOR:
1510 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1511 break;
1512 case DTB_PMIC0:
1513 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1514 break;
1515 case DTB_PMIC1:
1516 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1517 break;
1518 case DTB_PMIC2:
1519 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1520 break;
1521 case DTB_PMIC3:
1522 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1523 break;
1524 default:
1525 DEBUG ((EFI_D_ERROR,
1526 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1527 return 0;
1528 }
1529
1530 if (current_info != best_info) {
1531 DEBUG (
1532 (EFI_D_VERBOSE,
1533 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1534 dt_node_tmp1->dt_entry_m->platform_id,
1535 dt_node_tmp1->dt_entry_m->variant_id,
1536 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1537 dt_node_tmp1->dt_entry_m->soc_rev,
1538 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1539 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1540 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1541 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1542 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1543
1544 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1545 dt_entry_list_delete (dt_node_tmp1);
1546 dt_node_tmp1 = dt_node_tmp2;
1547 }
1548 }
1549 return 1;
1550}
1551
1552STATIC struct dt_entry *
1553platform_dt_match_best (struct dt_entry_node *dt_list)
1554{
1555 struct dt_entry_node *dt_node_tmp1 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001556
lijuangc336a292017-08-22 19:48:49 +08001557 /* check Foundry id
1558 * the foundry id must exact match board founddry id, this is compatibility
1559 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1560 */
1561 platform_dt_absolute_compat_match (dt_list, DTB_FOUNDRY);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001562
Chandra Sai Chidipudi3b1450c2020-02-07 15:06:15 +05301563 /* check DDR type
1564 * the DDR type must exact match board DDR tpe, this is compatibility
1565 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1566 */
1567 platform_dt_absolute_compat_match (dt_list, DTB_DDR);
1568
lijuangc336a292017-08-22 19:48:49 +08001569 /* check PMIC model
1570 * the PMIC model must exact match board PMIC model, this is compatibility
1571 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1572 */
1573 platform_dt_absolute_compat_match (dt_list, DTB_PMIC_MODEL);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001574
lijuangc336a292017-08-22 19:48:49 +08001575 /* check soc version
1576 * the suitable soc version must less than or equal to board soc version
1577 */
1578 update_dtb_entry_node (dt_list, DTB_SOC);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001579
lijuangc336a292017-08-22 19:48:49 +08001580 /*check major and minor version
1581 * the suitable major&minor version must less than or equal to board
1582 * major&minor version
1583 */
1584 update_dtb_entry_node (dt_list, DTB_MAJOR_MINOR);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001585
lijuangc336a292017-08-22 19:48:49 +08001586 /*check pmic info
1587 * the suitable pmic major&minor info must less than or equal to board pmic
1588 * major&minor version
1589 */
1590 update_dtb_entry_node (dt_list, DTB_PMIC0);
1591 update_dtb_entry_node (dt_list, DTB_PMIC1);
1592 update_dtb_entry_node (dt_list, DTB_PMIC2);
1593 update_dtb_entry_node (dt_list, DTB_PMIC3);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001594
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001595 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1596 {
1597 if (!dt_node_tmp1) {
1598 DEBUG ((EFI_D_ERROR, "ERROR: Couldn't find the suitable DTB!\n"));
1599 return NULL;
1600 }
1601 if (dt_node_tmp1->dt_entry_m)
1602 return dt_node_tmp1->dt_entry_m;
1603 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001604
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001605 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001606}
Bhanuprakash Modemed797c72018-09-05 20:39:07 +05301607
1608BOOLEAN
1609AppendToDtList (struct fdt_entry_node **DtList,
1610 UINT64 Address,
1611 UINT64 Size) {
1612 struct fdt_entry_node *Current = *DtList;
1613
1614 if (*DtList == NULL) {
1615 DEBUG ((EFI_D_VERBOSE, "DTs list: NULL\n"));
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +05301616 Current = AllocateZeroPool (sizeof (struct fdt_entry_node));
Bhanuprakash Modemed797c72018-09-05 20:39:07 +05301617 if (!Current) {
1618 return FALSE;
1619 }
1620
1621 Current->address = Address;
1622 Current->size = Size;
1623 Current->next = NULL;
1624 *DtList = Current;
1625 return TRUE;
1626 } else {
1627
1628 while (Current->next != NULL) {
1629 Current = Current->next;
1630 }
1631
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +05301632 Current->next = AllocateZeroPool (sizeof (struct fdt_entry_node));
Bhanuprakash Modemed797c72018-09-05 20:39:07 +05301633 if (!Current->next) {
1634 return FALSE;
1635 }
1636 Current->next->address = Address;
1637 Current->next->size = Size;
1638 Current->next->next = NULL;
1639 return TRUE;
1640 }
1641}
1642
1643VOID DeleteDtList (struct fdt_entry_node** DtList)
1644{
1645 struct fdt_entry_node *Current = *DtList;
1646 struct fdt_entry_node *Next;
1647
1648 while (Current != NULL) {
1649 Next = Current->next;
1650 FreePool (Current);
1651 Current = Next;
1652 }
1653
1654 *DtList = NULL;
1655}