blob: 72ccbc081f6df9986799853fab1e5f848b122447 [file] [log] [blame]
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +05301/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#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
lijuangf0bbcad2017-08-16 16:59:18 +080051BOOLEAN GetDtboNeeded (VOID)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053052{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070053 return DtboNeed;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053054}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080055/* Add function to allocate dt entry list, used for recording
56 * the entry which conform to platform_dt_absolute_match()
57 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -070058static struct dt_entry_node *dt_entry_list_init (VOID)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080059{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070060 struct dt_entry_node *dt_node_member = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080061
Jeevan Shriram17f173d2017-10-24 22:11:07 -070062 dt_node_member =
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +053063 (struct dt_entry_node *)AllocateZeroPool (sizeof (struct dt_entry_node));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080064
Jeevan Shriram17f173d2017-10-24 22:11:07 -070065 if (!dt_node_member) {
66 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_node_member\n"));
67 return NULL;
68 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080069
Jeevan Shriram17f173d2017-10-24 22:11:07 -070070 list_clear_node (&dt_node_member->node);
71 dt_node_member->dt_entry_m =
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +053072 (struct dt_entry *)AllocateZeroPool (sizeof (struct dt_entry));
Jeevan Shriram17f173d2017-10-24 22:11:07 -070073 if (!dt_node_member->dt_entry_m) {
74 DEBUG ((EFI_D_ERROR,
75 "Failed to allocate memory for dt_node_member->dt_entry_m\n"));
76 FreePool (dt_node_member);
77 dt_node_member = NULL;
78 return NULL;
79 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080080
Jeevan Shriram17f173d2017-10-24 22:11:07 -070081 return dt_node_member;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080082}
83
Jeevan Shriram17f173d2017-10-24 22:11:07 -070084static VOID
85insert_dt_entry_in_queue (struct dt_entry_node *dt_list,
86 struct dt_entry_node *dt_node_member)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080087{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070088 list_add_tail (&dt_list->node, &dt_node_member->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080089}
90
Jeevan Shriram17f173d2017-10-24 22:11:07 -070091static VOID
92dt_entry_list_delete (struct dt_entry_node *dt_node_member)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080093{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070094 if (list_in_list (&dt_node_member->node)) {
95 list_delete (&dt_node_member->node);
96 FreePool (dt_node_member->dt_entry_m);
97 dt_node_member->dt_entry_m = NULL;
98 FreePool (dt_node_member);
99 dt_node_member = NULL;
100 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800101}
102
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700103static BOOLEAN
104DeviceTreeCompatible (VOID *dtb,
105 UINT32 dtb_size,
106 struct dt_entry_node *dtb_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800107{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700108 int root_offset;
109 const VOID *prop = NULL;
110 const char *plat_prop = NULL;
111 const char *board_prop = NULL;
112 const char *pmic_prop = NULL;
113 char *model = NULL;
114 struct dt_entry *dt_entry_array = NULL;
115 struct board_id *board_data = NULL;
116 struct plat_id *platform_data = NULL;
117 struct pmic_id *pmic_data = NULL;
118 int len;
119 int len_board_id;
120 int len_plat_id;
121 int min_plat_id_len = 0;
122 int len_pmic_id;
123 UINT32 dtb_ver;
jianzhoue687ba82017-11-27 16:08:51 +0800124 UINT64 NumEntries = 0;
125 UINT64 i;
126 UINT32 j, k, n;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700127 UINT32 msm_data_count;
128 UINT32 board_data_count;
129 UINT32 pmic_data_count;
130 BOOLEAN Result = FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800131
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700132 root_offset = fdt_path_offset (dtb, "/");
133 if (root_offset < 0)
134 return FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800135
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700136 prop = fdt_getprop (dtb, root_offset, "model", &len);
137 if (prop && len > 0) {
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530138 model = (char *)AllocateZeroPool (sizeof (char) * len);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700139 if (!model) {
140 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for model\n"));
141 return FALSE;
142 }
143 AsciiStrnCpyS (model, (sizeof (CHAR8) * len), prop, len);
144 } else {
145 DEBUG ((EFI_D_ERROR, "model does not exist in device tree\n"));
146 }
147 /* Find the pmic-id prop from DTB , if pmic-id is present then
148 * the DTB is version 3, otherwise find the board-id prop from DTB ,
149 * if board-id is present then the DTB is version 2 */
150 pmic_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,pmic-id",
151 &len_pmic_id);
152 board_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,board-id",
153 &len_board_id);
154 if (pmic_prop && (len_pmic_id > 0) && board_prop && (len_board_id > 0)) {
155 if ((len_pmic_id % PMIC_ID_SIZE) || (len_board_id % BOARD_ID_SIZE)) {
156 DEBUG ((EFI_D_ERROR, "qcom,pmic-id (%d) or qcom,board-id(%d) in device "
157 "tree is not a multiple of (%d %d)\n",
158 len_pmic_id, len_board_id, PMIC_ID_SIZE, BOARD_ID_SIZE));
159 goto Exit;
160 }
161 dtb_ver = DEV_TREE_VERSION_V3;
162 min_plat_id_len = PLAT_ID_SIZE;
163 } else if (board_prop && len_board_id > 0) {
164 if (len_board_id % BOARD_ID_SIZE) {
165 DEBUG ((EFI_D_ERROR,
166 "qcom,pmic-id (%d) in device tree is not a multiple of (%d)\n",
167 len_board_id, BOARD_ID_SIZE));
168 goto Exit;
169 }
170 dtb_ver = DEV_TREE_VERSION_V2;
171 min_plat_id_len = PLAT_ID_SIZE;
172 } else {
173 dtb_ver = DEV_TREE_VERSION_V1;
174 min_plat_id_len = DT_ENTRY_V1_SIZE;
175 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800176
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700177 /* Get the msm-id prop from DTB */
178 plat_prop =
179 (const char *)fdt_getprop (dtb, root_offset, "qcom,msm-id", &len_plat_id);
180 if (!plat_prop || len_plat_id <= 0) {
181 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id entry not found\n"));
182 goto Exit;
183 } else if (len_plat_id % min_plat_id_len) {
184 DEBUG ((EFI_D_ERROR,
185 "qcom, msm-id in device tree is (%d) not a multiple of (%d)\n",
186 len_plat_id, min_plat_id_len));
187 goto Exit;
188 }
189 if (dtb_ver == DEV_TREE_VERSION_V2 || dtb_ver == DEV_TREE_VERSION_V3) {
190 board_data_count = (len_board_id / BOARD_ID_SIZE);
191 msm_data_count = (len_plat_id / PLAT_ID_SIZE);
192 /* If dtb version is v2.0, the pmic_data_count will be <= 0 */
193 pmic_data_count = (len_pmic_id / PMIC_ID_SIZE);
194
195 /* If we are using dtb v3.0, then we have split board, msm & pmic data in
196 * the DTB
197 * If we are using dtb v2.0, then we have split board & msmdata in the DTB
198 */
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530199 board_data = (struct board_id *)AllocateZeroPool (
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700200 sizeof (struct board_id) * (len_board_id / BOARD_ID_SIZE));
201 if (!board_data) {
202 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for board_data\n"));
203 goto Exit;
204 }
205
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530206 platform_data = (struct plat_id *)AllocateZeroPool (
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700207 sizeof (struct plat_id) * (len_plat_id / PLAT_ID_SIZE));
208 if (!platform_data) {
209 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for platform_data\n"));
210 goto Exit;
211 }
212 if (dtb_ver == DEV_TREE_VERSION_V3) {
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530213 pmic_data = (struct pmic_id *)AllocateZeroPool (sizeof (struct pmic_id) *
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700214 (len_pmic_id / PMIC_ID_SIZE));
215 if (!pmic_data) {
216 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for pmic_data\n"));
lijuang46df8442017-09-28 19:06:36 +0800217 goto Exit;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700218 }
219 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800220
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700221 /* Extract board data from DTB */
222 for (i = 0; i < board_data_count; i++) {
223 board_data[i].variant_id =
224 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id);
225 board_data[i].platform_subtype =
226 fdt32_to_cpu (((struct board_id *)board_prop)->platform_subtype);
227 /* For V2/V3 version of DTBs we have platform version field as part
228 * of variant ID, in such case the subtype will be mentioned as 0x0
229 * As the qcom, board-id = <0xSSPMPmPH, 0x0>
230 * SS -- Subtype
231 * PM -- Platform major version
232 * Pm -- Platform minor version
233 * PH -- Platform hardware CDP/MTP
234 * In such case to make it compatible with LK algorithm move the subtype
235 * from variant_id to subtype field
236 */
237 if (board_data[i].platform_subtype == 0)
238 board_data[i].platform_subtype =
239 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id) >> 0x18;
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +0530240
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700241 len_board_id -= sizeof (struct board_id);
242 board_prop += sizeof (struct board_id);
243 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800244
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700245 /* Extract platform data from DTB */
246 for (i = 0; i < msm_data_count; i++) {
247 platform_data[i].platform_id =
248 fdt32_to_cpu (((struct plat_id *)plat_prop)->platform_id);
249 platform_data[i].soc_rev =
250 fdt32_to_cpu (((struct plat_id *)plat_prop)->soc_rev);
251 len_plat_id -= sizeof (struct plat_id);
252 plat_prop += sizeof (struct plat_id);
253 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800254
jianzhoue687ba82017-11-27 16:08:51 +0800255 if ((pmic_data_count != 0) &&
256 (MAX_UINT64 / pmic_data_count < (msm_data_count * board_data_count))) {
257 DEBUG ((EFI_D_ERROR, "NumEntries exceeds MAX_UINT64\n"));
258 goto Exit;
259 }
260
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700261 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
262 /* Extract pmic data from DTB */
263 for (i = 0; i < pmic_data_count; i++) {
264 pmic_data[i].pmic_version[0] =
265 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[0]);
266 pmic_data[i].pmic_version[1] =
267 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[1]);
268 pmic_data[i].pmic_version[2] =
269 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[2]);
270 pmic_data[i].pmic_version[3] =
271 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[3]);
272 len_pmic_id -= sizeof (struct pmic_id);
273 pmic_prop += sizeof (struct pmic_id);
274 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800275
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700276 /* We need to merge board & platform data into dt entry structure */
jianzhoue687ba82017-11-27 16:08:51 +0800277 NumEntries = (uint64_t)msm_data_count * board_data_count *
278 pmic_data_count;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700279 } else {
280 /* We need to merge board & platform data into dt entry structure */
jianzhoue687ba82017-11-27 16:08:51 +0800281 NumEntries = (uint64_t)msm_data_count * board_data_count;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700282 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800283
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530284 dt_entry_array = (struct dt_entry *)AllocateZeroPool (
285 sizeof (struct dt_entry) *
286 NumEntries);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700287 if (!dt_entry_array) {
288 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_entry_array\n"));
289 goto Exit;
290 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800291
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700292 /* If we have '<X>; <Y>; <Z>' as platform data & '<A>; <B>; <C>' as board
293 * data.
294 * Then dt entry should look like
295 * <X ,A >;<X, B>;<X, C>;
296 * <Y ,A >;<Y, B>;<Y, C>;
297 * <Z ,A >;<Z, B>;<Z, C>;
298 */
299 k = 0;
300 for (i = 0; i < msm_data_count; i++) {
301 for (j = 0; j < board_data_count; j++) {
302 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
303 for (n = 0; n < pmic_data_count; n++) {
304 dt_entry_array[k].platform_id = platform_data[i].platform_id;
305 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
306 dt_entry_array[k].variant_id = board_data[j].variant_id;
307 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
308 dt_entry_array[k].pmic_rev[0] = pmic_data[n].pmic_version[0];
309 dt_entry_array[k].pmic_rev[1] = pmic_data[n].pmic_version[1];
310 dt_entry_array[k].pmic_rev[2] = pmic_data[n].pmic_version[2];
311 dt_entry_array[k].pmic_rev[3] = pmic_data[n].pmic_version[3];
312 dt_entry_array[k].offset = (UINT64)dtb;
313 dt_entry_array[k].size = dtb_size;
314 k++;
315 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800316
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700317 } else {
318 dt_entry_array[k].platform_id = platform_data[i].platform_id;
319 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
320 dt_entry_array[k].variant_id = board_data[j].variant_id;
321 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
322 dt_entry_array[k].pmic_rev[0] = BoardPmicTarget (0);
323 dt_entry_array[k].pmic_rev[1] = BoardPmicTarget (1);
324 dt_entry_array[k].pmic_rev[2] = BoardPmicTarget (2);
325 dt_entry_array[k].pmic_rev[3] = BoardPmicTarget (3);
326 dt_entry_array[k].offset = (UINT64)dtb;
327 dt_entry_array[k].size = dtb_size;
328 k++;
lijuang46df8442017-09-28 19:06:36 +0800329 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700330 }
331 }
332
jianzhoue687ba82017-11-27 16:08:51 +0800333 for (i = 0; i < NumEntries; i++) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700334 if (platform_dt_absolute_match (&(dt_entry_array[i]), dtb_list)) {
335 DEBUG ((EFI_D_VERBOSE, "Device tree exact match the board: <0x%x 0x%x "
336 "0x%x 0x%x> == <0x%x 0x%x 0x%x 0x%x>\n",
337 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
338 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
339 BoardPlatformRawChipId (), BoardPlatformType (),
340 BoardPlatformChipVersion (), BoardPlatformSubType ()));
341 } else {
342 DEBUG ((EFI_D_VERBOSE, "Device tree's msm_id doesn't match the board: "
343 "<0x%x 0x%x 0x%x 0x%x> != <0x%x 0x%x 0x%x "
344 "0x%x>\n",
345 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
346 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
347 BoardPlatformRawChipId (), BoardPlatformType (),
348 BoardPlatformChipVersion (), BoardPlatformSubType ()));
349 }
350 }
351 Result = TRUE;
352 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800353
lijuang46df8442017-09-28 19:06:36 +0800354Exit:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700355 if (board_data) {
356 FreePool (board_data);
357 board_data = NULL;
358 }
359 if (platform_data) {
360 FreePool (platform_data);
361 platform_data = NULL;
362 }
363 if (pmic_data) {
364 FreePool (pmic_data);
365 pmic_data = NULL;
366 }
367 if (dt_entry_array) {
368 FreePool (dt_entry_array);
369 dt_entry_array = NULL;
370 }
371 if (model) {
372 FreePool (model);
373 model = NULL;
374 }
lijuang46df8442017-09-28 19:06:36 +0800375
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700376 return Result;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800377}
378
379/*
380 * Will relocate the DTB to the tags addr if the device tree is found and return
381 * its address
382 *
383 * Arguments: kernel - Start address of the kernel loaded in RAM
384 * tags - Start address of the tags loaded in RAM
385 * kernel_size - Size of the kernel in bytes
386 *
387 * Return Value: DTB address : If appended device tree is found
388 * 'NULL' : Otherwise
389 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700390VOID *
391DeviceTreeAppended (VOID *kernel,
392 UINT32 kernel_size,
393 UINT32 dtb_offset,
394 VOID *tags)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800395{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700396 EFI_STATUS Status;
397 uintptr_t kernel_end = (uintptr_t)kernel + kernel_size;
398 VOID *dtb = NULL;
399 VOID *bestmatch_tag = NULL;
400 UINT64 RamdiskLoadAddr;
401 UINT64 BaseMemory = 0;
402 struct dt_entry *best_match_dt_entry = NULL;
403 UINT32 bestmatch_tag_size;
404 struct dt_entry_node *dt_entry_queue = NULL;
405 struct dt_entry_node *dt_node_tmp1 = NULL;
406 struct dt_entry_node *dt_node_tmp2 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800407
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700408 /* Initialize the dtb entry node*/
409 dt_entry_queue =
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +0530410 (struct dt_entry_node *)AllocateZeroPool (sizeof (struct dt_entry_node));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700411 if (!dt_entry_queue) {
412 DEBUG ((EFI_D_ERROR, "Out of memory\n"));
413 return NULL;
414 }
Jeevan Shrirame07dd432016-08-22 11:05:06 -0700415
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700416 list_initialize (&dt_entry_queue->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800417
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700418 if (!dtb_offset) {
419 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
420 goto out;
421 }
Runmin Wang7db42962016-06-27 14:35:35 -0700422
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700423 if (((uintptr_t)kernel + (uintptr_t)dtb_offset) < (uintptr_t)kernel) {
424 goto out;
425 }
426 dtb = kernel + dtb_offset;
427 while (((uintptr_t)dtb + sizeof (struct fdt_header)) <
428 (uintptr_t)kernel_end) {
429 struct fdt_header dtb_hdr;
430 UINT32 dtb_size;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800431
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700432 /* the DTB could be unaligned, so extract the header,
433 * and operate on it separately */
434 gBS->CopyMem (&dtb_hdr, dtb, sizeof (struct fdt_header));
435 if (fdt_check_header ((const VOID *)&dtb_hdr) != 0 ||
436 fdt_check_header_ext ((VOID *)&dtb_hdr) != 0 ||
437 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) <
438 (uintptr_t)dtb) ||
439 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) >
440 (uintptr_t)kernel_end))
441 break;
442 dtb_size = fdt_totalsize (&dtb_hdr);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800443
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700444 if (!DeviceTreeCompatible (dtb, dtb_size, dt_entry_queue)) {
445 DEBUG ((EFI_D_VERBOSE, "Error while DTB parse continue with next DTB\n"));
446 if (!GetRticDtb (dtb))
447 DEBUG ((EFI_D_VERBOSE,
448 "Error while DTB parsing RTIC prop continue with next DTB\n"));
449 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530450
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700451 /* goto the next device tree if any */
452 dtb += dtb_size;
453 }
454 best_match_dt_entry = platform_dt_match_best (dt_entry_queue);
455 if (best_match_dt_entry) {
456 bestmatch_tag = (VOID *)best_match_dt_entry->offset;
457 bestmatch_tag_size = best_match_dt_entry->size;
458 DEBUG ((EFI_D_INFO, "Best match DTB tags "
459 "%u/%08x/0x%08x/%x/%x/%x/%x/%x/(offset)0x%08x/"
460 "(size)0x%08x\n",
461 best_match_dt_entry->platform_id, best_match_dt_entry->variant_id,
462 best_match_dt_entry->board_hw_subtype, best_match_dt_entry->soc_rev,
463 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
464 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
465 best_match_dt_entry->offset, best_match_dt_entry->size));
466 DEBUG ((EFI_D_INFO, "Using pmic info 0x%0x/0x%x/0x%x/0x%0x for device "
467 "0x%0x/0x%x/0x%x/0x%0x\n",
468 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
469 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
470 BoardPmicTarget (0), BoardPmicTarget (1), BoardPmicTarget (2),
471 BoardPmicTarget (3)));
472 }
473 /* free queue's memory */
474 list_for_every_entry (&dt_entry_queue->node, dt_node_tmp1, dt_node, node)
475 {
476 if (!dt_node_tmp1) {
477 DEBUG ((EFI_D_VERBOSE, "Current node is the end\n"));
478 break;
479 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800480
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700481 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
482 dt_entry_list_delete (dt_node_tmp1);
483 dt_node_tmp1 = dt_node_tmp2;
484 }
lijuangf71a4842017-07-27 19:26:31 +0800485
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700486 if (bestmatch_tag) {
487 Status = BaseMem (&BaseMemory);
488 if (Status != EFI_SUCCESS) {
489 DEBUG ((EFI_D_ERROR, "Unable to find Base memory for DDR %r\n", Status));
490 FreePool (dt_entry_queue);
491 dt_entry_queue = NULL;
492 goto out;
493 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800494
Venkata Narendra Kumar Gutta00f46852018-11-29 12:38:08 -0800495 RamdiskLoadAddr = SetandGetLoadAddr (NULL, LOAD_ADDR_RAMDISK);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700496 if ((RamdiskLoadAddr - (UINT64)tags) > RamdiskLoadAddr) {
497 DEBUG ((EFI_D_ERROR, "Tags address is not valid\n"));
498 goto out;
499 }
500 if ((RamdiskLoadAddr - (UINT64)tags) < bestmatch_tag_size) {
501 DEBUG ((EFI_D_ERROR, "Tag size is over the limit\n"));
502 goto out;
503 }
504 gBS->CopyMem (tags, bestmatch_tag, bestmatch_tag_size);
505 /* clear out the old DTB magic so kernel doesn't find it */
506 *((UINT32 *)(kernel + dtb_offset)) = 0;
lijuang46df8442017-09-28 19:06:36 +0800507 FreePool (dt_entry_queue);
508 dt_entry_queue = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700509
510 return tags;
511 }
512
513 DEBUG (
514 (EFI_D_ERROR,
515 "DTB offset is incorrect, kernel image does not have appended DTB\n"));
516
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700517out:
518 FreePool (dt_entry_queue);
519 dt_entry_queue = NULL;
520 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800521}
522
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700523STATIC BOOLEAN
524CheckAllBitsSet (UINT32 DtMatchVal)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530525{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700526 return (DtMatchVal & ALL_BITS_SET) == (ALL_BITS_SET);
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530527}
528
Mukesh Ojhafa815352017-11-08 14:43:41 +0530529STATIC VOID
530ReadBestPmicMatch (CONST CHAR8 *PmicProp, UINT32 PmicEntCount,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530531 PmicIdInfo *BestPmicInfo)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530532{
533 UINT32 PmicEntIdx;
534 UINT32 Idx;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530535 PmicIdInfo CurPmicInfo;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530536
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530537 memset (BestPmicInfo, 0, sizeof (PmicIdInfo));
Mukesh Ojhafa815352017-11-08 14:43:41 +0530538 for (PmicEntIdx = 0; PmicEntIdx < PmicEntCount; PmicEntIdx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530539 memset (&CurPmicInfo, 0, sizeof (PmicIdInfo));
Mukesh Ojhafa815352017-11-08 14:43:41 +0530540 for (Idx = 0; Idx < MAX_PMIC_IDX; Idx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530541 CurPmicInfo.DtPmicModel[Idx] =
Mukesh Ojhafa815352017-11-08 14:43:41 +0530542 fdt32_to_cpu (((struct pmic_id *)PmicProp)->pmic_version[Idx]);
543
544 DEBUG ((EFI_D_VERBOSE, "pmic_data[%u].:%x\n", Idx,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530545 CurPmicInfo.DtPmicModel[Idx]));
546 CurPmicInfo.DtPmicRev[Idx] =
547 CurPmicInfo.DtPmicModel[Idx] & PMIC_REV_MASK;
548 CurPmicInfo.DtPmicModel[Idx] =
549 CurPmicInfo.DtPmicModel[Idx] & PMIC_MODEL_MASK;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530550
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530551 if ((CurPmicInfo.DtPmicModel[Idx]) ==
Mukesh Ojhafa815352017-11-08 14:43:41 +0530552 BoardPmicModel (Idx)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530553 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530554 BIT ((PMIC_MATCH_EXACT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530555 } else if (CurPmicInfo.DtPmicModel[Idx] == 0) {
556 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530557 BIT ((PMIC_MATCH_DEFAULT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
558 } else {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530559 CurPmicInfo.DtMatchVal = BIT (NONE_MATCH);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530560 DEBUG ((EFI_D_VERBOSE, "Pmic model does not match\n"));
561 break;
562 }
563
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530564 if (CurPmicInfo.DtPmicRev[Idx] == (BoardPmicTarget (Idx)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530565 & PMIC_REV_MASK)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530566 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530567 BIT ((PMIC_MATCH_EXACT_REV_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530568 } else if (CurPmicInfo.DtPmicRev[Idx] <
Mukesh Ojhafa815352017-11-08 14:43:41 +0530569 (BoardPmicTarget (Idx) & PMIC_REV_MASK)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530570 CurPmicInfo.DtMatchVal |= BIT ((PMIC_MATCH_BEST_REV_IDX0 +
Mukesh Ojhafa815352017-11-08 14:43:41 +0530571 Idx * PMIC_SHIFT_IDX));
572 } else {
573 DEBUG ((EFI_D_VERBOSE, "Pmic revision does not match\n"));
574 break;
575 }
576 }
577
578 DEBUG ((EFI_D_VERBOSE, "BestPmicInfo.DtMatchVal : %x"
579 " CurPmicInfo[%u]->DtMatchVal : %x\n", BestPmicInfo->DtMatchVal,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530580 PmicEntIdx, CurPmicInfo.DtMatchVal));
581 if (BestPmicInfo->DtMatchVal < CurPmicInfo.DtMatchVal) {
582 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530583 sizeof (struct PmicIdInfo));
584 } else if (BestPmicInfo->DtMatchVal ==
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530585 CurPmicInfo.DtMatchVal) {
586 if (BestPmicInfo->DtPmicRev[0] < CurPmicInfo.DtPmicRev[0]) {
587 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530588 sizeof (struct PmicIdInfo));
589 } else if (BestPmicInfo->DtPmicRev[1] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530590 CurPmicInfo.DtPmicRev[1]) {
591 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530592 sizeof (struct PmicIdInfo));
593 } else if (BestPmicInfo->DtPmicRev[2] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530594 CurPmicInfo.DtPmicRev[2]) {
595 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530596 sizeof (struct PmicIdInfo));
597 } else if (BestPmicInfo->DtPmicRev[3] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530598 CurPmicInfo.DtPmicRev[3]) {
599 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530600 sizeof (struct PmicIdInfo));
601 }
602 }
603
604 PmicProp += sizeof (struct pmic_id);
605 }
606}
607
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800608STATIC EFI_STATUS GetPlatformMatchDtb (DtInfo * CurDtbInfo,
609 CONST CHAR8 *PlatProp,
610 INT32 LenPlatId,
611 INT32 MinPlatIdLen)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530612{
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530613
lijuangf6b1c5f2018-03-20 13:15:47 +0800614 if (CurDtbInfo == NULL) {
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800615 DEBUG ((EFI_D_VERBOSE, "Input parameters null\n"));
616 return EFI_INVALID_PARAMETER;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700617 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530618
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700619 if (PlatProp && (LenPlatId > 0) && (!(LenPlatId % MinPlatIdLen))) {
620 /*Compare msm-id of the dtb vs Board*/
621 CurDtbInfo->DtPlatformId =
622 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id);
623 DEBUG ((EFI_D_VERBOSE, "Boardsocid = %x, Dtsocid = %x\n",
624 (BoardPlatformRawChipId () & SOC_MASK),
625 (CurDtbInfo->DtPlatformId & SOC_MASK)));
626 if ((BoardPlatformRawChipId () & SOC_MASK) ==
627 (CurDtbInfo->DtPlatformId & SOC_MASK)) {
628 CurDtbInfo->DtMatchVal |= BIT (SOC_MATCH);
629 } else {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530630 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id does not match\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700631 /* If it's neither exact nor default match don't select dtb */
632 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800633 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700634 }
635 /*Compare soc rev of the dtb vs Board*/
636 CurDtbInfo->DtSocRev = fdt32_to_cpu (((struct plat_id *)PlatProp)->soc_rev);
637 DEBUG ((EFI_D_VERBOSE, "BoardSocRev = %x, DtSocRev =%x\n",
638 BoardPlatformChipVersion (), CurDtbInfo->DtSocRev));
639 if (CurDtbInfo->DtSocRev == BoardPlatformChipVersion ()) {
640 CurDtbInfo->DtMatchVal |= BIT (VERSION_EXACT_MATCH);
641 } else if (CurDtbInfo->DtSocRev < BoardPlatformChipVersion ()) {
642 CurDtbInfo->DtMatchVal |= BIT (VERSION_BEST_MATCH);
643 } else if (CurDtbInfo->DtSocRev) {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530644 DEBUG ((EFI_D_VERBOSE, "soc version does not match\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700645 }
646 /*Compare Foundry Id of the dtb vs Board*/
647 CurDtbInfo->DtFoundryId =
648 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id) &
649 FOUNDRY_ID_MASK;
650 DEBUG ((EFI_D_VERBOSE, "BoardFoundry = %x, DtFoundry = %x\n",
651 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT),
652 CurDtbInfo->DtFoundryId));
653 if (CurDtbInfo->DtFoundryId ==
654 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT)) {
655 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_EXACT_MATCH);
656 } else if (CurDtbInfo->DtFoundryId == 0) {
657 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_DEFAULT_MATCH);
658 } else {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530659 DEBUG ((EFI_D_VERBOSE, "soc foundry does not match\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700660 /* If it's neither exact nor default match don't select dtb */
661 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800662 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700663 }
664 } else {
665 DEBUG ((EFI_D_VERBOSE, "qcom, msm-id does not exist (or) is"
666 " (%d) not a multiple of (%d)\n",
667 LenPlatId, MinPlatIdLen));
668 }
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800669 return EFI_SUCCESS;
670}
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530671
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800672STATIC EFI_STATUS GetBoardMatchDtb (DtInfo *CurDtbInfo,
673 CONST CHAR8 *BoardProp,
674 INT32 LenBoardId)
675{
lijuangf6b1c5f2018-03-20 13:15:47 +0800676 if (CurDtbInfo == NULL) {
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800677 DEBUG ((EFI_D_VERBOSE, "Input parameters null\n"));
678 return EFI_INVALID_PARAMETER;
679 }
680
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700681 if (BoardProp && (LenBoardId > 0) && (!(LenBoardId % BOARD_ID_SIZE))) {
682 CurDtbInfo->DtVariantId =
683 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id);
684 CurDtbInfo->DtPlatformSubtype =
685 fdt32_to_cpu (((struct board_id *)BoardProp)->platform_subtype);
686 if (CurDtbInfo->DtPlatformSubtype == 0) {
687 CurDtbInfo->DtPlatformSubtype =
688 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id) >>
689 PLATFORM_SUBTYPE_SHIFT_ID;
690 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530691
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700692 DEBUG ((EFI_D_VERBOSE, "BoardVariant = %x, DtVariant = %x\n",
693 BoardPlatformType (), CurDtbInfo->DtVariantId));
694 CurDtbInfo->DtVariantMajor = CurDtbInfo->DtVariantId & VARIANT_MAJOR_MASK;
695 CurDtbInfo->DtVariantMinor = CurDtbInfo->DtVariantId & VARIANT_MINOR_MASK;
696 CurDtbInfo->DtVariantId = CurDtbInfo->DtVariantId & VARIANT_MASK;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530697
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700698 if (CurDtbInfo->DtVariantId == BoardPlatformType ()) {
699 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MATCH);
700 } else if (CurDtbInfo->DtVariantId) {
701 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not"
702 " match\n"));
703 /* If it's neither exact nor default match don't select dtb */
704 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800705 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700706 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530707
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700708 if (CurDtbInfo->DtVariantMajor == (BoardTargetId () & VARIANT_MAJOR_MASK)) {
709 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_EXACT_MATCH);
710 } else if (CurDtbInfo->DtVariantMajor <
711 (BoardTargetId () & VARIANT_MAJOR_MASK)) {
712 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_BEST_MATCH);
713 } else if (CurDtbInfo->DtVariantMajor) {
714 DEBUG ((EFI_D_VERBOSE, "qcom,board-id major version "
715 "does not match\n"));
716 }
Parth Dixitd4887652017-09-13 22:28:52 +0530717
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700718 if (CurDtbInfo->DtVariantMinor == (BoardTargetId () & VARIANT_MINOR_MASK)) {
719 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_EXACT_MATCH);
720 } else if (CurDtbInfo->DtVariantMinor <
721 (BoardTargetId () & VARIANT_MINOR_MASK)) {
722 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_BEST_MATCH);
723 } else if (CurDtbInfo->DtVariantMinor) {
724 DEBUG ((EFI_D_VERBOSE, "qcom,board-id minor version "
725 "does not match\n"));
726 }
Parth Dixitd4887652017-09-13 22:28:52 +0530727
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700728 DEBUG ((EFI_D_VERBOSE, "BoardSubtype = %x, DtSubType = %x\n",
729 BoardPlatformSubType (), CurDtbInfo->DtPlatformSubtype));
730 if (CurDtbInfo->DtPlatformSubtype == BoardPlatformSubType ()) {
731 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_EXACT_MATCH);
732 } else if (CurDtbInfo->DtPlatformSubtype == 0) {
733 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_DEFAULT_MATCH);
jianzhou254e1e02017-11-01 14:52:02 +0800734 } else {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700735 DEBUG ((EFI_D_VERBOSE, "subtype-id doesnot match\n"));
736 /* If it's neither exact nor default match don't select dtb */
737 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800738 return EFI_NOT_FOUND;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700739 }
740 } else {
741 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not exist (or) (%d) "
742 "is not a multiple of (%d)\n",
743 LenBoardId, BOARD_ID_SIZE));
744 }
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800745 return EFI_SUCCESS;
746}
747
748/* Dt selection table for quick reference
749 | SNO | Dt Property | CDT Property | Exact | Best | Default |
750 |-----+---------------+-----------------+-------+------+---------+
751 | | qcom, msm-id | | | | |
752 | | | PlatformId | Y | N | N |
753 | | | SocRev | N | Y | N |
754 | | | FoundryId | Y | N | 0 |
755 | | qcom,board-id | | | | |
756 | | | VariantId | Y | N | N |
757 | | | VariantMajor | N | Y | N |
758 | | | VariantMinor | N | Y | N |
759 | | | PlatformSubtype | Y | N | 0 |
760 | | qcom,pmic-id | | | | |
761 | | | PmicModelId | Y | N | 0 |
762 | | | PmicMetalRev | N | Y | N |
763 | | | PmicLayerRev | N | Y | N |
764 | | | PmicVariantRev | N | Y | N |
765*/
lijuang6fa55c02018-06-22 19:19:26 +0800766STATIC BOOLEAN
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800767ReadDtbFindMatch (DtInfo *CurDtbInfo, DtInfo *BestDtbInfo, UINT32 ExactMatch)
768{
769 EFI_STATUS Status;
770 CONST CHAR8 *PlatProp = NULL;
771 CONST CHAR8 *BoardProp = NULL;
772 CONST CHAR8 *PmicProp = NULL;
773 INT32 LenBoardId;
774 INT32 LenPlatId;
775 INT32 LenPmicId;
776 INT32 MinPlatIdLen = PLAT_ID_SIZE;
777 INT32 RootOffset = 0;
778 VOID *Dtb = CurDtbInfo->Dtb;
779 UINT32 Idx;
780 UINT32 PmicEntCount;
Bhanuprakash Modem64333302018-09-10 18:58:11 +0530781 UINT32 MsmDataCount;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800782 PmicIdInfo BestPmicInfo;
lijuang6fa55c02018-06-22 19:19:26 +0800783 BOOLEAN FindBestMatch = FALSE;
Bhanuprakash Modem64333302018-09-10 18:58:11 +0530784 DtInfo TempDtbInfo = *CurDtbInfo;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800785
786 memset (&BestPmicInfo, 0, sizeof (PmicIdInfo));
787 /*Ensure MatchVal to 0 initially*/
788 CurDtbInfo->DtMatchVal = 0;
789 RootOffset = fdt_path_offset (Dtb, "/");
790 if (RootOffset < 0) {
791 DEBUG ((EFI_D_ERROR, "Unable to locate root node\n"));
lijuang6fa55c02018-06-22 19:19:26 +0800792 return FALSE;
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800793 }
794
795 /* Get the msm-id prop from DTB */
796 PlatProp = (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,msm-id",
797 &LenPlatId);
Bhanuprakash Modem64333302018-09-10 18:58:11 +0530798 if (PlatProp &&
799 (LenPlatId > 0) &&
800 (!(LenPlatId % MinPlatIdLen))) {
801 /*
802 For Multiple soc-id's, save the best SocRev match DT in temp and search
803 for the exact match. If exact match is not found, use best match DT from
804 temp.
805 */
806 MsmDataCount = (LenPlatId / MinPlatIdLen);
807
808 /* Ensure to reset the match value */
809 TempDtbInfo.DtMatchVal = NONE_MATCH;
810
811 for (Idx = 0; Idx < MsmDataCount; Idx++) {
812 /* Ensure MatchVal should be 0 for every match */
813 CurDtbInfo->DtMatchVal = NONE_MATCH;
814 Status = GetPlatformMatchDtb (CurDtbInfo,
815 PlatProp,
816 LenPlatId,
817 MinPlatIdLen);
818 if (Status == EFI_SUCCESS &&
819 CurDtbInfo->DtMatchVal > TempDtbInfo.DtMatchVal) {
820 TempDtbInfo = *CurDtbInfo;
821 }
822 LenPlatId -= PLAT_ID_SIZE;
823 PlatProp += PLAT_ID_SIZE;
824 }
825
826 *CurDtbInfo = TempDtbInfo;
827
828 if (CurDtbInfo->DtMatchVal == NONE_MATCH) {
829 DEBUG ((EFI_D_VERBOSE, "Platform dt prop search failed.\n"));
830 goto cleanup;
831 }
832 } else {
833 DEBUG ((EFI_D_VERBOSE, "qcom, msm-id does not exist (or) is"
834 " (%d) not a multiple of (%d)\n",
835 LenPlatId, MinPlatIdLen));
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800836 }
837
838 /* Get the properties like variant id, subtype from Dtb then compare the
839 * dtb vs Board*/
840 BoardProp = (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,board-id",
841 &LenBoardId);
842 Status = GetBoardMatchDtb (CurDtbInfo, BoardProp, LenBoardId);
843 if (Status != EFI_SUCCESS) {
Mukesh Ojha0eedc352018-02-14 17:42:30 +0530844 DEBUG ((EFI_D_VERBOSE, "Board dt prop search failed.\n"));
Kamalpreet Singhe3b8fe42017-12-07 14:03:36 -0800845 goto cleanup;
846 }
Parth Dixitd4887652017-09-13 22:28:52 +0530847
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700848 /*Get the pmic property from Dtb then compare the dtb vs Board*/
849 PmicProp =
850 (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,pmic-id", &LenPmicId);
851 if ((PmicProp) && (LenPmicId > 0) && (!(LenPmicId % PMIC_ID_SIZE))) {
Mukesh Ojhafa815352017-11-08 14:43:41 +0530852 PmicEntCount = LenPmicId / PMIC_ID_SIZE;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530853 /* Get the best match pmic */
854 ReadBestPmicMatch (PmicProp, PmicEntCount, &BestPmicInfo);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530855 CurDtbInfo->DtMatchVal |= BestPmicInfo.DtMatchVal;
856 for (Idx = 0; Idx < MAX_PMIC_IDX; Idx++) {
857 CurDtbInfo->DtPmicModel[Idx] = BestPmicInfo.DtPmicModel[Idx];
858 CurDtbInfo->DtPmicRev[Idx] = BestPmicInfo.DtPmicRev[Idx];
859 }
860
861 DEBUG ((EFI_D_VERBOSE, "CurDtbInfo->DtMatchVal : %x "
862 "BestPmicInfo.DtMatchVal :%x\n", CurDtbInfo->DtMatchVal,
863 BestPmicInfo.DtMatchVal));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700864 } else {
865 DEBUG ((EFI_D_VERBOSE, "qcom,pmic-id does not exit (or) is (%d)"
866 " not a multiple of (%d)\n",
867 LenPmicId, PMIC_ID_SIZE));
868 }
Parth Dixitd4887652017-09-13 22:28:52 +0530869
870cleanup:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700871 if (CurDtbInfo->DtMatchVal & BIT (ExactMatch)) {
872 if (BestDtbInfo->DtMatchVal < CurDtbInfo->DtMatchVal) {
873 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
lijuang6fa55c02018-06-22 19:19:26 +0800874 FindBestMatch = TRUE;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700875 } else if (BestDtbInfo->DtMatchVal == CurDtbInfo->DtMatchVal) {
lijuang6fa55c02018-06-22 19:19:26 +0800876 FindBestMatch = TRUE;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700877 if (BestDtbInfo->DtSocRev < CurDtbInfo->DtSocRev) {
878 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
879 } else if (BestDtbInfo->DtVariantMajor < CurDtbInfo->DtVariantMajor) {
880 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
881 } else if (BestDtbInfo->DtVariantMinor < CurDtbInfo->DtVariantMinor) {
882 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
883 } else if (BestDtbInfo->DtPmicRev[0] < CurDtbInfo->DtPmicRev[0]) {
884 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
885 } else if (BestDtbInfo->DtPmicRev[1] < CurDtbInfo->DtPmicRev[1]) {
886 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
887 } else if (BestDtbInfo->DtPmicRev[2] < CurDtbInfo->DtPmicRev[2]) {
888 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
889 } else if (BestDtbInfo->DtPmicRev[3] < CurDtbInfo->DtPmicRev[3]) {
890 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
lijuang6fa55c02018-06-22 19:19:26 +0800891 } else {
892 FindBestMatch = FALSE;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700893 }
894 }
895 }
lijuang6fa55c02018-06-22 19:19:26 +0800896
897 return FindBestMatch;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700898}
899
900VOID *
901GetSocDtb (VOID *Kernel, UINT32 KernelSize, UINT32 DtbOffset, VOID *DtbLoadAddr)
902{
903 uintptr_t KernelEnd = (uintptr_t)Kernel + KernelSize;
904 VOID *Dtb = NULL;
905 struct fdt_header DtbHdr;
906 UINT32 DtbSize = 0;
907 DtInfo CurDtbInfo = {0};
908 DtInfo BestDtbInfo = {0};
909 if (!DtbOffset) {
910 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
911 return NULL;
912 }
913
914 if (((uintptr_t)Kernel + (uintptr_t)DtbOffset) < (uintptr_t)Kernel) {
915 return NULL;
916 }
917 Dtb = Kernel + DtbOffset;
918 while (((uintptr_t)Dtb + sizeof (struct fdt_header)) < (uintptr_t)KernelEnd) {
919 /* the DTB could be unaligned, so extract the header,
920 * and operate on it separately */
921 gBS->CopyMem (&DtbHdr, Dtb, sizeof (struct fdt_header));
922 DtbSize = fdt_totalsize ((const VOID *)&DtbHdr);
923 if (fdt_check_header ((const VOID *)&DtbHdr) != 0 ||
924 fdt_check_header_ext ((VOID *)&DtbHdr) != 0 ||
925 ((uintptr_t)Dtb + DtbSize < (uintptr_t)Dtb) ||
926 ((uintptr_t)Dtb + DtbSize > (uintptr_t)KernelEnd))
927 break;
928
929 CurDtbInfo.Dtb = Dtb;
930 ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, SOC_MATCH);
931 if (CurDtbInfo.DtMatchVal) {
932 if (CurDtbInfo.DtMatchVal & BIT (SOC_MATCH)) {
933 if (CheckAllBitsSet (CurDtbInfo.DtMatchVal)) {
934 DEBUG ((EFI_D_VERBOSE, "Exact DTB match"
935 " found. DTBO search is not "
936 "required\n"));
937 DtboNeed = FALSE;
Parth Dixitd4887652017-09-13 22:28:52 +0530938 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700939 }
940 } else {
941 if (!GetRticDtb (Dtb)) {
942 DEBUG ((EFI_D_VERBOSE, "Error while DTB parsing"
943 " RTIC prop continue with next DTB\n"));
944 }
945 }
946
947 DEBUG ((EFI_D_VERBOSE, "Bestmatch = %x\n", BestDtbInfo.DtMatchVal));
948 Dtb += DtbSize;
949 }
950
951 if (!BestDtbInfo.Dtb) {
952 DEBUG ((EFI_D_ERROR, "No match found for Soc Dtb type\n"));
953 return NULL;
954 }
955
956 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530957}
958
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700959VOID *
960GetBoardDtb (BootInfo *Info, VOID *DtboImgBuffer)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530961{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700962 struct DtboTableHdr *DtboTableHdr = DtboImgBuffer;
963 struct DtboTableEntry *DtboTableEntry = NULL;
964 UINT32 DtboCount = 0;
965 VOID *BoardDtb = NULL;
966 UINT32 DtboTableEntriesCount = 0;
967 UINT32 FirstDtboTableEntryOffset = 0;
968 DtInfo CurDtbInfo = {0};
969 DtInfo BestDtbInfo = {0};
lijuang6fa55c02018-06-22 19:19:26 +0800970 BOOLEAN FindBestDtb = FALSE;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530971
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700972 if (!DtboImgBuffer) {
973 DEBUG ((EFI_D_ERROR, "Dtbo Img buffer is NULL\n"));
974 return NULL;
975 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530976
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700977 FirstDtboTableEntryOffset = fdt32_to_cpu (DtboTableHdr->DtEntryOffset);
978 if (CHECK_ADD64 ((UINT64)DtboImgBuffer, FirstDtboTableEntryOffset)) {
979 DEBUG ((EFI_D_ERROR, "Integer overflow deteced with Dtbo address\n"));
980 return NULL;
981 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530982
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700983 DtboTableEntry =
984 (struct DtboTableEntry *)(DtboImgBuffer + FirstDtboTableEntryOffset);
985 if (!DtboTableEntry) {
986 DEBUG ((EFI_D_ERROR, "No proper DtTable\n"));
987 return NULL;
988 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530989
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700990 DtboTableEntriesCount = fdt32_to_cpu (DtboTableHdr->DtEntryCount);
991 for (DtboCount = 0; DtboCount < DtboTableEntriesCount; DtboCount++) {
992 if (CHECK_ADD64 ((UINT64)DtboImgBuffer,
993 fdt32_to_cpu (DtboTableEntry->DtOffset))) {
Mukesh Ojha82911f82018-04-30 16:45:07 +0530994 DEBUG ((EFI_D_ERROR, "Integer overflow detected with Dtbo address\n"));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700995 return NULL;
996 }
997 BoardDtb = DtboImgBuffer + fdt32_to_cpu (DtboTableEntry->DtOffset);
998 if (fdt_check_header (BoardDtb) || fdt_check_header_ext (BoardDtb)) {
999 DEBUG ((EFI_D_ERROR, "No Valid Dtb\n"));
1000 break;
1001 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +05301002
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001003 CurDtbInfo.Dtb = BoardDtb;
lijuang6fa55c02018-06-22 19:19:26 +08001004 FindBestDtb = ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, VARIANT_MATCH);
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001005 DEBUG ((EFI_D_VERBOSE, "Dtbo count = %u LocalBoardDtMatch = %x"
1006 "\n",
1007 DtboCount, CurDtbInfo.DtMatchVal));
lijuang6fa55c02018-06-22 19:19:26 +08001008
1009 if (FindBestDtb) {
1010 DtboIdx = DtboCount;
1011 }
1012
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001013 DtboTableEntry++;
1014 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301015
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001016 if (!BestDtbInfo.Dtb) {
1017 DEBUG ((EFI_D_ERROR, "Unable to find the Board Dtb\n"));
1018 return NULL;
1019 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301020
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001021 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +05301022}
1023
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001024/* Returns 0 if the device tree is valid. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001025int
1026DeviceTreeValidate (UINT8 *DeviceTreeBuff,
1027 UINT32 PageSize,
1028 UINT32 *DeviceTreeSize)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001029{
lijuangc336a292017-08-22 19:48:49 +08001030 UINT32 dt_entry_size;
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001031 UINT64 hdr_size;
1032 struct dt_table *table;
1033 if (DeviceTreeSize) {
1034 table = (struct dt_table *)DeviceTreeBuff;
1035 if (table->magic != DEV_TREE_MAGIC) {
1036 // bad magic in device tree table
1037 return -1;
1038 }
1039 if (table->version == DEV_TREE_VERSION_V1) {
1040 dt_entry_size = sizeof (struct dt_entry_v1);
1041 } else if (table->version == DEV_TREE_VERSION_V2) {
1042 dt_entry_size = sizeof (struct dt_entry_v2);
1043 } else if (table->version == DEV_TREE_VERSION_V3) {
1044 dt_entry_size = sizeof (struct dt_entry);
1045 } else {
1046 // unsupported dt version
1047 return -1;
1048 }
1049 hdr_size =
1050 ((UINT64)table->num_entries * dt_entry_size) + DEV_TREE_HEADER_SIZE;
1051 // hdr_size = ROUNDUP(hdr_size, PageSize);
1052 hdr_size = EFI_SIZE_TO_PAGES (hdr_size);
1053 if (hdr_size > MAX_UINT64)
1054 return -1;
1055 else
1056 *DeviceTreeSize = hdr_size & MAX_UINT64;
1057 // dt_entry_ptr = (struct dt_entry *)((CHAR8 *)table +
1058 // DEV_TREE_HEADER_SIZE);
1059 // table_ptr = dt_entry_ptr;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001060
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001061 DEBUG ((EFI_D_ERROR, "DT Total number of entries: %d, DTB version: %d\n",
1062 table->num_entries, table->version));
1063 }
1064 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001065}
1066
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001067STATIC int
1068platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
1069 struct dt_entry_node *dt_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001070{
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001071 UINT32 cur_dt_hw_platform;
1072 UINT32 cur_dt_hw_subtype;
1073 UINT32 cur_dt_msm_id;
1074 dt_node *dt_node_tmp = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001075
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001076 /* Platform-id
1077 * bit no |31 24|23 16|15 0|
1078 * |reserved|foundry-id|msm-id|
1079 */
1080 cur_dt_msm_id = (cur_dt_entry->platform_id & 0x0000ffff);
1081 cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
1082 cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001083
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001084 /* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
1085 * soc, board major/minor, pmic major/minor must less than board info
1086 * 2. find the matched DTB then return 1
1087 * 3. otherwise return 0
1088 */
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001089
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001090 if ((cur_dt_msm_id == (BoardPlatformRawChipId () & 0x0000ffff)) &&
1091 (cur_dt_hw_platform == BoardPlatformType ()) &&
1092 (cur_dt_hw_subtype == BoardPlatformSubType ()) &&
1093 (cur_dt_entry->soc_rev <= BoardPlatformChipVersion ()) &&
1094 ((cur_dt_entry->variant_id & 0x00ffff00) <=
1095 (BoardTargetId () & 0x00ffff00)) &&
1096 (cur_dt_entry->pmic_rev[0] <= BoardPmicTarget (0)) &&
1097 (cur_dt_entry->pmic_rev[1] <= BoardPmicTarget (1)) &&
1098 (cur_dt_entry->pmic_rev[2] <= BoardPmicTarget (2)) &&
1099 (cur_dt_entry->pmic_rev[3] <= BoardPmicTarget (3))) {
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001100
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001101 dt_node_tmp = dt_entry_list_init ();
1102 if (!dt_node_tmp) {
1103 DEBUG ((EFI_D_ERROR, "dt_node_tmp is NULL\n"));
1104 return 0;
1105 }
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +05301106
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001107 gBS->CopyMem ((VOID *)dt_node_tmp->dt_entry_m, (VOID *)cur_dt_entry,
1108 sizeof (struct dt_entry));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001109
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001110 DEBUG (
1111 (EFI_D_VERBOSE,
1112 "Add DTB entry 0x%x/%08x/0x%08x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
1113 dt_node_tmp->dt_entry_m->platform_id,
1114 dt_node_tmp->dt_entry_m->variant_id,
1115 dt_node_tmp->dt_entry_m->board_hw_subtype,
1116 dt_node_tmp->dt_entry_m->soc_rev, dt_node_tmp->dt_entry_m->pmic_rev[0],
1117 dt_node_tmp->dt_entry_m->pmic_rev[1],
1118 dt_node_tmp->dt_entry_m->pmic_rev[2],
1119 dt_node_tmp->dt_entry_m->pmic_rev[3], dt_node_tmp->dt_entry_m->offset,
1120 dt_node_tmp->dt_entry_m->size));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001121
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001122 insert_dt_entry_in_queue (dt_list, dt_node_tmp);
1123 return 1;
1124 }
1125 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001126}
1127
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001128int
1129platform_dt_absolute_compat_match (struct dt_entry_node *dt_list,
1130 UINT32 dtb_info)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001131{
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001132 struct dt_entry_node *dt_node_tmp1 = NULL;
1133 struct dt_entry_node *dt_node_tmp2 = NULL;
1134 UINT32 current_info = 0;
1135 UINT32 board_info = 0;
1136 UINT32 best_info = 0;
1137 UINT32 current_pmic_model[4] = {0, 0, 0, 0};
1138 UINT32 board_pmic_model[4] = {0, 0, 0, 0};
1139 UINT32 best_pmic_model[4] = {0, 0, 0, 0};
1140 UINT32 delete_current_dt = 0;
1141 UINT32 i;
1142
1143 /* start to select the exact entry
1144 * default to exact match 0, if find current DTB entry info is the same as
1145 * board info,
1146 * then exact match board info.
1147 */
1148 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1149 {
1150 if (!dt_node_tmp1) {
1151 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1152 break;
1153 }
1154 switch (dtb_info) {
1155 case DTB_FOUNDRY:
1156 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1157 board_info = BoardPlatformFoundryId () << 16;
1158 break;
1159 case DTB_PMIC_MODEL:
1160 for (i = 0; i < 4; i++) {
1161 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1162 board_pmic_model[i] = BoardPmicModel (i);
1163 }
1164 break;
1165 default:
1166 DEBUG ((EFI_D_ERROR,
1167 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1168 return 0;
1169 }
1170
1171 if (dtb_info == DTB_PMIC_MODEL) {
1172 if ((current_pmic_model[0] == board_pmic_model[0]) &&
1173 (current_pmic_model[1] == board_pmic_model[1]) &&
1174 (current_pmic_model[2] == board_pmic_model[2]) &&
1175 (current_pmic_model[3] == board_pmic_model[3])) {
1176
1177 for (i = 0; i < 4; i++) {
1178 best_pmic_model[i] = current_pmic_model[i];
1179 }
1180 break;
1181 }
1182 } else {
1183 if (current_info == board_info) {
1184 best_info = current_info;
1185 break;
1186 }
1187 }
1188 }
1189
1190 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1191 {
1192 if (!dt_node_tmp1) {
1193 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1194 break;
1195 }
1196 switch (dtb_info) {
1197 case DTB_FOUNDRY:
1198 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1199 break;
1200 case DTB_PMIC_MODEL:
1201 for (i = 0; i < 4; i++) {
1202 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1203 }
1204 break;
1205 default:
1206 DEBUG ((EFI_D_ERROR,
1207 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1208 return 0;
1209 }
1210
1211 if (dtb_info == DTB_PMIC_MODEL) {
1212 if ((current_pmic_model[0] != best_pmic_model[0]) ||
1213 (current_pmic_model[1] != best_pmic_model[1]) ||
1214 (current_pmic_model[2] != best_pmic_model[2]) ||
1215 (current_pmic_model[3] != best_pmic_model[3])) {
1216
1217 delete_current_dt = 1;
1218 }
1219 } else {
1220 if (current_info != best_info) {
1221 delete_current_dt = 1;
1222 }
1223 }
1224
1225 if (delete_current_dt) {
1226 DEBUG (
1227 (EFI_D_VERBOSE,
1228 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1229 dt_node_tmp1->dt_entry_m->platform_id,
1230 dt_node_tmp1->dt_entry_m->variant_id,
1231 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1232 dt_node_tmp1->dt_entry_m->soc_rev,
1233 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1234 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1235 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1236 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1237 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1238
1239 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1240 dt_entry_list_delete (dt_node_tmp1);
1241 dt_node_tmp1 = dt_node_tmp2;
1242 delete_current_dt = 0;
1243 }
1244 }
1245
1246 return 1;
1247}
1248
1249int
1250update_dtb_entry_node (struct dt_entry_node *dt_list, UINT32 dtb_info)
1251{
1252 struct dt_entry_node *dt_node_tmp1 = NULL;
1253 struct dt_entry_node *dt_node_tmp2 = NULL;
1254 UINT32 current_info = 0;
1255 UINT32 board_info = 0;
1256 UINT32 best_info = 0;
1257
1258 /* start to select the best entry*/
1259 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1260 {
1261 if (!dt_node_tmp1) {
1262 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1263 break;
1264 }
1265 switch (dtb_info) {
1266 case DTB_SOC:
1267 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1268 board_info = BoardPlatformChipVersion ();
1269 break;
1270 case DTB_MAJOR_MINOR:
1271 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1272 board_info = BoardTargetId () & 0x00ffff00;
1273 break;
1274 case DTB_PMIC0:
1275 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1276 board_info = BoardPmicTarget (0);
1277 break;
1278 case DTB_PMIC1:
1279 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1280 board_info = BoardPmicTarget (1);
1281 break;
1282 case DTB_PMIC2:
1283 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1284 board_info = BoardPmicTarget (2);
1285 break;
1286 case DTB_PMIC3:
1287 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1288 board_info = BoardPmicTarget (3);
1289 break;
1290 default:
1291 DEBUG ((EFI_D_ERROR,
1292 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1293 return 0;
1294 }
1295
1296 if (current_info == board_info) {
1297 best_info = current_info;
1298 break;
1299 }
1300 if ((current_info < board_info) && (current_info > best_info)) {
1301 best_info = current_info;
1302 }
1303 if (current_info < best_info) {
1304 DEBUG (
1305 (EFI_D_ERROR,
1306 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1307 dt_node_tmp1->dt_entry_m->platform_id,
1308 dt_node_tmp1->dt_entry_m->variant_id,
1309 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1310 dt_node_tmp1->dt_entry_m->soc_rev,
1311 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1312 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1313 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1314 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1315 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1316
1317 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1318 dt_entry_list_delete (dt_node_tmp1);
1319 dt_node_tmp1 = dt_node_tmp2;
1320 }
1321 }
1322
1323 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1324 {
1325 if (!dt_node_tmp1) {
1326 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1327 break;
1328 }
1329 switch (dtb_info) {
1330 case DTB_SOC:
1331 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1332 break;
1333 case DTB_MAJOR_MINOR:
1334 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1335 break;
1336 case DTB_PMIC0:
1337 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1338 break;
1339 case DTB_PMIC1:
1340 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1341 break;
1342 case DTB_PMIC2:
1343 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1344 break;
1345 case DTB_PMIC3:
1346 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1347 break;
1348 default:
1349 DEBUG ((EFI_D_ERROR,
1350 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1351 return 0;
1352 }
1353
1354 if (current_info != best_info) {
1355 DEBUG (
1356 (EFI_D_VERBOSE,
1357 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1358 dt_node_tmp1->dt_entry_m->platform_id,
1359 dt_node_tmp1->dt_entry_m->variant_id,
1360 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1361 dt_node_tmp1->dt_entry_m->soc_rev,
1362 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1363 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1364 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1365 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1366 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1367
1368 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1369 dt_entry_list_delete (dt_node_tmp1);
1370 dt_node_tmp1 = dt_node_tmp2;
1371 }
1372 }
1373 return 1;
1374}
1375
1376STATIC struct dt_entry *
1377platform_dt_match_best (struct dt_entry_node *dt_list)
1378{
1379 struct dt_entry_node *dt_node_tmp1 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001380
lijuangc336a292017-08-22 19:48:49 +08001381 /* check Foundry id
1382 * the foundry id must exact match board founddry id, this is compatibility
1383 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1384 */
1385 platform_dt_absolute_compat_match (dt_list, DTB_FOUNDRY);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001386
lijuangc336a292017-08-22 19:48:49 +08001387 /* check PMIC model
1388 * the PMIC model must exact match board PMIC model, this is compatibility
1389 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1390 */
1391 platform_dt_absolute_compat_match (dt_list, DTB_PMIC_MODEL);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001392
lijuangc336a292017-08-22 19:48:49 +08001393 /* check soc version
1394 * the suitable soc version must less than or equal to board soc version
1395 */
1396 update_dtb_entry_node (dt_list, DTB_SOC);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001397
lijuangc336a292017-08-22 19:48:49 +08001398 /*check major and minor version
1399 * the suitable major&minor version must less than or equal to board
1400 * major&minor version
1401 */
1402 update_dtb_entry_node (dt_list, DTB_MAJOR_MINOR);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001403
lijuangc336a292017-08-22 19:48:49 +08001404 /*check pmic info
1405 * the suitable pmic major&minor info must less than or equal to board pmic
1406 * major&minor version
1407 */
1408 update_dtb_entry_node (dt_list, DTB_PMIC0);
1409 update_dtb_entry_node (dt_list, DTB_PMIC1);
1410 update_dtb_entry_node (dt_list, DTB_PMIC2);
1411 update_dtb_entry_node (dt_list, DTB_PMIC3);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001412
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001413 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1414 {
1415 if (!dt_node_tmp1) {
1416 DEBUG ((EFI_D_ERROR, "ERROR: Couldn't find the suitable DTB!\n"));
1417 return NULL;
1418 }
1419 if (dt_node_tmp1->dt_entry_m)
1420 return dt_node_tmp1->dt_entry_m;
1421 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001422
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001423 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001424}
Bhanuprakash Modemed797c72018-09-05 20:39:07 +05301425
1426BOOLEAN
1427AppendToDtList (struct fdt_entry_node **DtList,
1428 UINT64 Address,
1429 UINT64 Size) {
1430 struct fdt_entry_node *Current = *DtList;
1431
1432 if (*DtList == NULL) {
1433 DEBUG ((EFI_D_VERBOSE, "DTs list: NULL\n"));
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +05301434 Current = AllocateZeroPool (sizeof (struct fdt_entry_node));
Bhanuprakash Modemed797c72018-09-05 20:39:07 +05301435 if (!Current) {
1436 return FALSE;
1437 }
1438
1439 Current->address = Address;
1440 Current->size = Size;
1441 Current->next = NULL;
1442 *DtList = Current;
1443 return TRUE;
1444 } else {
1445
1446 while (Current->next != NULL) {
1447 Current = Current->next;
1448 }
1449
Bhanuprakash Modem763cdd52018-11-01 14:49:55 +05301450 Current->next = AllocateZeroPool (sizeof (struct fdt_entry_node));
Bhanuprakash Modemed797c72018-09-05 20:39:07 +05301451 if (!Current->next) {
1452 return FALSE;
1453 }
1454 Current->next->address = Address;
1455 Current->next->size = Size;
1456 Current->next->next = NULL;
1457 return TRUE;
1458 }
1459}
1460
1461VOID DeleteDtList (struct fdt_entry_node** DtList)
1462{
1463 struct fdt_entry_node *Current = *DtList;
1464 struct fdt_entry_node *Next;
1465
1466 while (Current != NULL) {
1467 Next = Current->next;
1468 FreePool (Current);
1469 Current = Next;
1470 }
1471
1472 *DtList = NULL;
1473}