blob: 0e713ff156842ef7dac0082ef884ce7e84edb4c3 [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
lijuangf0bbcad2017-08-16 16:59:18 +080045BOOLEAN GetDtboNeeded (VOID)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053046{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070047 return DtboNeed;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +053048}
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080049/* Add function to allocate dt entry list, used for recording
50 * the entry which conform to platform_dt_absolute_match()
51 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -070052static struct dt_entry_node *dt_entry_list_init (VOID)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080053{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070054 struct dt_entry_node *dt_node_member = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080055
Jeevan Shriram17f173d2017-10-24 22:11:07 -070056 dt_node_member =
57 (struct dt_entry_node *)AllocatePool (sizeof (struct dt_entry_node));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080058
Jeevan Shriram17f173d2017-10-24 22:11:07 -070059 if (!dt_node_member) {
60 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_node_member\n"));
61 return NULL;
62 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080063
Jeevan Shriram17f173d2017-10-24 22:11:07 -070064 list_clear_node (&dt_node_member->node);
65 dt_node_member->dt_entry_m =
66 (struct dt_entry *)AllocatePool (sizeof (struct dt_entry));
67 if (!dt_node_member->dt_entry_m) {
68 DEBUG ((EFI_D_ERROR,
69 "Failed to allocate memory for dt_node_member->dt_entry_m\n"));
70 FreePool (dt_node_member);
71 dt_node_member = NULL;
72 return NULL;
73 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080074
Jeevan Shriram17f173d2017-10-24 22:11:07 -070075 memset (dt_node_member->dt_entry_m, 0, sizeof (struct dt_entry));
76 return dt_node_member;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080077}
78
Jeevan Shriram17f173d2017-10-24 22:11:07 -070079static VOID
80insert_dt_entry_in_queue (struct dt_entry_node *dt_list,
81 struct dt_entry_node *dt_node_member)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080082{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070083 list_add_tail (&dt_list->node, &dt_node_member->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080084}
85
Jeevan Shriram17f173d2017-10-24 22:11:07 -070086static VOID
87dt_entry_list_delete (struct dt_entry_node *dt_node_member)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080088{
Jeevan Shriram17f173d2017-10-24 22:11:07 -070089 if (list_in_list (&dt_node_member->node)) {
90 list_delete (&dt_node_member->node);
91 FreePool (dt_node_member->dt_entry_m);
92 dt_node_member->dt_entry_m = NULL;
93 FreePool (dt_node_member);
94 dt_node_member = NULL;
95 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -080096}
97
Jeevan Shriram17f173d2017-10-24 22:11:07 -070098static BOOLEAN
99DeviceTreeCompatible (VOID *dtb,
100 UINT32 dtb_size,
101 struct dt_entry_node *dtb_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800102{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700103 int root_offset;
104 const VOID *prop = NULL;
105 const char *plat_prop = NULL;
106 const char *board_prop = NULL;
107 const char *pmic_prop = NULL;
108 char *model = NULL;
109 struct dt_entry *dt_entry_array = NULL;
110 struct board_id *board_data = NULL;
111 struct plat_id *platform_data = NULL;
112 struct pmic_id *pmic_data = NULL;
113 int len;
114 int len_board_id;
115 int len_plat_id;
116 int min_plat_id_len = 0;
117 int len_pmic_id;
118 UINT32 dtb_ver;
jianzhoue687ba82017-11-27 16:08:51 +0800119 UINT64 NumEntries = 0;
120 UINT64 i;
121 UINT32 j, k, n;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700122 UINT32 msm_data_count;
123 UINT32 board_data_count;
124 UINT32 pmic_data_count;
125 BOOLEAN Result = FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800126
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700127 root_offset = fdt_path_offset (dtb, "/");
128 if (root_offset < 0)
129 return FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800130
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700131 prop = fdt_getprop (dtb, root_offset, "model", &len);
132 if (prop && len > 0) {
133 model = (char *)AllocatePool (sizeof (char) * len);
134 if (!model) {
135 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for model\n"));
136 return FALSE;
137 }
138 AsciiStrnCpyS (model, (sizeof (CHAR8) * len), prop, len);
139 } else {
140 DEBUG ((EFI_D_ERROR, "model does not exist in device tree\n"));
141 }
142 /* Find the pmic-id prop from DTB , if pmic-id is present then
143 * the DTB is version 3, otherwise find the board-id prop from DTB ,
144 * if board-id is present then the DTB is version 2 */
145 pmic_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,pmic-id",
146 &len_pmic_id);
147 board_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,board-id",
148 &len_board_id);
149 if (pmic_prop && (len_pmic_id > 0) && board_prop && (len_board_id > 0)) {
150 if ((len_pmic_id % PMIC_ID_SIZE) || (len_board_id % BOARD_ID_SIZE)) {
151 DEBUG ((EFI_D_ERROR, "qcom,pmic-id (%d) or qcom,board-id(%d) in device "
152 "tree is not a multiple of (%d %d)\n",
153 len_pmic_id, len_board_id, PMIC_ID_SIZE, BOARD_ID_SIZE));
154 goto Exit;
155 }
156 dtb_ver = DEV_TREE_VERSION_V3;
157 min_plat_id_len = PLAT_ID_SIZE;
158 } else if (board_prop && len_board_id > 0) {
159 if (len_board_id % BOARD_ID_SIZE) {
160 DEBUG ((EFI_D_ERROR,
161 "qcom,pmic-id (%d) in device tree is not a multiple of (%d)\n",
162 len_board_id, BOARD_ID_SIZE));
163 goto Exit;
164 }
165 dtb_ver = DEV_TREE_VERSION_V2;
166 min_plat_id_len = PLAT_ID_SIZE;
167 } else {
168 dtb_ver = DEV_TREE_VERSION_V1;
169 min_plat_id_len = DT_ENTRY_V1_SIZE;
170 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800171
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700172 /* Get the msm-id prop from DTB */
173 plat_prop =
174 (const char *)fdt_getprop (dtb, root_offset, "qcom,msm-id", &len_plat_id);
175 if (!plat_prop || len_plat_id <= 0) {
176 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id entry not found\n"));
177 goto Exit;
178 } else if (len_plat_id % min_plat_id_len) {
179 DEBUG ((EFI_D_ERROR,
180 "qcom, msm-id in device tree is (%d) not a multiple of (%d)\n",
181 len_plat_id, min_plat_id_len));
182 goto Exit;
183 }
184 if (dtb_ver == DEV_TREE_VERSION_V2 || dtb_ver == DEV_TREE_VERSION_V3) {
185 board_data_count = (len_board_id / BOARD_ID_SIZE);
186 msm_data_count = (len_plat_id / PLAT_ID_SIZE);
187 /* If dtb version is v2.0, the pmic_data_count will be <= 0 */
188 pmic_data_count = (len_pmic_id / PMIC_ID_SIZE);
189
190 /* If we are using dtb v3.0, then we have split board, msm & pmic data in
191 * the DTB
192 * If we are using dtb v2.0, then we have split board & msmdata in the DTB
193 */
194 board_data = (struct board_id *)AllocatePool (
195 sizeof (struct board_id) * (len_board_id / BOARD_ID_SIZE));
196 if (!board_data) {
197 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for board_data\n"));
198 goto Exit;
199 }
200
201 platform_data = (struct plat_id *)AllocatePool (
202 sizeof (struct plat_id) * (len_plat_id / PLAT_ID_SIZE));
203 if (!platform_data) {
204 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for platform_data\n"));
205 goto Exit;
206 }
207 if (dtb_ver == DEV_TREE_VERSION_V3) {
208 pmic_data = (struct pmic_id *)AllocatePool (sizeof (struct pmic_id) *
209 (len_pmic_id / PMIC_ID_SIZE));
210 if (!pmic_data) {
211 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for pmic_data\n"));
lijuang46df8442017-09-28 19:06:36 +0800212 goto Exit;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700213 }
214 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800215
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700216 /* Extract board data from DTB */
217 for (i = 0; i < board_data_count; i++) {
218 board_data[i].variant_id =
219 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id);
220 board_data[i].platform_subtype =
221 fdt32_to_cpu (((struct board_id *)board_prop)->platform_subtype);
222 /* For V2/V3 version of DTBs we have platform version field as part
223 * of variant ID, in such case the subtype will be mentioned as 0x0
224 * As the qcom, board-id = <0xSSPMPmPH, 0x0>
225 * SS -- Subtype
226 * PM -- Platform major version
227 * Pm -- Platform minor version
228 * PH -- Platform hardware CDP/MTP
229 * In such case to make it compatible with LK algorithm move the subtype
230 * from variant_id to subtype field
231 */
232 if (board_data[i].platform_subtype == 0)
233 board_data[i].platform_subtype =
234 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id) >> 0x18;
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +0530235
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700236 len_board_id -= sizeof (struct board_id);
237 board_prop += sizeof (struct board_id);
238 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800239
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700240 /* Extract platform data from DTB */
241 for (i = 0; i < msm_data_count; i++) {
242 platform_data[i].platform_id =
243 fdt32_to_cpu (((struct plat_id *)plat_prop)->platform_id);
244 platform_data[i].soc_rev =
245 fdt32_to_cpu (((struct plat_id *)plat_prop)->soc_rev);
246 len_plat_id -= sizeof (struct plat_id);
247 plat_prop += sizeof (struct plat_id);
248 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800249
jianzhoue687ba82017-11-27 16:08:51 +0800250 if ((pmic_data_count != 0) &&
251 (MAX_UINT64 / pmic_data_count < (msm_data_count * board_data_count))) {
252 DEBUG ((EFI_D_ERROR, "NumEntries exceeds MAX_UINT64\n"));
253 goto Exit;
254 }
255
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700256 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
257 /* Extract pmic data from DTB */
258 for (i = 0; i < pmic_data_count; i++) {
259 pmic_data[i].pmic_version[0] =
260 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[0]);
261 pmic_data[i].pmic_version[1] =
262 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[1]);
263 pmic_data[i].pmic_version[2] =
264 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[2]);
265 pmic_data[i].pmic_version[3] =
266 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[3]);
267 len_pmic_id -= sizeof (struct pmic_id);
268 pmic_prop += sizeof (struct pmic_id);
269 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800270
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700271 /* We need to merge board & platform data into dt entry structure */
jianzhoue687ba82017-11-27 16:08:51 +0800272 NumEntries = (uint64_t)msm_data_count * board_data_count *
273 pmic_data_count;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700274 } else {
275 /* We need to merge board & platform data into dt entry structure */
jianzhoue687ba82017-11-27 16:08:51 +0800276 NumEntries = (uint64_t)msm_data_count * board_data_count;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700277 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800278
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700279 dt_entry_array = (struct dt_entry *)AllocatePool (sizeof (struct dt_entry) *
jianzhoue687ba82017-11-27 16:08:51 +0800280 NumEntries);
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700281 if (!dt_entry_array) {
282 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_entry_array\n"));
283 goto Exit;
284 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800285
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700286 /* If we have '<X>; <Y>; <Z>' as platform data & '<A>; <B>; <C>' as board
287 * data.
288 * Then dt entry should look like
289 * <X ,A >;<X, B>;<X, C>;
290 * <Y ,A >;<Y, B>;<Y, C>;
291 * <Z ,A >;<Z, B>;<Z, C>;
292 */
293 k = 0;
294 for (i = 0; i < msm_data_count; i++) {
295 for (j = 0; j < board_data_count; j++) {
296 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
297 for (n = 0; n < pmic_data_count; n++) {
298 dt_entry_array[k].platform_id = platform_data[i].platform_id;
299 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
300 dt_entry_array[k].variant_id = board_data[j].variant_id;
301 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
302 dt_entry_array[k].pmic_rev[0] = pmic_data[n].pmic_version[0];
303 dt_entry_array[k].pmic_rev[1] = pmic_data[n].pmic_version[1];
304 dt_entry_array[k].pmic_rev[2] = pmic_data[n].pmic_version[2];
305 dt_entry_array[k].pmic_rev[3] = pmic_data[n].pmic_version[3];
306 dt_entry_array[k].offset = (UINT64)dtb;
307 dt_entry_array[k].size = dtb_size;
308 k++;
309 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800310
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700311 } else {
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] = BoardPmicTarget (0);
317 dt_entry_array[k].pmic_rev[1] = BoardPmicTarget (1);
318 dt_entry_array[k].pmic_rev[2] = BoardPmicTarget (2);
319 dt_entry_array[k].pmic_rev[3] = BoardPmicTarget (3);
320 dt_entry_array[k].offset = (UINT64)dtb;
321 dt_entry_array[k].size = dtb_size;
322 k++;
lijuang46df8442017-09-28 19:06:36 +0800323 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700324 }
325 }
326
jianzhoue687ba82017-11-27 16:08:51 +0800327 for (i = 0; i < NumEntries; i++) {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700328 if (platform_dt_absolute_match (&(dt_entry_array[i]), dtb_list)) {
329 DEBUG ((EFI_D_VERBOSE, "Device tree exact match the board: <0x%x 0x%x "
330 "0x%x 0x%x> == <0x%x 0x%x 0x%x 0x%x>\n",
331 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
332 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
333 BoardPlatformRawChipId (), BoardPlatformType (),
334 BoardPlatformChipVersion (), BoardPlatformSubType ()));
335 } else {
336 DEBUG ((EFI_D_VERBOSE, "Device tree's msm_id doesn't match the board: "
337 "<0x%x 0x%x 0x%x 0x%x> != <0x%x 0x%x 0x%x "
338 "0x%x>\n",
339 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
340 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
341 BoardPlatformRawChipId (), BoardPlatformType (),
342 BoardPlatformChipVersion (), BoardPlatformSubType ()));
343 }
344 }
345 Result = TRUE;
346 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800347
lijuang46df8442017-09-28 19:06:36 +0800348Exit:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700349 if (board_data) {
350 FreePool (board_data);
351 board_data = NULL;
352 }
353 if (platform_data) {
354 FreePool (platform_data);
355 platform_data = NULL;
356 }
357 if (pmic_data) {
358 FreePool (pmic_data);
359 pmic_data = NULL;
360 }
361 if (dt_entry_array) {
362 FreePool (dt_entry_array);
363 dt_entry_array = NULL;
364 }
365 if (model) {
366 FreePool (model);
367 model = NULL;
368 }
lijuang46df8442017-09-28 19:06:36 +0800369
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700370 return Result;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800371}
372
373/*
374 * Will relocate the DTB to the tags addr if the device tree is found and return
375 * its address
376 *
377 * Arguments: kernel - Start address of the kernel loaded in RAM
378 * tags - Start address of the tags loaded in RAM
379 * kernel_size - Size of the kernel in bytes
380 *
381 * Return Value: DTB address : If appended device tree is found
382 * 'NULL' : Otherwise
383 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700384VOID *
385DeviceTreeAppended (VOID *kernel,
386 UINT32 kernel_size,
387 UINT32 dtb_offset,
388 VOID *tags)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800389{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700390 EFI_STATUS Status;
391 uintptr_t kernel_end = (uintptr_t)kernel + kernel_size;
392 VOID *dtb = NULL;
393 VOID *bestmatch_tag = NULL;
394 UINT64 RamdiskLoadAddr;
395 UINT64 BaseMemory = 0;
396 struct dt_entry *best_match_dt_entry = NULL;
397 UINT32 bestmatch_tag_size;
398 struct dt_entry_node *dt_entry_queue = NULL;
399 struct dt_entry_node *dt_node_tmp1 = NULL;
400 struct dt_entry_node *dt_node_tmp2 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800401
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700402 /* Initialize the dtb entry node*/
403 dt_entry_queue =
404 (struct dt_entry_node *)AllocatePool (sizeof (struct dt_entry_node));
405 if (!dt_entry_queue) {
406 DEBUG ((EFI_D_ERROR, "Out of memory\n"));
407 return NULL;
408 }
Jeevan Shrirame07dd432016-08-22 11:05:06 -0700409
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700410 memset (dt_entry_queue, 0, sizeof (struct dt_entry_node));
411 list_initialize (&dt_entry_queue->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800412
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700413 if (!dtb_offset) {
414 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
415 goto out;
416 }
Runmin Wang7db42962016-06-27 14:35:35 -0700417
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700418 if (((uintptr_t)kernel + (uintptr_t)dtb_offset) < (uintptr_t)kernel) {
419 goto out;
420 }
421 dtb = kernel + dtb_offset;
422 while (((uintptr_t)dtb + sizeof (struct fdt_header)) <
423 (uintptr_t)kernel_end) {
424 struct fdt_header dtb_hdr;
425 UINT32 dtb_size;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800426
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700427 /* the DTB could be unaligned, so extract the header,
428 * and operate on it separately */
429 gBS->CopyMem (&dtb_hdr, dtb, sizeof (struct fdt_header));
430 if (fdt_check_header ((const VOID *)&dtb_hdr) != 0 ||
431 fdt_check_header_ext ((VOID *)&dtb_hdr) != 0 ||
432 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) <
433 (uintptr_t)dtb) ||
434 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) >
435 (uintptr_t)kernel_end))
436 break;
437 dtb_size = fdt_totalsize (&dtb_hdr);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800438
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700439 if (!DeviceTreeCompatible (dtb, dtb_size, dt_entry_queue)) {
440 DEBUG ((EFI_D_VERBOSE, "Error while DTB parse continue with next DTB\n"));
441 if (!GetRticDtb (dtb))
442 DEBUG ((EFI_D_VERBOSE,
443 "Error while DTB parsing RTIC prop continue with next DTB\n"));
444 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530445
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700446 /* goto the next device tree if any */
447 dtb += dtb_size;
448 }
449 best_match_dt_entry = platform_dt_match_best (dt_entry_queue);
450 if (best_match_dt_entry) {
451 bestmatch_tag = (VOID *)best_match_dt_entry->offset;
452 bestmatch_tag_size = best_match_dt_entry->size;
453 DEBUG ((EFI_D_INFO, "Best match DTB tags "
454 "%u/%08x/0x%08x/%x/%x/%x/%x/%x/(offset)0x%08x/"
455 "(size)0x%08x\n",
456 best_match_dt_entry->platform_id, best_match_dt_entry->variant_id,
457 best_match_dt_entry->board_hw_subtype, best_match_dt_entry->soc_rev,
458 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
459 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
460 best_match_dt_entry->offset, best_match_dt_entry->size));
461 DEBUG ((EFI_D_INFO, "Using pmic info 0x%0x/0x%x/0x%x/0x%0x for device "
462 "0x%0x/0x%x/0x%x/0x%0x\n",
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 BoardPmicTarget (0), BoardPmicTarget (1), BoardPmicTarget (2),
466 BoardPmicTarget (3)));
467 }
468 /* free queue's memory */
469 list_for_every_entry (&dt_entry_queue->node, dt_node_tmp1, dt_node, node)
470 {
471 if (!dt_node_tmp1) {
472 DEBUG ((EFI_D_VERBOSE, "Current node is the end\n"));
473 break;
474 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800475
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700476 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
477 dt_entry_list_delete (dt_node_tmp1);
478 dt_node_tmp1 = dt_node_tmp2;
479 }
lijuangf71a4842017-07-27 19:26:31 +0800480
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700481 if (bestmatch_tag) {
482 Status = BaseMem (&BaseMemory);
483 if (Status != EFI_SUCCESS) {
484 DEBUG ((EFI_D_ERROR, "Unable to find Base memory for DDR %r\n", Status));
485 FreePool (dt_entry_queue);
486 dt_entry_queue = NULL;
487 goto out;
488 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800489
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700490 RamdiskLoadAddr =
491 (EFI_PHYSICAL_ADDRESS) (BaseMemory | PcdGet32 (RamdiskLoadAddress));
492 if ((RamdiskLoadAddr - (UINT64)tags) > RamdiskLoadAddr) {
493 DEBUG ((EFI_D_ERROR, "Tags address is not valid\n"));
494 goto out;
495 }
496 if ((RamdiskLoadAddr - (UINT64)tags) < bestmatch_tag_size) {
497 DEBUG ((EFI_D_ERROR, "Tag size is over the limit\n"));
498 goto out;
499 }
500 gBS->CopyMem (tags, bestmatch_tag, bestmatch_tag_size);
501 /* clear out the old DTB magic so kernel doesn't find it */
502 *((UINT32 *)(kernel + dtb_offset)) = 0;
lijuang46df8442017-09-28 19:06:36 +0800503 FreePool (dt_entry_queue);
504 dt_entry_queue = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700505
506 return tags;
507 }
508
509 DEBUG (
510 (EFI_D_ERROR,
511 "DTB offset is incorrect, kernel image does not have appended DTB\n"));
512
513/*DEBUG((EFI_D_ERROR, "Device info 0x%08x/%08x/0x%08x/%u, pmic
514 0x%0x/0x%x/0x%x/0x%0x\n",
515 board_platform_id(), board_soc_version(),
516 board_target_id(), board_hardware_subtype(),
517 BoardPmicTarget(0), BoardPmicTarget(1),
518 BoardPmicTarget(2), BoardPmicTarget(3)));*/
519out:
520 FreePool (dt_entry_queue);
521 dt_entry_queue = NULL;
522 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800523}
524
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700525STATIC BOOLEAN
526CheckAllBitsSet (UINT32 DtMatchVal)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530527{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700528 return (DtMatchVal & ALL_BITS_SET) == (ALL_BITS_SET);
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530529}
530
Mukesh Ojhafa815352017-11-08 14:43:41 +0530531STATIC VOID
532ReadBestPmicMatch (CONST CHAR8 *PmicProp, UINT32 PmicEntCount,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530533 PmicIdInfo *BestPmicInfo)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530534{
535 UINT32 PmicEntIdx;
536 UINT32 Idx;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530537 PmicIdInfo CurPmicInfo;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530538
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530539 memset (BestPmicInfo, 0, sizeof (PmicIdInfo));
Mukesh Ojhafa815352017-11-08 14:43:41 +0530540 for (PmicEntIdx = 0; PmicEntIdx < PmicEntCount; PmicEntIdx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530541 memset (&CurPmicInfo, 0, sizeof (PmicIdInfo));
Mukesh Ojhafa815352017-11-08 14:43:41 +0530542 for (Idx = 0; Idx < MAX_PMIC_IDX; Idx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530543 CurPmicInfo.DtPmicModel[Idx] =
Mukesh Ojhafa815352017-11-08 14:43:41 +0530544 fdt32_to_cpu (((struct pmic_id *)PmicProp)->pmic_version[Idx]);
545
546 DEBUG ((EFI_D_VERBOSE, "pmic_data[%u].:%x\n", Idx,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530547 CurPmicInfo.DtPmicModel[Idx]));
548 CurPmicInfo.DtPmicRev[Idx] =
549 CurPmicInfo.DtPmicModel[Idx] & PMIC_REV_MASK;
550 CurPmicInfo.DtPmicModel[Idx] =
551 CurPmicInfo.DtPmicModel[Idx] & PMIC_MODEL_MASK;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530552
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530553 if ((CurPmicInfo.DtPmicModel[Idx]) ==
Mukesh Ojhafa815352017-11-08 14:43:41 +0530554 BoardPmicModel (Idx)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530555 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530556 BIT ((PMIC_MATCH_EXACT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530557 } else if (CurPmicInfo.DtPmicModel[Idx] == 0) {
558 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530559 BIT ((PMIC_MATCH_DEFAULT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
560 } else {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530561 CurPmicInfo.DtMatchVal = BIT (NONE_MATCH);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530562 DEBUG ((EFI_D_VERBOSE, "Pmic model does not match\n"));
563 break;
564 }
565
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530566 if (CurPmicInfo.DtPmicRev[Idx] == (BoardPmicTarget (Idx)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530567 & PMIC_REV_MASK)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530568 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530569 BIT ((PMIC_MATCH_EXACT_REV_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530570 } else if (CurPmicInfo.DtPmicRev[Idx] <
Mukesh Ojhafa815352017-11-08 14:43:41 +0530571 (BoardPmicTarget (Idx) & PMIC_REV_MASK)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530572 CurPmicInfo.DtMatchVal |= BIT ((PMIC_MATCH_BEST_REV_IDX0 +
Mukesh Ojhafa815352017-11-08 14:43:41 +0530573 Idx * PMIC_SHIFT_IDX));
574 } else {
575 DEBUG ((EFI_D_VERBOSE, "Pmic revision does not match\n"));
576 break;
577 }
578 }
579
580 DEBUG ((EFI_D_VERBOSE, "BestPmicInfo.DtMatchVal : %x"
581 " CurPmicInfo[%u]->DtMatchVal : %x\n", BestPmicInfo->DtMatchVal,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530582 PmicEntIdx, CurPmicInfo.DtMatchVal));
583 if (BestPmicInfo->DtMatchVal < CurPmicInfo.DtMatchVal) {
584 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530585 sizeof (struct PmicIdInfo));
586 } else if (BestPmicInfo->DtMatchVal ==
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530587 CurPmicInfo.DtMatchVal) {
588 if (BestPmicInfo->DtPmicRev[0] < CurPmicInfo.DtPmicRev[0]) {
589 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530590 sizeof (struct PmicIdInfo));
591 } else if (BestPmicInfo->DtPmicRev[1] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530592 CurPmicInfo.DtPmicRev[1]) {
593 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530594 sizeof (struct PmicIdInfo));
595 } else if (BestPmicInfo->DtPmicRev[2] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530596 CurPmicInfo.DtPmicRev[2]) {
597 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530598 sizeof (struct PmicIdInfo));
599 } else if (BestPmicInfo->DtPmicRev[3] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530600 CurPmicInfo.DtPmicRev[3]) {
601 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530602 sizeof (struct PmicIdInfo));
603 }
604 }
605
606 PmicProp += sizeof (struct pmic_id);
607 }
608}
609
610
Parth Dixitd4887652017-09-13 22:28:52 +0530611/* Dt selection table for quick reference
612 | SNO | Dt Property | CDT Property | Exact | Best | Default |
613 |-----+---------------+-----------------+-------+------+---------+
614 | | qcom, msm-id | | | | |
615 | | | PlatformId | Y | N | N |
616 | | | SocRev | N | Y | N |
617 | | | FoundryId | Y | N | 0 |
618 | | qcom,board-id | | | | |
619 | | | VariantId | Y | N | N |
620 | | | VariantMajor | N | Y | N |
621 | | | VariantMinor | N | Y | N |
622 | | | PlatformSubtype | Y | N | 0 |
623 | | qcom,pmic-id | | | | |
624 | | | PmicModelId | Y | N | 0 |
625 | | | PmicMetalRev | N | Y | N |
626 | | | PmicLayerRev | N | Y | N |
627 | | | PmicVariantRev | N | Y | N |
628*/
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700629STATIC VOID
630ReadDtbFindMatch (DtInfo *CurDtbInfo, DtInfo *BestDtbInfo, UINT32 ExactMatch)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530631{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700632 const char *PlatProp = NULL;
633 const char *BoardProp = NULL;
634 const char *PmicProp = NULL;
635 INT32 LenBoardId;
636 INT32 LenPlatId;
637 INT32 LenPmicId;
638 INT32 MinPlatIdLen = PLAT_ID_SIZE;
639 INT32 RootOffset = 0;
640 VOID *Dtb = CurDtbInfo->Dtb;
641 UINT32 Idx;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530642 UINT32 PmicEntCount;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530643 PmicIdInfo BestPmicInfo;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530644
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700645 /*Ensure MatchVal to 0 initially*/
646 CurDtbInfo->DtMatchVal = 0;
647 RootOffset = fdt_path_offset (Dtb, "/");
648 if (RootOffset < 0) {
649 DEBUG ((EFI_D_ERROR, "Unable to locate root node\n"));
650 return;
651 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530652
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700653 /* Get the msm-id prop from DTB */
654 PlatProp =
655 (const char *)fdt_getprop (Dtb, RootOffset, "qcom,msm-id", &LenPlatId);
656 if (PlatProp && (LenPlatId > 0) && (!(LenPlatId % MinPlatIdLen))) {
657 /*Compare msm-id of the dtb vs Board*/
658 CurDtbInfo->DtPlatformId =
659 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id);
660 DEBUG ((EFI_D_VERBOSE, "Boardsocid = %x, Dtsocid = %x\n",
661 (BoardPlatformRawChipId () & SOC_MASK),
662 (CurDtbInfo->DtPlatformId & SOC_MASK)));
663 if ((BoardPlatformRawChipId () & SOC_MASK) ==
664 (CurDtbInfo->DtPlatformId & SOC_MASK)) {
665 CurDtbInfo->DtMatchVal |= BIT (SOC_MATCH);
666 } else {
667 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id doesnot match\n"));
668 /* If it's neither exact nor default match don't select dtb */
669 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
670 goto cleanup;
671 }
672 /*Compare soc rev of the dtb vs Board*/
673 CurDtbInfo->DtSocRev = fdt32_to_cpu (((struct plat_id *)PlatProp)->soc_rev);
674 DEBUG ((EFI_D_VERBOSE, "BoardSocRev = %x, DtSocRev =%x\n",
675 BoardPlatformChipVersion (), CurDtbInfo->DtSocRev));
676 if (CurDtbInfo->DtSocRev == BoardPlatformChipVersion ()) {
677 CurDtbInfo->DtMatchVal |= BIT (VERSION_EXACT_MATCH);
678 } else if (CurDtbInfo->DtSocRev < BoardPlatformChipVersion ()) {
679 CurDtbInfo->DtMatchVal |= BIT (VERSION_BEST_MATCH);
680 } else if (CurDtbInfo->DtSocRev) {
681 DEBUG ((EFI_D_VERBOSE, "soc version doesnot match\n"));
682 }
683 /*Compare Foundry Id of the dtb vs Board*/
684 CurDtbInfo->DtFoundryId =
685 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id) &
686 FOUNDRY_ID_MASK;
687 DEBUG ((EFI_D_VERBOSE, "BoardFoundry = %x, DtFoundry = %x\n",
688 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT),
689 CurDtbInfo->DtFoundryId));
690 if (CurDtbInfo->DtFoundryId ==
691 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT)) {
692 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_EXACT_MATCH);
693 } else if (CurDtbInfo->DtFoundryId == 0) {
694 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_DEFAULT_MATCH);
695 } else {
696 DEBUG ((EFI_D_VERBOSE, "soc foundry doesnot match\n"));
697 /* If it's neither exact nor default match don't select dtb */
698 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
699 goto cleanup;
700 }
701 } else {
702 DEBUG ((EFI_D_VERBOSE, "qcom, msm-id does not exist (or) is"
703 " (%d) not a multiple of (%d)\n",
704 LenPlatId, MinPlatIdLen));
705 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530706
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700707 /* Get the properties like variant id, subtype from Dtb then compare the
708 * dtb vs Board*/
709 BoardProp = (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,board-id",
710 &LenBoardId);
711 if (BoardProp && (LenBoardId > 0) && (!(LenBoardId % BOARD_ID_SIZE))) {
712 CurDtbInfo->DtVariantId =
713 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id);
714 CurDtbInfo->DtPlatformSubtype =
715 fdt32_to_cpu (((struct board_id *)BoardProp)->platform_subtype);
716 if (CurDtbInfo->DtPlatformSubtype == 0) {
717 CurDtbInfo->DtPlatformSubtype =
718 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id) >>
719 PLATFORM_SUBTYPE_SHIFT_ID;
720 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530721
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700722 DEBUG ((EFI_D_VERBOSE, "BoardVariant = %x, DtVariant = %x\n",
723 BoardPlatformType (), CurDtbInfo->DtVariantId));
724 CurDtbInfo->DtVariantMajor = CurDtbInfo->DtVariantId & VARIANT_MAJOR_MASK;
725 CurDtbInfo->DtVariantMinor = CurDtbInfo->DtVariantId & VARIANT_MINOR_MASK;
726 CurDtbInfo->DtVariantId = CurDtbInfo->DtVariantId & VARIANT_MASK;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530727
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700728 if (CurDtbInfo->DtVariantId == BoardPlatformType ()) {
729 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MATCH);
730 } else if (CurDtbInfo->DtVariantId) {
731 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not"
732 " match\n"));
733 /* If it's neither exact nor default match don't select dtb */
734 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
735 goto cleanup;
736 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530737
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700738 if (CurDtbInfo->DtVariantMajor == (BoardTargetId () & VARIANT_MAJOR_MASK)) {
739 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_EXACT_MATCH);
740 } else if (CurDtbInfo->DtVariantMajor <
741 (BoardTargetId () & VARIANT_MAJOR_MASK)) {
742 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_BEST_MATCH);
743 } else if (CurDtbInfo->DtVariantMajor) {
744 DEBUG ((EFI_D_VERBOSE, "qcom,board-id major version "
745 "does not match\n"));
746 }
Parth Dixitd4887652017-09-13 22:28:52 +0530747
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700748 if (CurDtbInfo->DtVariantMinor == (BoardTargetId () & VARIANT_MINOR_MASK)) {
749 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_EXACT_MATCH);
750 } else if (CurDtbInfo->DtVariantMinor <
751 (BoardTargetId () & VARIANT_MINOR_MASK)) {
752 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_BEST_MATCH);
753 } else if (CurDtbInfo->DtVariantMinor) {
754 DEBUG ((EFI_D_VERBOSE, "qcom,board-id minor version "
755 "does not match\n"));
756 }
Parth Dixitd4887652017-09-13 22:28:52 +0530757
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700758 DEBUG ((EFI_D_VERBOSE, "BoardSubtype = %x, DtSubType = %x\n",
759 BoardPlatformSubType (), CurDtbInfo->DtPlatformSubtype));
760 if (CurDtbInfo->DtPlatformSubtype == BoardPlatformSubType ()) {
761 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_EXACT_MATCH);
762 } else if (CurDtbInfo->DtPlatformSubtype == 0) {
763 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_DEFAULT_MATCH);
jianzhou254e1e02017-11-01 14:52:02 +0800764 } else {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700765 DEBUG ((EFI_D_VERBOSE, "subtype-id doesnot match\n"));
766 /* If it's neither exact nor default match don't select dtb */
767 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
768 goto cleanup;
769 }
770 } else {
771 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not exist (or) (%d) "
772 "is not a multiple of (%d)\n",
773 LenBoardId, BOARD_ID_SIZE));
774 }
Parth Dixitd4887652017-09-13 22:28:52 +0530775
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700776 /*Get the pmic property from Dtb then compare the dtb vs Board*/
777 PmicProp =
778 (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,pmic-id", &LenPmicId);
779 if ((PmicProp) && (LenPmicId > 0) && (!(LenPmicId % PMIC_ID_SIZE))) {
Mukesh Ojhafa815352017-11-08 14:43:41 +0530780 PmicEntCount = LenPmicId / PMIC_ID_SIZE;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530781 /* Get the best match pmic */
782 ReadBestPmicMatch (PmicProp, PmicEntCount, &BestPmicInfo);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530783 CurDtbInfo->DtMatchVal |= BestPmicInfo.DtMatchVal;
784 for (Idx = 0; Idx < MAX_PMIC_IDX; Idx++) {
785 CurDtbInfo->DtPmicModel[Idx] = BestPmicInfo.DtPmicModel[Idx];
786 CurDtbInfo->DtPmicRev[Idx] = BestPmicInfo.DtPmicRev[Idx];
787 }
788
789 DEBUG ((EFI_D_VERBOSE, "CurDtbInfo->DtMatchVal : %x "
790 "BestPmicInfo.DtMatchVal :%x\n", CurDtbInfo->DtMatchVal,
791 BestPmicInfo.DtMatchVal));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700792 } else {
793 DEBUG ((EFI_D_VERBOSE, "qcom,pmic-id does not exit (or) is (%d)"
794 " not a multiple of (%d)\n",
795 LenPmicId, PMIC_ID_SIZE));
796 }
Parth Dixitd4887652017-09-13 22:28:52 +0530797
798cleanup:
Mukesh Ojhafa815352017-11-08 14:43:41 +0530799
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700800 if (CurDtbInfo->DtMatchVal & BIT (ExactMatch)) {
801 if (BestDtbInfo->DtMatchVal < CurDtbInfo->DtMatchVal) {
802 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
803 } else if (BestDtbInfo->DtMatchVal == CurDtbInfo->DtMatchVal) {
804 if (BestDtbInfo->DtSocRev < CurDtbInfo->DtSocRev) {
805 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
806 } else if (BestDtbInfo->DtVariantMajor < CurDtbInfo->DtVariantMajor) {
807 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
808 } else if (BestDtbInfo->DtVariantMinor < CurDtbInfo->DtVariantMinor) {
809 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
810 } else if (BestDtbInfo->DtPmicRev[0] < CurDtbInfo->DtPmicRev[0]) {
811 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
812 } else if (BestDtbInfo->DtPmicRev[1] < CurDtbInfo->DtPmicRev[1]) {
813 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
814 } else if (BestDtbInfo->DtPmicRev[2] < CurDtbInfo->DtPmicRev[2]) {
815 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
816 } else if (BestDtbInfo->DtPmicRev[3] < CurDtbInfo->DtPmicRev[3]) {
817 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
818 }
819 }
820 }
821}
822
823VOID *
824GetSocDtb (VOID *Kernel, UINT32 KernelSize, UINT32 DtbOffset, VOID *DtbLoadAddr)
825{
826 uintptr_t KernelEnd = (uintptr_t)Kernel + KernelSize;
827 VOID *Dtb = NULL;
828 struct fdt_header DtbHdr;
829 UINT32 DtbSize = 0;
830 DtInfo CurDtbInfo = {0};
831 DtInfo BestDtbInfo = {0};
832 if (!DtbOffset) {
833 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
834 return NULL;
835 }
836
837 if (((uintptr_t)Kernel + (uintptr_t)DtbOffset) < (uintptr_t)Kernel) {
838 return NULL;
839 }
840 Dtb = Kernel + DtbOffset;
841 while (((uintptr_t)Dtb + sizeof (struct fdt_header)) < (uintptr_t)KernelEnd) {
842 /* the DTB could be unaligned, so extract the header,
843 * and operate on it separately */
844 gBS->CopyMem (&DtbHdr, Dtb, sizeof (struct fdt_header));
845 DtbSize = fdt_totalsize ((const VOID *)&DtbHdr);
846 if (fdt_check_header ((const VOID *)&DtbHdr) != 0 ||
847 fdt_check_header_ext ((VOID *)&DtbHdr) != 0 ||
848 ((uintptr_t)Dtb + DtbSize < (uintptr_t)Dtb) ||
849 ((uintptr_t)Dtb + DtbSize > (uintptr_t)KernelEnd))
850 break;
851
852 CurDtbInfo.Dtb = Dtb;
853 ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, SOC_MATCH);
854 if (CurDtbInfo.DtMatchVal) {
855 if (CurDtbInfo.DtMatchVal & BIT (SOC_MATCH)) {
856 if (CheckAllBitsSet (CurDtbInfo.DtMatchVal)) {
857 DEBUG ((EFI_D_VERBOSE, "Exact DTB match"
858 " found. DTBO search is not "
859 "required\n"));
860 DtboNeed = FALSE;
Parth Dixitd4887652017-09-13 22:28:52 +0530861 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700862 }
863 } else {
864 if (!GetRticDtb (Dtb)) {
865 DEBUG ((EFI_D_VERBOSE, "Error while DTB parsing"
866 " RTIC prop continue with next DTB\n"));
867 }
868 }
869
870 DEBUG ((EFI_D_VERBOSE, "Bestmatch = %x\n", BestDtbInfo.DtMatchVal));
871 Dtb += DtbSize;
872 }
873
874 if (!BestDtbInfo.Dtb) {
875 DEBUG ((EFI_D_ERROR, "No match found for Soc Dtb type\n"));
876 return NULL;
877 }
878
879 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530880}
881
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700882VOID *
883GetBoardDtb (BootInfo *Info, VOID *DtboImgBuffer)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530884{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700885 struct DtboTableHdr *DtboTableHdr = DtboImgBuffer;
886 struct DtboTableEntry *DtboTableEntry = NULL;
887 UINT32 DtboCount = 0;
888 VOID *BoardDtb = NULL;
889 UINT32 DtboTableEntriesCount = 0;
890 UINT32 FirstDtboTableEntryOffset = 0;
891 DtInfo CurDtbInfo = {0};
892 DtInfo BestDtbInfo = {0};
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530893
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700894 if (!DtboImgBuffer) {
895 DEBUG ((EFI_D_ERROR, "Dtbo Img buffer is NULL\n"));
896 return NULL;
897 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530898
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700899 FirstDtboTableEntryOffset = fdt32_to_cpu (DtboTableHdr->DtEntryOffset);
900 if (CHECK_ADD64 ((UINT64)DtboImgBuffer, FirstDtboTableEntryOffset)) {
901 DEBUG ((EFI_D_ERROR, "Integer overflow deteced with Dtbo address\n"));
902 return NULL;
903 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530904
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700905 DtboTableEntry =
906 (struct DtboTableEntry *)(DtboImgBuffer + FirstDtboTableEntryOffset);
907 if (!DtboTableEntry) {
908 DEBUG ((EFI_D_ERROR, "No proper DtTable\n"));
909 return NULL;
910 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530911
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700912 DtboTableEntriesCount = fdt32_to_cpu (DtboTableHdr->DtEntryCount);
913 for (DtboCount = 0; DtboCount < DtboTableEntriesCount; DtboCount++) {
914 if (CHECK_ADD64 ((UINT64)DtboImgBuffer,
915 fdt32_to_cpu (DtboTableEntry->DtOffset))) {
916 DEBUG ((EFI_D_ERROR, "Integer overflow deteced with Dtbo address\n"));
917 return NULL;
918 }
919 BoardDtb = DtboImgBuffer + fdt32_to_cpu (DtboTableEntry->DtOffset);
920 if (fdt_check_header (BoardDtb) || fdt_check_header_ext (BoardDtb)) {
921 DEBUG ((EFI_D_ERROR, "No Valid Dtb\n"));
922 break;
923 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530924
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700925 CurDtbInfo.Dtb = BoardDtb;
926 ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, VARIANT_MATCH);
927 DEBUG ((EFI_D_VERBOSE, "Dtbo count = %u LocalBoardDtMatch = %x"
928 "\n",
929 DtboCount, CurDtbInfo.DtMatchVal));
930 DtboTableEntry++;
931 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530932
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700933 if (!BestDtbInfo.Dtb) {
934 DEBUG ((EFI_D_ERROR, "Unable to find the Board Dtb\n"));
935 return NULL;
936 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530937
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700938 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530939}
940
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800941/* Returns 0 if the device tree is valid. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700942int
943DeviceTreeValidate (UINT8 *DeviceTreeBuff,
944 UINT32 PageSize,
945 UINT32 *DeviceTreeSize)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800946{
lijuangc336a292017-08-22 19:48:49 +0800947 UINT32 dt_entry_size;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700948 UINT64 hdr_size;
949 struct dt_table *table;
950 if (DeviceTreeSize) {
951 table = (struct dt_table *)DeviceTreeBuff;
952 if (table->magic != DEV_TREE_MAGIC) {
953 // bad magic in device tree table
954 return -1;
955 }
956 if (table->version == DEV_TREE_VERSION_V1) {
957 dt_entry_size = sizeof (struct dt_entry_v1);
958 } else if (table->version == DEV_TREE_VERSION_V2) {
959 dt_entry_size = sizeof (struct dt_entry_v2);
960 } else if (table->version == DEV_TREE_VERSION_V3) {
961 dt_entry_size = sizeof (struct dt_entry);
962 } else {
963 // unsupported dt version
964 return -1;
965 }
966 hdr_size =
967 ((UINT64)table->num_entries * dt_entry_size) + DEV_TREE_HEADER_SIZE;
968 // hdr_size = ROUNDUP(hdr_size, PageSize);
969 hdr_size = EFI_SIZE_TO_PAGES (hdr_size);
970 if (hdr_size > MAX_UINT64)
971 return -1;
972 else
973 *DeviceTreeSize = hdr_size & MAX_UINT64;
974 // dt_entry_ptr = (struct dt_entry *)((CHAR8 *)table +
975 // DEV_TREE_HEADER_SIZE);
976 // table_ptr = dt_entry_ptr;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800977
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700978 DEBUG ((EFI_D_ERROR, "DT Total number of entries: %d, DTB version: %d\n",
979 table->num_entries, table->version));
980 }
981 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800982}
983
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700984STATIC int
985platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
986 struct dt_entry_node *dt_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800987{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700988 UINT32 cur_dt_hw_platform;
989 UINT32 cur_dt_hw_subtype;
990 UINT32 cur_dt_msm_id;
991 dt_node *dt_node_tmp = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800992
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700993 /* Platform-id
994 * bit no |31 24|23 16|15 0|
995 * |reserved|foundry-id|msm-id|
996 */
997 cur_dt_msm_id = (cur_dt_entry->platform_id & 0x0000ffff);
998 cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
999 cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001000
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001001 /* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
1002 * soc, board major/minor, pmic major/minor must less than board info
1003 * 2. find the matched DTB then return 1
1004 * 3. otherwise return 0
1005 */
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001006
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001007 if ((cur_dt_msm_id == (BoardPlatformRawChipId () & 0x0000ffff)) &&
1008 (cur_dt_hw_platform == BoardPlatformType ()) &&
1009 (cur_dt_hw_subtype == BoardPlatformSubType ()) &&
1010 (cur_dt_entry->soc_rev <= BoardPlatformChipVersion ()) &&
1011 ((cur_dt_entry->variant_id & 0x00ffff00) <=
1012 (BoardTargetId () & 0x00ffff00)) &&
1013 (cur_dt_entry->pmic_rev[0] <= BoardPmicTarget (0)) &&
1014 (cur_dt_entry->pmic_rev[1] <= BoardPmicTarget (1)) &&
1015 (cur_dt_entry->pmic_rev[2] <= BoardPmicTarget (2)) &&
1016 (cur_dt_entry->pmic_rev[3] <= BoardPmicTarget (3))) {
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001017
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001018 dt_node_tmp = dt_entry_list_init ();
1019 if (!dt_node_tmp) {
1020 DEBUG ((EFI_D_ERROR, "dt_node_tmp is NULL\n"));
1021 return 0;
1022 }
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +05301023
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001024 gBS->CopyMem ((VOID *)dt_node_tmp->dt_entry_m, (VOID *)cur_dt_entry,
1025 sizeof (struct dt_entry));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001026
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001027 DEBUG (
1028 (EFI_D_VERBOSE,
1029 "Add DTB entry 0x%x/%08x/0x%08x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
1030 dt_node_tmp->dt_entry_m->platform_id,
1031 dt_node_tmp->dt_entry_m->variant_id,
1032 dt_node_tmp->dt_entry_m->board_hw_subtype,
1033 dt_node_tmp->dt_entry_m->soc_rev, dt_node_tmp->dt_entry_m->pmic_rev[0],
1034 dt_node_tmp->dt_entry_m->pmic_rev[1],
1035 dt_node_tmp->dt_entry_m->pmic_rev[2],
1036 dt_node_tmp->dt_entry_m->pmic_rev[3], dt_node_tmp->dt_entry_m->offset,
1037 dt_node_tmp->dt_entry_m->size));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001038
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001039 insert_dt_entry_in_queue (dt_list, dt_node_tmp);
1040 return 1;
1041 }
1042 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001043}
1044
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001045int
1046platform_dt_absolute_compat_match (struct dt_entry_node *dt_list,
1047 UINT32 dtb_info)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001048{
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001049 struct dt_entry_node *dt_node_tmp1 = NULL;
1050 struct dt_entry_node *dt_node_tmp2 = NULL;
1051 UINT32 current_info = 0;
1052 UINT32 board_info = 0;
1053 UINT32 best_info = 0;
1054 UINT32 current_pmic_model[4] = {0, 0, 0, 0};
1055 UINT32 board_pmic_model[4] = {0, 0, 0, 0};
1056 UINT32 best_pmic_model[4] = {0, 0, 0, 0};
1057 UINT32 delete_current_dt = 0;
1058 UINT32 i;
1059
1060 /* start to select the exact entry
1061 * default to exact match 0, if find current DTB entry info is the same as
1062 * board info,
1063 * then exact match board info.
1064 */
1065 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1066 {
1067 if (!dt_node_tmp1) {
1068 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1069 break;
1070 }
1071 switch (dtb_info) {
1072 case DTB_FOUNDRY:
1073 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1074 board_info = BoardPlatformFoundryId () << 16;
1075 break;
1076 case DTB_PMIC_MODEL:
1077 for (i = 0; i < 4; i++) {
1078 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1079 board_pmic_model[i] = BoardPmicModel (i);
1080 }
1081 break;
1082 default:
1083 DEBUG ((EFI_D_ERROR,
1084 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1085 return 0;
1086 }
1087
1088 if (dtb_info == DTB_PMIC_MODEL) {
1089 if ((current_pmic_model[0] == board_pmic_model[0]) &&
1090 (current_pmic_model[1] == board_pmic_model[1]) &&
1091 (current_pmic_model[2] == board_pmic_model[2]) &&
1092 (current_pmic_model[3] == board_pmic_model[3])) {
1093
1094 for (i = 0; i < 4; i++) {
1095 best_pmic_model[i] = current_pmic_model[i];
1096 }
1097 break;
1098 }
1099 } else {
1100 if (current_info == board_info) {
1101 best_info = current_info;
1102 break;
1103 }
1104 }
1105 }
1106
1107 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1108 {
1109 if (!dt_node_tmp1) {
1110 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1111 break;
1112 }
1113 switch (dtb_info) {
1114 case DTB_FOUNDRY:
1115 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1116 break;
1117 case DTB_PMIC_MODEL:
1118 for (i = 0; i < 4; i++) {
1119 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1120 }
1121 break;
1122 default:
1123 DEBUG ((EFI_D_ERROR,
1124 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1125 return 0;
1126 }
1127
1128 if (dtb_info == DTB_PMIC_MODEL) {
1129 if ((current_pmic_model[0] != best_pmic_model[0]) ||
1130 (current_pmic_model[1] != best_pmic_model[1]) ||
1131 (current_pmic_model[2] != best_pmic_model[2]) ||
1132 (current_pmic_model[3] != best_pmic_model[3])) {
1133
1134 delete_current_dt = 1;
1135 }
1136 } else {
1137 if (current_info != best_info) {
1138 delete_current_dt = 1;
1139 }
1140 }
1141
1142 if (delete_current_dt) {
1143 DEBUG (
1144 (EFI_D_VERBOSE,
1145 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1146 dt_node_tmp1->dt_entry_m->platform_id,
1147 dt_node_tmp1->dt_entry_m->variant_id,
1148 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1149 dt_node_tmp1->dt_entry_m->soc_rev,
1150 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1151 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1152 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1153 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1154 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1155
1156 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1157 dt_entry_list_delete (dt_node_tmp1);
1158 dt_node_tmp1 = dt_node_tmp2;
1159 delete_current_dt = 0;
1160 }
1161 }
1162
1163 return 1;
1164}
1165
1166int
1167update_dtb_entry_node (struct dt_entry_node *dt_list, UINT32 dtb_info)
1168{
1169 struct dt_entry_node *dt_node_tmp1 = NULL;
1170 struct dt_entry_node *dt_node_tmp2 = NULL;
1171 UINT32 current_info = 0;
1172 UINT32 board_info = 0;
1173 UINT32 best_info = 0;
1174
1175 /* start to select the best entry*/
1176 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1177 {
1178 if (!dt_node_tmp1) {
1179 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1180 break;
1181 }
1182 switch (dtb_info) {
1183 case DTB_SOC:
1184 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1185 board_info = BoardPlatformChipVersion ();
1186 break;
1187 case DTB_MAJOR_MINOR:
1188 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1189 board_info = BoardTargetId () & 0x00ffff00;
1190 break;
1191 case DTB_PMIC0:
1192 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1193 board_info = BoardPmicTarget (0);
1194 break;
1195 case DTB_PMIC1:
1196 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1197 board_info = BoardPmicTarget (1);
1198 break;
1199 case DTB_PMIC2:
1200 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1201 board_info = BoardPmicTarget (2);
1202 break;
1203 case DTB_PMIC3:
1204 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1205 board_info = BoardPmicTarget (3);
1206 break;
1207 default:
1208 DEBUG ((EFI_D_ERROR,
1209 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1210 return 0;
1211 }
1212
1213 if (current_info == board_info) {
1214 best_info = current_info;
1215 break;
1216 }
1217 if ((current_info < board_info) && (current_info > best_info)) {
1218 best_info = current_info;
1219 }
1220 if (current_info < best_info) {
1221 DEBUG (
1222 (EFI_D_ERROR,
1223 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1224 dt_node_tmp1->dt_entry_m->platform_id,
1225 dt_node_tmp1->dt_entry_m->variant_id,
1226 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1227 dt_node_tmp1->dt_entry_m->soc_rev,
1228 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1229 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1230 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1231 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1232 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1233
1234 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1235 dt_entry_list_delete (dt_node_tmp1);
1236 dt_node_tmp1 = dt_node_tmp2;
1237 }
1238 }
1239
1240 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1241 {
1242 if (!dt_node_tmp1) {
1243 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1244 break;
1245 }
1246 switch (dtb_info) {
1247 case DTB_SOC:
1248 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1249 break;
1250 case DTB_MAJOR_MINOR:
1251 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1252 break;
1253 case DTB_PMIC0:
1254 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1255 break;
1256 case DTB_PMIC1:
1257 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1258 break;
1259 case DTB_PMIC2:
1260 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1261 break;
1262 case DTB_PMIC3:
1263 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1264 break;
1265 default:
1266 DEBUG ((EFI_D_ERROR,
1267 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1268 return 0;
1269 }
1270
1271 if (current_info != best_info) {
1272 DEBUG (
1273 (EFI_D_VERBOSE,
1274 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1275 dt_node_tmp1->dt_entry_m->platform_id,
1276 dt_node_tmp1->dt_entry_m->variant_id,
1277 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1278 dt_node_tmp1->dt_entry_m->soc_rev,
1279 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1280 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1281 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1282 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1283 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1284
1285 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1286 dt_entry_list_delete (dt_node_tmp1);
1287 dt_node_tmp1 = dt_node_tmp2;
1288 }
1289 }
1290 return 1;
1291}
1292
1293STATIC struct dt_entry *
1294platform_dt_match_best (struct dt_entry_node *dt_list)
1295{
1296 struct dt_entry_node *dt_node_tmp1 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001297
lijuangc336a292017-08-22 19:48:49 +08001298 /* check Foundry id
1299 * the foundry id must exact match board founddry id, this is compatibility
1300 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1301 */
1302 platform_dt_absolute_compat_match (dt_list, DTB_FOUNDRY);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001303
lijuangc336a292017-08-22 19:48:49 +08001304 /* check PMIC model
1305 * the PMIC model must exact match board PMIC model, this is compatibility
1306 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1307 */
1308 platform_dt_absolute_compat_match (dt_list, DTB_PMIC_MODEL);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001309
lijuangc336a292017-08-22 19:48:49 +08001310 /* check soc version
1311 * the suitable soc version must less than or equal to board soc version
1312 */
1313 update_dtb_entry_node (dt_list, DTB_SOC);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001314
lijuangc336a292017-08-22 19:48:49 +08001315 /*check major and minor version
1316 * the suitable major&minor version must less than or equal to board
1317 * major&minor version
1318 */
1319 update_dtb_entry_node (dt_list, DTB_MAJOR_MINOR);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001320
lijuangc336a292017-08-22 19:48:49 +08001321 /*check pmic info
1322 * the suitable pmic major&minor info must less than or equal to board pmic
1323 * major&minor version
1324 */
1325 update_dtb_entry_node (dt_list, DTB_PMIC0);
1326 update_dtb_entry_node (dt_list, DTB_PMIC1);
1327 update_dtb_entry_node (dt_list, DTB_PMIC2);
1328 update_dtb_entry_node (dt_list, DTB_PMIC3);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001329
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001330 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1331 {
1332 if (!dt_node_tmp1) {
1333 DEBUG ((EFI_D_ERROR, "ERROR: Couldn't find the suitable DTB!\n"));
1334 return NULL;
1335 }
1336 if (dt_node_tmp1->dt_entry_m)
1337 return dt_node_tmp1->dt_entry_m;
1338 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001339
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001340 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001341}