blob: 70c9815c1db7823a5ac6e91a1716b1633ec98711 [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;
119 UINT32 num_entries = 0;
120 UINT32 i, j, k, n;
121 UINT32 msm_data_count;
122 UINT32 board_data_count;
123 UINT32 pmic_data_count;
124 BOOLEAN Result = FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800125
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700126 root_offset = fdt_path_offset (dtb, "/");
127 if (root_offset < 0)
128 return FALSE;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800129
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700130 prop = fdt_getprop (dtb, root_offset, "model", &len);
131 if (prop && len > 0) {
132 model = (char *)AllocatePool (sizeof (char) * len);
133 if (!model) {
134 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for model\n"));
135 return FALSE;
136 }
137 AsciiStrnCpyS (model, (sizeof (CHAR8) * len), prop, len);
138 } else {
139 DEBUG ((EFI_D_ERROR, "model does not exist in device tree\n"));
140 }
141 /* Find the pmic-id prop from DTB , if pmic-id is present then
142 * the DTB is version 3, otherwise find the board-id prop from DTB ,
143 * if board-id is present then the DTB is version 2 */
144 pmic_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,pmic-id",
145 &len_pmic_id);
146 board_prop = (const char *)fdt_getprop (dtb, root_offset, "qcom,board-id",
147 &len_board_id);
148 if (pmic_prop && (len_pmic_id > 0) && board_prop && (len_board_id > 0)) {
149 if ((len_pmic_id % PMIC_ID_SIZE) || (len_board_id % BOARD_ID_SIZE)) {
150 DEBUG ((EFI_D_ERROR, "qcom,pmic-id (%d) or qcom,board-id(%d) in device "
151 "tree is not a multiple of (%d %d)\n",
152 len_pmic_id, len_board_id, PMIC_ID_SIZE, BOARD_ID_SIZE));
153 goto Exit;
154 }
155 dtb_ver = DEV_TREE_VERSION_V3;
156 min_plat_id_len = PLAT_ID_SIZE;
157 } else if (board_prop && len_board_id > 0) {
158 if (len_board_id % BOARD_ID_SIZE) {
159 DEBUG ((EFI_D_ERROR,
160 "qcom,pmic-id (%d) in device tree is not a multiple of (%d)\n",
161 len_board_id, BOARD_ID_SIZE));
162 goto Exit;
163 }
164 dtb_ver = DEV_TREE_VERSION_V2;
165 min_plat_id_len = PLAT_ID_SIZE;
166 } else {
167 dtb_ver = DEV_TREE_VERSION_V1;
168 min_plat_id_len = DT_ENTRY_V1_SIZE;
169 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800170
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700171 /* Get the msm-id prop from DTB */
172 plat_prop =
173 (const char *)fdt_getprop (dtb, root_offset, "qcom,msm-id", &len_plat_id);
174 if (!plat_prop || len_plat_id <= 0) {
175 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id entry not found\n"));
176 goto Exit;
177 } else if (len_plat_id % min_plat_id_len) {
178 DEBUG ((EFI_D_ERROR,
179 "qcom, msm-id in device tree is (%d) not a multiple of (%d)\n",
180 len_plat_id, min_plat_id_len));
181 goto Exit;
182 }
183 if (dtb_ver == DEV_TREE_VERSION_V2 || dtb_ver == DEV_TREE_VERSION_V3) {
184 board_data_count = (len_board_id / BOARD_ID_SIZE);
185 msm_data_count = (len_plat_id / PLAT_ID_SIZE);
186 /* If dtb version is v2.0, the pmic_data_count will be <= 0 */
187 pmic_data_count = (len_pmic_id / PMIC_ID_SIZE);
188
189 /* If we are using dtb v3.0, then we have split board, msm & pmic data in
190 * the DTB
191 * If we are using dtb v2.0, then we have split board & msmdata in the DTB
192 */
193 board_data = (struct board_id *)AllocatePool (
194 sizeof (struct board_id) * (len_board_id / BOARD_ID_SIZE));
195 if (!board_data) {
196 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for board_data\n"));
197 goto Exit;
198 }
199
200 platform_data = (struct plat_id *)AllocatePool (
201 sizeof (struct plat_id) * (len_plat_id / PLAT_ID_SIZE));
202 if (!platform_data) {
203 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for platform_data\n"));
204 goto Exit;
205 }
206 if (dtb_ver == DEV_TREE_VERSION_V3) {
207 pmic_data = (struct pmic_id *)AllocatePool (sizeof (struct pmic_id) *
208 (len_pmic_id / PMIC_ID_SIZE));
209 if (!pmic_data) {
210 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for pmic_data\n"));
lijuang46df8442017-09-28 19:06:36 +0800211 goto Exit;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700212 }
213 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800214
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700215 /* Extract board data from DTB */
216 for (i = 0; i < board_data_count; i++) {
217 board_data[i].variant_id =
218 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id);
219 board_data[i].platform_subtype =
220 fdt32_to_cpu (((struct board_id *)board_prop)->platform_subtype);
221 /* For V2/V3 version of DTBs we have platform version field as part
222 * of variant ID, in such case the subtype will be mentioned as 0x0
223 * As the qcom, board-id = <0xSSPMPmPH, 0x0>
224 * SS -- Subtype
225 * PM -- Platform major version
226 * Pm -- Platform minor version
227 * PH -- Platform hardware CDP/MTP
228 * In such case to make it compatible with LK algorithm move the subtype
229 * from variant_id to subtype field
230 */
231 if (board_data[i].platform_subtype == 0)
232 board_data[i].platform_subtype =
233 fdt32_to_cpu (((struct board_id *)board_prop)->variant_id) >> 0x18;
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +0530234
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700235 len_board_id -= sizeof (struct board_id);
236 board_prop += sizeof (struct board_id);
237 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800238
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700239 /* Extract platform data from DTB */
240 for (i = 0; i < msm_data_count; i++) {
241 platform_data[i].platform_id =
242 fdt32_to_cpu (((struct plat_id *)plat_prop)->platform_id);
243 platform_data[i].soc_rev =
244 fdt32_to_cpu (((struct plat_id *)plat_prop)->soc_rev);
245 len_plat_id -= sizeof (struct plat_id);
246 plat_prop += sizeof (struct plat_id);
247 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800248
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700249 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
250 /* Extract pmic data from DTB */
251 for (i = 0; i < pmic_data_count; i++) {
252 pmic_data[i].pmic_version[0] =
253 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[0]);
254 pmic_data[i].pmic_version[1] =
255 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[1]);
256 pmic_data[i].pmic_version[2] =
257 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[2]);
258 pmic_data[i].pmic_version[3] =
259 fdt32_to_cpu (((struct pmic_id *)pmic_prop)->pmic_version[3]);
260 len_pmic_id -= sizeof (struct pmic_id);
261 pmic_prop += sizeof (struct pmic_id);
262 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800263
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700264 /* We need to merge board & platform data into dt entry structure */
265 num_entries = msm_data_count * board_data_count * pmic_data_count;
266 } else {
267 /* We need to merge board & platform data into dt entry structure */
268 num_entries = msm_data_count * board_data_count;
269 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800270
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700271 if ((((uint64_t)msm_data_count * (uint64_t)board_data_count *
272 (uint64_t)pmic_data_count) !=
273 msm_data_count * board_data_count * pmic_data_count) ||
274 (((uint64_t)msm_data_count * (uint64_t)board_data_count) !=
275 msm_data_count * board_data_count)) {
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800276
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700277 goto Exit;
278 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800279
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700280 dt_entry_array = (struct dt_entry *)AllocatePool (sizeof (struct dt_entry) *
281 num_entries);
282 if (!dt_entry_array) {
283 DEBUG ((EFI_D_ERROR, "Failed to allocate memory for dt_entry_array\n"));
284 goto Exit;
285 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800286
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700287 /* If we have '<X>; <Y>; <Z>' as platform data & '<A>; <B>; <C>' as board
288 * data.
289 * Then dt entry should look like
290 * <X ,A >;<X, B>;<X, C>;
291 * <Y ,A >;<Y, B>;<Y, C>;
292 * <Z ,A >;<Z, B>;<Z, C>;
293 */
294 k = 0;
295 for (i = 0; i < msm_data_count; i++) {
296 for (j = 0; j < board_data_count; j++) {
297 if (dtb_ver == DEV_TREE_VERSION_V3 && pmic_prop) {
298 for (n = 0; n < pmic_data_count; n++) {
299 dt_entry_array[k].platform_id = platform_data[i].platform_id;
300 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
301 dt_entry_array[k].variant_id = board_data[j].variant_id;
302 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
303 dt_entry_array[k].pmic_rev[0] = pmic_data[n].pmic_version[0];
304 dt_entry_array[k].pmic_rev[1] = pmic_data[n].pmic_version[1];
305 dt_entry_array[k].pmic_rev[2] = pmic_data[n].pmic_version[2];
306 dt_entry_array[k].pmic_rev[3] = pmic_data[n].pmic_version[3];
307 dt_entry_array[k].offset = (UINT64)dtb;
308 dt_entry_array[k].size = dtb_size;
309 k++;
310 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800311
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700312 } else {
313 dt_entry_array[k].platform_id = platform_data[i].platform_id;
314 dt_entry_array[k].soc_rev = platform_data[i].soc_rev;
315 dt_entry_array[k].variant_id = board_data[j].variant_id;
316 dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
317 dt_entry_array[k].pmic_rev[0] = BoardPmicTarget (0);
318 dt_entry_array[k].pmic_rev[1] = BoardPmicTarget (1);
319 dt_entry_array[k].pmic_rev[2] = BoardPmicTarget (2);
320 dt_entry_array[k].pmic_rev[3] = BoardPmicTarget (3);
321 dt_entry_array[k].offset = (UINT64)dtb;
322 dt_entry_array[k].size = dtb_size;
323 k++;
lijuang46df8442017-09-28 19:06:36 +0800324 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700325 }
326 }
327
328 for (i = 0; i < num_entries; i++) {
329 if (platform_dt_absolute_match (&(dt_entry_array[i]), dtb_list)) {
330 DEBUG ((EFI_D_VERBOSE, "Device tree exact match the board: <0x%x 0x%x "
331 "0x%x 0x%x> == <0x%x 0x%x 0x%x 0x%x>\n",
332 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
333 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
334 BoardPlatformRawChipId (), BoardPlatformType (),
335 BoardPlatformChipVersion (), BoardPlatformSubType ()));
336 } else {
337 DEBUG ((EFI_D_VERBOSE, "Device tree's msm_id doesn't match the board: "
338 "<0x%x 0x%x 0x%x 0x%x> != <0x%x 0x%x 0x%x "
339 "0x%x>\n",
340 dt_entry_array[i].platform_id, dt_entry_array[i].variant_id,
341 dt_entry_array[i].soc_rev, dt_entry_array[i].board_hw_subtype,
342 BoardPlatformRawChipId (), BoardPlatformType (),
343 BoardPlatformChipVersion (), BoardPlatformSubType ()));
344 }
345 }
346 Result = TRUE;
347 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800348
lijuang46df8442017-09-28 19:06:36 +0800349Exit:
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700350 if (board_data) {
351 FreePool (board_data);
352 board_data = NULL;
353 }
354 if (platform_data) {
355 FreePool (platform_data);
356 platform_data = NULL;
357 }
358 if (pmic_data) {
359 FreePool (pmic_data);
360 pmic_data = NULL;
361 }
362 if (dt_entry_array) {
363 FreePool (dt_entry_array);
364 dt_entry_array = NULL;
365 }
366 if (model) {
367 FreePool (model);
368 model = NULL;
369 }
lijuang46df8442017-09-28 19:06:36 +0800370
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700371 return Result;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800372}
373
374/*
375 * Will relocate the DTB to the tags addr if the device tree is found and return
376 * its address
377 *
378 * Arguments: kernel - Start address of the kernel loaded in RAM
379 * tags - Start address of the tags loaded in RAM
380 * kernel_size - Size of the kernel in bytes
381 *
382 * Return Value: DTB address : If appended device tree is found
383 * 'NULL' : Otherwise
384 */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700385VOID *
386DeviceTreeAppended (VOID *kernel,
387 UINT32 kernel_size,
388 UINT32 dtb_offset,
389 VOID *tags)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800390{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700391 EFI_STATUS Status;
392 uintptr_t kernel_end = (uintptr_t)kernel + kernel_size;
393 VOID *dtb = NULL;
394 VOID *bestmatch_tag = NULL;
395 UINT64 RamdiskLoadAddr;
396 UINT64 BaseMemory = 0;
397 struct dt_entry *best_match_dt_entry = NULL;
398 UINT32 bestmatch_tag_size;
399 struct dt_entry_node *dt_entry_queue = NULL;
400 struct dt_entry_node *dt_node_tmp1 = NULL;
401 struct dt_entry_node *dt_node_tmp2 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800402
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700403 /* Initialize the dtb entry node*/
404 dt_entry_queue =
405 (struct dt_entry_node *)AllocatePool (sizeof (struct dt_entry_node));
406 if (!dt_entry_queue) {
407 DEBUG ((EFI_D_ERROR, "Out of memory\n"));
408 return NULL;
409 }
Jeevan Shrirame07dd432016-08-22 11:05:06 -0700410
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700411 memset (dt_entry_queue, 0, sizeof (struct dt_entry_node));
412 list_initialize (&dt_entry_queue->node);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800413
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700414 if (!dtb_offset) {
415 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
416 goto out;
417 }
Runmin Wang7db42962016-06-27 14:35:35 -0700418
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700419 if (((uintptr_t)kernel + (uintptr_t)dtb_offset) < (uintptr_t)kernel) {
420 goto out;
421 }
422 dtb = kernel + dtb_offset;
423 while (((uintptr_t)dtb + sizeof (struct fdt_header)) <
424 (uintptr_t)kernel_end) {
425 struct fdt_header dtb_hdr;
426 UINT32 dtb_size;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800427
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700428 /* the DTB could be unaligned, so extract the header,
429 * and operate on it separately */
430 gBS->CopyMem (&dtb_hdr, dtb, sizeof (struct fdt_header));
431 if (fdt_check_header ((const VOID *)&dtb_hdr) != 0 ||
432 fdt_check_header_ext ((VOID *)&dtb_hdr) != 0 ||
433 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) <
434 (uintptr_t)dtb) ||
435 ((uintptr_t)dtb + (uintptr_t)fdt_totalsize ((const VOID *)&dtb_hdr) >
436 (uintptr_t)kernel_end))
437 break;
438 dtb_size = fdt_totalsize (&dtb_hdr);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800439
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700440 if (!DeviceTreeCompatible (dtb, dtb_size, dt_entry_queue)) {
441 DEBUG ((EFI_D_VERBOSE, "Error while DTB parse continue with next DTB\n"));
442 if (!GetRticDtb (dtb))
443 DEBUG ((EFI_D_VERBOSE,
444 "Error while DTB parsing RTIC prop continue with next DTB\n"));
445 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530446
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700447 /* goto the next device tree if any */
448 dtb += dtb_size;
449 }
450 best_match_dt_entry = platform_dt_match_best (dt_entry_queue);
451 if (best_match_dt_entry) {
452 bestmatch_tag = (VOID *)best_match_dt_entry->offset;
453 bestmatch_tag_size = best_match_dt_entry->size;
454 DEBUG ((EFI_D_INFO, "Best match DTB tags "
455 "%u/%08x/0x%08x/%x/%x/%x/%x/%x/(offset)0x%08x/"
456 "(size)0x%08x\n",
457 best_match_dt_entry->platform_id, best_match_dt_entry->variant_id,
458 best_match_dt_entry->board_hw_subtype, best_match_dt_entry->soc_rev,
459 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
460 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
461 best_match_dt_entry->offset, best_match_dt_entry->size));
462 DEBUG ((EFI_D_INFO, "Using pmic info 0x%0x/0x%x/0x%x/0x%0x for device "
463 "0x%0x/0x%x/0x%x/0x%0x\n",
464 best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
465 best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
466 BoardPmicTarget (0), BoardPmicTarget (1), BoardPmicTarget (2),
467 BoardPmicTarget (3)));
468 }
469 /* free queue's memory */
470 list_for_every_entry (&dt_entry_queue->node, dt_node_tmp1, dt_node, node)
471 {
472 if (!dt_node_tmp1) {
473 DEBUG ((EFI_D_VERBOSE, "Current node is the end\n"));
474 break;
475 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800476
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700477 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
478 dt_entry_list_delete (dt_node_tmp1);
479 dt_node_tmp1 = dt_node_tmp2;
480 }
lijuangf71a4842017-07-27 19:26:31 +0800481
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700482 if (bestmatch_tag) {
483 Status = BaseMem (&BaseMemory);
484 if (Status != EFI_SUCCESS) {
485 DEBUG ((EFI_D_ERROR, "Unable to find Base memory for DDR %r\n", Status));
486 FreePool (dt_entry_queue);
487 dt_entry_queue = NULL;
488 goto out;
489 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800490
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700491 RamdiskLoadAddr =
492 (EFI_PHYSICAL_ADDRESS) (BaseMemory | PcdGet32 (RamdiskLoadAddress));
493 if ((RamdiskLoadAddr - (UINT64)tags) > RamdiskLoadAddr) {
494 DEBUG ((EFI_D_ERROR, "Tags address is not valid\n"));
495 goto out;
496 }
497 if ((RamdiskLoadAddr - (UINT64)tags) < bestmatch_tag_size) {
498 DEBUG ((EFI_D_ERROR, "Tag size is over the limit\n"));
499 goto out;
500 }
501 gBS->CopyMem (tags, bestmatch_tag, bestmatch_tag_size);
502 /* clear out the old DTB magic so kernel doesn't find it */
503 *((UINT32 *)(kernel + dtb_offset)) = 0;
lijuang46df8442017-09-28 19:06:36 +0800504 FreePool (dt_entry_queue);
505 dt_entry_queue = NULL;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700506
507 return tags;
508 }
509
510 DEBUG (
511 (EFI_D_ERROR,
512 "DTB offset is incorrect, kernel image does not have appended DTB\n"));
513
514/*DEBUG((EFI_D_ERROR, "Device info 0x%08x/%08x/0x%08x/%u, pmic
515 0x%0x/0x%x/0x%x/0x%0x\n",
516 board_platform_id(), board_soc_version(),
517 board_target_id(), board_hardware_subtype(),
518 BoardPmicTarget(0), BoardPmicTarget(1),
519 BoardPmicTarget(2), BoardPmicTarget(3)));*/
520out:
521 FreePool (dt_entry_queue);
522 dt_entry_queue = NULL;
523 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800524}
525
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700526STATIC BOOLEAN
527CheckAllBitsSet (UINT32 DtMatchVal)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530528{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700529 return (DtMatchVal & ALL_BITS_SET) == (ALL_BITS_SET);
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530530}
531
Mukesh Ojhafa815352017-11-08 14:43:41 +0530532STATIC VOID
533ReadBestPmicMatch (CONST CHAR8 *PmicProp, UINT32 PmicEntCount,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530534 PmicIdInfo *BestPmicInfo)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530535{
536 UINT32 PmicEntIdx;
537 UINT32 Idx;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530538 PmicIdInfo CurPmicInfo;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530539
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530540 memset (BestPmicInfo, 0, sizeof (PmicIdInfo));
Mukesh Ojhafa815352017-11-08 14:43:41 +0530541 for (PmicEntIdx = 0; PmicEntIdx < PmicEntCount; PmicEntIdx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530542 memset (&CurPmicInfo, 0, sizeof (PmicIdInfo));
Mukesh Ojhafa815352017-11-08 14:43:41 +0530543 for (Idx = 0; Idx < MAX_PMIC_IDX; Idx++) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530544 CurPmicInfo.DtPmicModel[Idx] =
Mukesh Ojhafa815352017-11-08 14:43:41 +0530545 fdt32_to_cpu (((struct pmic_id *)PmicProp)->pmic_version[Idx]);
546
547 DEBUG ((EFI_D_VERBOSE, "pmic_data[%u].:%x\n", Idx,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530548 CurPmicInfo.DtPmicModel[Idx]));
549 CurPmicInfo.DtPmicRev[Idx] =
550 CurPmicInfo.DtPmicModel[Idx] & PMIC_REV_MASK;
551 CurPmicInfo.DtPmicModel[Idx] =
552 CurPmicInfo.DtPmicModel[Idx] & PMIC_MODEL_MASK;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530553
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530554 if ((CurPmicInfo.DtPmicModel[Idx]) ==
Mukesh Ojhafa815352017-11-08 14:43:41 +0530555 BoardPmicModel (Idx)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530556 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530557 BIT ((PMIC_MATCH_EXACT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530558 } else if (CurPmicInfo.DtPmicModel[Idx] == 0) {
559 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530560 BIT ((PMIC_MATCH_DEFAULT_MODEL_IDX0 + Idx * PMIC_SHIFT_IDX));
561 } else {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530562 CurPmicInfo.DtMatchVal = BIT (NONE_MATCH);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530563 DEBUG ((EFI_D_VERBOSE, "Pmic model does not match\n"));
564 break;
565 }
566
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530567 if (CurPmicInfo.DtPmicRev[Idx] == (BoardPmicTarget (Idx)
Mukesh Ojhafa815352017-11-08 14:43:41 +0530568 & PMIC_REV_MASK)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530569 CurPmicInfo.DtMatchVal |=
Mukesh Ojhafa815352017-11-08 14:43:41 +0530570 BIT ((PMIC_MATCH_EXACT_REV_IDX0 + Idx * PMIC_SHIFT_IDX));
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530571 } else if (CurPmicInfo.DtPmicRev[Idx] <
Mukesh Ojhafa815352017-11-08 14:43:41 +0530572 (BoardPmicTarget (Idx) & PMIC_REV_MASK)) {
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530573 CurPmicInfo.DtMatchVal |= BIT ((PMIC_MATCH_BEST_REV_IDX0 +
Mukesh Ojhafa815352017-11-08 14:43:41 +0530574 Idx * PMIC_SHIFT_IDX));
575 } else {
576 DEBUG ((EFI_D_VERBOSE, "Pmic revision does not match\n"));
577 break;
578 }
579 }
580
581 DEBUG ((EFI_D_VERBOSE, "BestPmicInfo.DtMatchVal : %x"
582 " CurPmicInfo[%u]->DtMatchVal : %x\n", BestPmicInfo->DtMatchVal,
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530583 PmicEntIdx, CurPmicInfo.DtMatchVal));
584 if (BestPmicInfo->DtMatchVal < CurPmicInfo.DtMatchVal) {
585 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530586 sizeof (struct PmicIdInfo));
587 } else if (BestPmicInfo->DtMatchVal ==
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530588 CurPmicInfo.DtMatchVal) {
589 if (BestPmicInfo->DtPmicRev[0] < CurPmicInfo.DtPmicRev[0]) {
590 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530591 sizeof (struct PmicIdInfo));
592 } else if (BestPmicInfo->DtPmicRev[1] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530593 CurPmicInfo.DtPmicRev[1]) {
594 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530595 sizeof (struct PmicIdInfo));
596 } else if (BestPmicInfo->DtPmicRev[2] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530597 CurPmicInfo.DtPmicRev[2]) {
598 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530599 sizeof (struct PmicIdInfo));
600 } else if (BestPmicInfo->DtPmicRev[3] <
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530601 CurPmicInfo.DtPmicRev[3]) {
602 gBS->CopyMem (BestPmicInfo, &CurPmicInfo,
Mukesh Ojhafa815352017-11-08 14:43:41 +0530603 sizeof (struct PmicIdInfo));
604 }
605 }
606
607 PmicProp += sizeof (struct pmic_id);
608 }
609}
610
611
Parth Dixitd4887652017-09-13 22:28:52 +0530612/* Dt selection table for quick reference
613 | SNO | Dt Property | CDT Property | Exact | Best | Default |
614 |-----+---------------+-----------------+-------+------+---------+
615 | | qcom, msm-id | | | | |
616 | | | PlatformId | Y | N | N |
617 | | | SocRev | N | Y | N |
618 | | | FoundryId | Y | N | 0 |
619 | | qcom,board-id | | | | |
620 | | | VariantId | Y | N | N |
621 | | | VariantMajor | N | Y | N |
622 | | | VariantMinor | N | Y | N |
623 | | | PlatformSubtype | Y | N | 0 |
624 | | qcom,pmic-id | | | | |
625 | | | PmicModelId | Y | N | 0 |
626 | | | PmicMetalRev | N | Y | N |
627 | | | PmicLayerRev | N | Y | N |
628 | | | PmicVariantRev | N | Y | N |
629*/
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700630STATIC VOID
631ReadDtbFindMatch (DtInfo *CurDtbInfo, DtInfo *BestDtbInfo, UINT32 ExactMatch)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530632{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700633 const char *PlatProp = NULL;
634 const char *BoardProp = NULL;
635 const char *PmicProp = NULL;
636 INT32 LenBoardId;
637 INT32 LenPlatId;
638 INT32 LenPmicId;
639 INT32 MinPlatIdLen = PLAT_ID_SIZE;
640 INT32 RootOffset = 0;
641 VOID *Dtb = CurDtbInfo->Dtb;
642 UINT32 Idx;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530643 UINT32 PmicEntCount;
Mukesh Ojhafa815352017-11-08 14:43:41 +0530644 PmicIdInfo BestPmicInfo;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530645
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700646 /*Ensure MatchVal to 0 initially*/
647 CurDtbInfo->DtMatchVal = 0;
648 RootOffset = fdt_path_offset (Dtb, "/");
649 if (RootOffset < 0) {
650 DEBUG ((EFI_D_ERROR, "Unable to locate root node\n"));
651 return;
652 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530653
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700654 /* Get the msm-id prop from DTB */
655 PlatProp =
656 (const char *)fdt_getprop (Dtb, RootOffset, "qcom,msm-id", &LenPlatId);
657 if (PlatProp && (LenPlatId > 0) && (!(LenPlatId % MinPlatIdLen))) {
658 /*Compare msm-id of the dtb vs Board*/
659 CurDtbInfo->DtPlatformId =
660 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id);
661 DEBUG ((EFI_D_VERBOSE, "Boardsocid = %x, Dtsocid = %x\n",
662 (BoardPlatformRawChipId () & SOC_MASK),
663 (CurDtbInfo->DtPlatformId & SOC_MASK)));
664 if ((BoardPlatformRawChipId () & SOC_MASK) ==
665 (CurDtbInfo->DtPlatformId & SOC_MASK)) {
666 CurDtbInfo->DtMatchVal |= BIT (SOC_MATCH);
667 } else {
668 DEBUG ((EFI_D_VERBOSE, "qcom,msm-id doesnot match\n"));
669 /* If it's neither exact nor default match don't select dtb */
670 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
671 goto cleanup;
672 }
673 /*Compare soc rev of the dtb vs Board*/
674 CurDtbInfo->DtSocRev = fdt32_to_cpu (((struct plat_id *)PlatProp)->soc_rev);
675 DEBUG ((EFI_D_VERBOSE, "BoardSocRev = %x, DtSocRev =%x\n",
676 BoardPlatformChipVersion (), CurDtbInfo->DtSocRev));
677 if (CurDtbInfo->DtSocRev == BoardPlatformChipVersion ()) {
678 CurDtbInfo->DtMatchVal |= BIT (VERSION_EXACT_MATCH);
679 } else if (CurDtbInfo->DtSocRev < BoardPlatformChipVersion ()) {
680 CurDtbInfo->DtMatchVal |= BIT (VERSION_BEST_MATCH);
681 } else if (CurDtbInfo->DtSocRev) {
682 DEBUG ((EFI_D_VERBOSE, "soc version doesnot match\n"));
683 }
684 /*Compare Foundry Id of the dtb vs Board*/
685 CurDtbInfo->DtFoundryId =
686 fdt32_to_cpu (((struct plat_id *)PlatProp)->platform_id) &
687 FOUNDRY_ID_MASK;
688 DEBUG ((EFI_D_VERBOSE, "BoardFoundry = %x, DtFoundry = %x\n",
689 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT),
690 CurDtbInfo->DtFoundryId));
691 if (CurDtbInfo->DtFoundryId ==
692 (BoardPlatformFoundryId () << PLATFORM_FOUNDRY_SHIFT)) {
693 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_EXACT_MATCH);
694 } else if (CurDtbInfo->DtFoundryId == 0) {
695 CurDtbInfo->DtMatchVal |= BIT (FOUNDRYID_DEFAULT_MATCH);
696 } else {
697 DEBUG ((EFI_D_VERBOSE, "soc foundry doesnot match\n"));
698 /* If it's neither exact nor default match don't select dtb */
699 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
700 goto cleanup;
701 }
702 } else {
703 DEBUG ((EFI_D_VERBOSE, "qcom, msm-id does not exist (or) is"
704 " (%d) not a multiple of (%d)\n",
705 LenPlatId, MinPlatIdLen));
706 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530707
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700708 /* Get the properties like variant id, subtype from Dtb then compare the
709 * dtb vs Board*/
710 BoardProp = (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,board-id",
711 &LenBoardId);
712 if (BoardProp && (LenBoardId > 0) && (!(LenBoardId % BOARD_ID_SIZE))) {
713 CurDtbInfo->DtVariantId =
714 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id);
715 CurDtbInfo->DtPlatformSubtype =
716 fdt32_to_cpu (((struct board_id *)BoardProp)->platform_subtype);
717 if (CurDtbInfo->DtPlatformSubtype == 0) {
718 CurDtbInfo->DtPlatformSubtype =
719 fdt32_to_cpu (((struct board_id *)BoardProp)->variant_id) >>
720 PLATFORM_SUBTYPE_SHIFT_ID;
721 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530722
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700723 DEBUG ((EFI_D_VERBOSE, "BoardVariant = %x, DtVariant = %x\n",
724 BoardPlatformType (), CurDtbInfo->DtVariantId));
725 CurDtbInfo->DtVariantMajor = CurDtbInfo->DtVariantId & VARIANT_MAJOR_MASK;
726 CurDtbInfo->DtVariantMinor = CurDtbInfo->DtVariantId & VARIANT_MINOR_MASK;
727 CurDtbInfo->DtVariantId = CurDtbInfo->DtVariantId & VARIANT_MASK;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530728
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700729 if (CurDtbInfo->DtVariantId == BoardPlatformType ()) {
730 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MATCH);
731 } else if (CurDtbInfo->DtVariantId) {
732 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not"
733 " match\n"));
734 /* If it's neither exact nor default match don't select dtb */
735 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
736 goto cleanup;
737 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530738
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700739 if (CurDtbInfo->DtVariantMajor == (BoardTargetId () & VARIANT_MAJOR_MASK)) {
740 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_EXACT_MATCH);
741 } else if (CurDtbInfo->DtVariantMajor <
742 (BoardTargetId () & VARIANT_MAJOR_MASK)) {
743 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MAJOR_BEST_MATCH);
744 } else if (CurDtbInfo->DtVariantMajor) {
745 DEBUG ((EFI_D_VERBOSE, "qcom,board-id major version "
746 "does not match\n"));
747 }
Parth Dixitd4887652017-09-13 22:28:52 +0530748
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700749 if (CurDtbInfo->DtVariantMinor == (BoardTargetId () & VARIANT_MINOR_MASK)) {
750 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_EXACT_MATCH);
751 } else if (CurDtbInfo->DtVariantMinor <
752 (BoardTargetId () & VARIANT_MINOR_MASK)) {
753 CurDtbInfo->DtMatchVal |= BIT (VARIANT_MINOR_BEST_MATCH);
754 } else if (CurDtbInfo->DtVariantMinor) {
755 DEBUG ((EFI_D_VERBOSE, "qcom,board-id minor version "
756 "does not match\n"));
757 }
Parth Dixitd4887652017-09-13 22:28:52 +0530758
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700759 DEBUG ((EFI_D_VERBOSE, "BoardSubtype = %x, DtSubType = %x\n",
760 BoardPlatformSubType (), CurDtbInfo->DtPlatformSubtype));
761 if (CurDtbInfo->DtPlatformSubtype == BoardPlatformSubType ()) {
762 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_EXACT_MATCH);
763 } else if (CurDtbInfo->DtPlatformSubtype == 0) {
764 CurDtbInfo->DtMatchVal |= BIT (SUBTYPE_DEFAULT_MATCH);
jianzhou254e1e02017-11-01 14:52:02 +0800765 } else {
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700766 DEBUG ((EFI_D_VERBOSE, "subtype-id doesnot match\n"));
767 /* If it's neither exact nor default match don't select dtb */
768 CurDtbInfo->DtMatchVal = BIT (NONE_MATCH);
769 goto cleanup;
770 }
771 } else {
772 DEBUG ((EFI_D_VERBOSE, "qcom,board-id does not exist (or) (%d) "
773 "is not a multiple of (%d)\n",
774 LenBoardId, BOARD_ID_SIZE));
775 }
Parth Dixitd4887652017-09-13 22:28:52 +0530776
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700777 /*Get the pmic property from Dtb then compare the dtb vs Board*/
778 PmicProp =
779 (CONST CHAR8 *)fdt_getprop (Dtb, RootOffset, "qcom,pmic-id", &LenPmicId);
780 if ((PmicProp) && (LenPmicId > 0) && (!(LenPmicId % PMIC_ID_SIZE))) {
Mukesh Ojhafa815352017-11-08 14:43:41 +0530781 PmicEntCount = LenPmicId / PMIC_ID_SIZE;
Mukesh Ojha8ff5b4a2017-12-28 17:47:19 +0530782 /* Get the best match pmic */
783 ReadBestPmicMatch (PmicProp, PmicEntCount, &BestPmicInfo);
Mukesh Ojhafa815352017-11-08 14:43:41 +0530784 CurDtbInfo->DtMatchVal |= BestPmicInfo.DtMatchVal;
785 for (Idx = 0; Idx < MAX_PMIC_IDX; Idx++) {
786 CurDtbInfo->DtPmicModel[Idx] = BestPmicInfo.DtPmicModel[Idx];
787 CurDtbInfo->DtPmicRev[Idx] = BestPmicInfo.DtPmicRev[Idx];
788 }
789
790 DEBUG ((EFI_D_VERBOSE, "CurDtbInfo->DtMatchVal : %x "
791 "BestPmicInfo.DtMatchVal :%x\n", CurDtbInfo->DtMatchVal,
792 BestPmicInfo.DtMatchVal));
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700793 } else {
794 DEBUG ((EFI_D_VERBOSE, "qcom,pmic-id does not exit (or) is (%d)"
795 " not a multiple of (%d)\n",
796 LenPmicId, PMIC_ID_SIZE));
797 }
Parth Dixitd4887652017-09-13 22:28:52 +0530798
799cleanup:
Mukesh Ojhafa815352017-11-08 14:43:41 +0530800
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700801 if (CurDtbInfo->DtMatchVal & BIT (ExactMatch)) {
802 if (BestDtbInfo->DtMatchVal < CurDtbInfo->DtMatchVal) {
803 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
804 } else if (BestDtbInfo->DtMatchVal == CurDtbInfo->DtMatchVal) {
805 if (BestDtbInfo->DtSocRev < CurDtbInfo->DtSocRev) {
806 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
807 } else if (BestDtbInfo->DtVariantMajor < CurDtbInfo->DtVariantMajor) {
808 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
809 } else if (BestDtbInfo->DtVariantMinor < CurDtbInfo->DtVariantMinor) {
810 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
811 } else if (BestDtbInfo->DtPmicRev[0] < CurDtbInfo->DtPmicRev[0]) {
812 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
813 } else if (BestDtbInfo->DtPmicRev[1] < CurDtbInfo->DtPmicRev[1]) {
814 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
815 } else if (BestDtbInfo->DtPmicRev[2] < CurDtbInfo->DtPmicRev[2]) {
816 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
817 } else if (BestDtbInfo->DtPmicRev[3] < CurDtbInfo->DtPmicRev[3]) {
818 gBS->CopyMem (BestDtbInfo, CurDtbInfo, sizeof (struct DtInfo));
819 }
820 }
821 }
822}
823
824VOID *
825GetSocDtb (VOID *Kernel, UINT32 KernelSize, UINT32 DtbOffset, VOID *DtbLoadAddr)
826{
827 uintptr_t KernelEnd = (uintptr_t)Kernel + KernelSize;
828 VOID *Dtb = NULL;
829 struct fdt_header DtbHdr;
830 UINT32 DtbSize = 0;
831 DtInfo CurDtbInfo = {0};
832 DtInfo BestDtbInfo = {0};
833 if (!DtbOffset) {
834 DEBUG ((EFI_D_ERROR, "DTB offset is NULL\n"));
835 return NULL;
836 }
837
838 if (((uintptr_t)Kernel + (uintptr_t)DtbOffset) < (uintptr_t)Kernel) {
839 return NULL;
840 }
841 Dtb = Kernel + DtbOffset;
842 while (((uintptr_t)Dtb + sizeof (struct fdt_header)) < (uintptr_t)KernelEnd) {
843 /* the DTB could be unaligned, so extract the header,
844 * and operate on it separately */
845 gBS->CopyMem (&DtbHdr, Dtb, sizeof (struct fdt_header));
846 DtbSize = fdt_totalsize ((const VOID *)&DtbHdr);
847 if (fdt_check_header ((const VOID *)&DtbHdr) != 0 ||
848 fdt_check_header_ext ((VOID *)&DtbHdr) != 0 ||
849 ((uintptr_t)Dtb + DtbSize < (uintptr_t)Dtb) ||
850 ((uintptr_t)Dtb + DtbSize > (uintptr_t)KernelEnd))
851 break;
852
853 CurDtbInfo.Dtb = Dtb;
854 ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, SOC_MATCH);
855 if (CurDtbInfo.DtMatchVal) {
856 if (CurDtbInfo.DtMatchVal & BIT (SOC_MATCH)) {
857 if (CheckAllBitsSet (CurDtbInfo.DtMatchVal)) {
858 DEBUG ((EFI_D_VERBOSE, "Exact DTB match"
859 " found. DTBO search is not "
860 "required\n"));
861 DtboNeed = FALSE;
Parth Dixitd4887652017-09-13 22:28:52 +0530862 }
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700863 }
864 } else {
865 if (!GetRticDtb (Dtb)) {
866 DEBUG ((EFI_D_VERBOSE, "Error while DTB parsing"
867 " RTIC prop continue with next DTB\n"));
868 }
869 }
870
871 DEBUG ((EFI_D_VERBOSE, "Bestmatch = %x\n", BestDtbInfo.DtMatchVal));
872 Dtb += DtbSize;
873 }
874
875 if (!BestDtbInfo.Dtb) {
876 DEBUG ((EFI_D_ERROR, "No match found for Soc Dtb type\n"));
877 return NULL;
878 }
879
880 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530881}
882
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700883VOID *
884GetBoardDtb (BootInfo *Info, VOID *DtboImgBuffer)
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530885{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700886 struct DtboTableHdr *DtboTableHdr = DtboImgBuffer;
887 struct DtboTableEntry *DtboTableEntry = NULL;
888 UINT32 DtboCount = 0;
889 VOID *BoardDtb = NULL;
890 UINT32 DtboTableEntriesCount = 0;
891 UINT32 FirstDtboTableEntryOffset = 0;
892 DtInfo CurDtbInfo = {0};
893 DtInfo BestDtbInfo = {0};
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530894
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700895 if (!DtboImgBuffer) {
896 DEBUG ((EFI_D_ERROR, "Dtbo Img buffer is NULL\n"));
897 return NULL;
898 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530899
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700900 FirstDtboTableEntryOffset = fdt32_to_cpu (DtboTableHdr->DtEntryOffset);
901 if (CHECK_ADD64 ((UINT64)DtboImgBuffer, FirstDtboTableEntryOffset)) {
902 DEBUG ((EFI_D_ERROR, "Integer overflow deteced with Dtbo address\n"));
903 return NULL;
904 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530905
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700906 DtboTableEntry =
907 (struct DtboTableEntry *)(DtboImgBuffer + FirstDtboTableEntryOffset);
908 if (!DtboTableEntry) {
909 DEBUG ((EFI_D_ERROR, "No proper DtTable\n"));
910 return NULL;
911 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530912
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700913 DtboTableEntriesCount = fdt32_to_cpu (DtboTableHdr->DtEntryCount);
914 for (DtboCount = 0; DtboCount < DtboTableEntriesCount; DtboCount++) {
915 if (CHECK_ADD64 ((UINT64)DtboImgBuffer,
916 fdt32_to_cpu (DtboTableEntry->DtOffset))) {
917 DEBUG ((EFI_D_ERROR, "Integer overflow deteced with Dtbo address\n"));
918 return NULL;
919 }
920 BoardDtb = DtboImgBuffer + fdt32_to_cpu (DtboTableEntry->DtOffset);
921 if (fdt_check_header (BoardDtb) || fdt_check_header_ext (BoardDtb)) {
922 DEBUG ((EFI_D_ERROR, "No Valid Dtb\n"));
923 break;
924 }
Mukesh Ojhaa1bd1f82017-05-25 19:04:21 +0530925
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700926 CurDtbInfo.Dtb = BoardDtb;
927 ReadDtbFindMatch (&CurDtbInfo, &BestDtbInfo, VARIANT_MATCH);
928 DEBUG ((EFI_D_VERBOSE, "Dtbo count = %u LocalBoardDtMatch = %x"
929 "\n",
930 DtboCount, CurDtbInfo.DtMatchVal));
931 DtboTableEntry++;
932 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530933
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700934 if (!BestDtbInfo.Dtb) {
935 DEBUG ((EFI_D_ERROR, "Unable to find the Board Dtb\n"));
936 return NULL;
937 }
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530938
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700939 return BestDtbInfo.Dtb;
Vijay Kumar Pendoti644a20b2017-03-15 18:22:17 +0530940}
941
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800942/* Returns 0 if the device tree is valid. */
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700943int
944DeviceTreeValidate (UINT8 *DeviceTreeBuff,
945 UINT32 PageSize,
946 UINT32 *DeviceTreeSize)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800947{
lijuangc336a292017-08-22 19:48:49 +0800948 UINT32 dt_entry_size;
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700949 UINT64 hdr_size;
950 struct dt_table *table;
951 if (DeviceTreeSize) {
952 table = (struct dt_table *)DeviceTreeBuff;
953 if (table->magic != DEV_TREE_MAGIC) {
954 // bad magic in device tree table
955 return -1;
956 }
957 if (table->version == DEV_TREE_VERSION_V1) {
958 dt_entry_size = sizeof (struct dt_entry_v1);
959 } else if (table->version == DEV_TREE_VERSION_V2) {
960 dt_entry_size = sizeof (struct dt_entry_v2);
961 } else if (table->version == DEV_TREE_VERSION_V3) {
962 dt_entry_size = sizeof (struct dt_entry);
963 } else {
964 // unsupported dt version
965 return -1;
966 }
967 hdr_size =
968 ((UINT64)table->num_entries * dt_entry_size) + DEV_TREE_HEADER_SIZE;
969 // hdr_size = ROUNDUP(hdr_size, PageSize);
970 hdr_size = EFI_SIZE_TO_PAGES (hdr_size);
971 if (hdr_size > MAX_UINT64)
972 return -1;
973 else
974 *DeviceTreeSize = hdr_size & MAX_UINT64;
975 // dt_entry_ptr = (struct dt_entry *)((CHAR8 *)table +
976 // DEV_TREE_HEADER_SIZE);
977 // table_ptr = dt_entry_ptr;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800978
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700979 DEBUG ((EFI_D_ERROR, "DT Total number of entries: %d, DTB version: %d\n",
980 table->num_entries, table->version));
981 }
982 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800983}
984
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700985STATIC int
986platform_dt_absolute_match (struct dt_entry *cur_dt_entry,
987 struct dt_entry_node *dt_list)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800988{
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700989 UINT32 cur_dt_hw_platform;
990 UINT32 cur_dt_hw_subtype;
991 UINT32 cur_dt_msm_id;
992 dt_node *dt_node_tmp = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -0800993
Jeevan Shriram17f173d2017-10-24 22:11:07 -0700994 /* Platform-id
995 * bit no |31 24|23 16|15 0|
996 * |reserved|foundry-id|msm-id|
997 */
998 cur_dt_msm_id = (cur_dt_entry->platform_id & 0x0000ffff);
999 cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
1000 cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001001
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001002 /* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
1003 * soc, board major/minor, pmic major/minor must less than board info
1004 * 2. find the matched DTB then return 1
1005 * 3. otherwise return 0
1006 */
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001007
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001008 if ((cur_dt_msm_id == (BoardPlatformRawChipId () & 0x0000ffff)) &&
1009 (cur_dt_hw_platform == BoardPlatformType ()) &&
1010 (cur_dt_hw_subtype == BoardPlatformSubType ()) &&
1011 (cur_dt_entry->soc_rev <= BoardPlatformChipVersion ()) &&
1012 ((cur_dt_entry->variant_id & 0x00ffff00) <=
1013 (BoardTargetId () & 0x00ffff00)) &&
1014 (cur_dt_entry->pmic_rev[0] <= BoardPmicTarget (0)) &&
1015 (cur_dt_entry->pmic_rev[1] <= BoardPmicTarget (1)) &&
1016 (cur_dt_entry->pmic_rev[2] <= BoardPmicTarget (2)) &&
1017 (cur_dt_entry->pmic_rev[3] <= BoardPmicTarget (3))) {
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001018
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001019 dt_node_tmp = dt_entry_list_init ();
1020 if (!dt_node_tmp) {
1021 DEBUG ((EFI_D_ERROR, "dt_node_tmp is NULL\n"));
1022 return 0;
1023 }
Vijay Kumar Pendoti1e847bd2016-11-21 15:29:13 +05301024
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001025 gBS->CopyMem ((VOID *)dt_node_tmp->dt_entry_m, (VOID *)cur_dt_entry,
1026 sizeof (struct dt_entry));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001027
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001028 DEBUG (
1029 (EFI_D_VERBOSE,
1030 "Add DTB entry 0x%x/%08x/0x%08x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
1031 dt_node_tmp->dt_entry_m->platform_id,
1032 dt_node_tmp->dt_entry_m->variant_id,
1033 dt_node_tmp->dt_entry_m->board_hw_subtype,
1034 dt_node_tmp->dt_entry_m->soc_rev, dt_node_tmp->dt_entry_m->pmic_rev[0],
1035 dt_node_tmp->dt_entry_m->pmic_rev[1],
1036 dt_node_tmp->dt_entry_m->pmic_rev[2],
1037 dt_node_tmp->dt_entry_m->pmic_rev[3], dt_node_tmp->dt_entry_m->offset,
1038 dt_node_tmp->dt_entry_m->size));
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001039
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001040 insert_dt_entry_in_queue (dt_list, dt_node_tmp);
1041 return 1;
1042 }
1043 return 0;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001044}
1045
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001046int
1047platform_dt_absolute_compat_match (struct dt_entry_node *dt_list,
1048 UINT32 dtb_info)
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001049{
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001050 struct dt_entry_node *dt_node_tmp1 = NULL;
1051 struct dt_entry_node *dt_node_tmp2 = NULL;
1052 UINT32 current_info = 0;
1053 UINT32 board_info = 0;
1054 UINT32 best_info = 0;
1055 UINT32 current_pmic_model[4] = {0, 0, 0, 0};
1056 UINT32 board_pmic_model[4] = {0, 0, 0, 0};
1057 UINT32 best_pmic_model[4] = {0, 0, 0, 0};
1058 UINT32 delete_current_dt = 0;
1059 UINT32 i;
1060
1061 /* start to select the exact entry
1062 * default to exact match 0, if find current DTB entry info is the same as
1063 * board info,
1064 * then exact match board info.
1065 */
1066 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1067 {
1068 if (!dt_node_tmp1) {
1069 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1070 break;
1071 }
1072 switch (dtb_info) {
1073 case DTB_FOUNDRY:
1074 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1075 board_info = BoardPlatformFoundryId () << 16;
1076 break;
1077 case DTB_PMIC_MODEL:
1078 for (i = 0; i < 4; i++) {
1079 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1080 board_pmic_model[i] = BoardPmicModel (i);
1081 }
1082 break;
1083 default:
1084 DEBUG ((EFI_D_ERROR,
1085 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1086 return 0;
1087 }
1088
1089 if (dtb_info == DTB_PMIC_MODEL) {
1090 if ((current_pmic_model[0] == board_pmic_model[0]) &&
1091 (current_pmic_model[1] == board_pmic_model[1]) &&
1092 (current_pmic_model[2] == board_pmic_model[2]) &&
1093 (current_pmic_model[3] == board_pmic_model[3])) {
1094
1095 for (i = 0; i < 4; i++) {
1096 best_pmic_model[i] = current_pmic_model[i];
1097 }
1098 break;
1099 }
1100 } else {
1101 if (current_info == board_info) {
1102 best_info = current_info;
1103 break;
1104 }
1105 }
1106 }
1107
1108 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1109 {
1110 if (!dt_node_tmp1) {
1111 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1112 break;
1113 }
1114 switch (dtb_info) {
1115 case DTB_FOUNDRY:
1116 current_info = ((dt_node_tmp1->dt_entry_m->platform_id) & 0x00ff0000);
1117 break;
1118 case DTB_PMIC_MODEL:
1119 for (i = 0; i < 4; i++) {
1120 current_pmic_model[i] = (dt_node_tmp1->dt_entry_m->pmic_rev[i] & 0xff);
1121 }
1122 break;
1123 default:
1124 DEBUG ((EFI_D_ERROR,
1125 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1126 return 0;
1127 }
1128
1129 if (dtb_info == DTB_PMIC_MODEL) {
1130 if ((current_pmic_model[0] != best_pmic_model[0]) ||
1131 (current_pmic_model[1] != best_pmic_model[1]) ||
1132 (current_pmic_model[2] != best_pmic_model[2]) ||
1133 (current_pmic_model[3] != best_pmic_model[3])) {
1134
1135 delete_current_dt = 1;
1136 }
1137 } else {
1138 if (current_info != best_info) {
1139 delete_current_dt = 1;
1140 }
1141 }
1142
1143 if (delete_current_dt) {
1144 DEBUG (
1145 (EFI_D_VERBOSE,
1146 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1147 dt_node_tmp1->dt_entry_m->platform_id,
1148 dt_node_tmp1->dt_entry_m->variant_id,
1149 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1150 dt_node_tmp1->dt_entry_m->soc_rev,
1151 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1152 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1153 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1154 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1155 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1156
1157 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1158 dt_entry_list_delete (dt_node_tmp1);
1159 dt_node_tmp1 = dt_node_tmp2;
1160 delete_current_dt = 0;
1161 }
1162 }
1163
1164 return 1;
1165}
1166
1167int
1168update_dtb_entry_node (struct dt_entry_node *dt_list, UINT32 dtb_info)
1169{
1170 struct dt_entry_node *dt_node_tmp1 = NULL;
1171 struct dt_entry_node *dt_node_tmp2 = NULL;
1172 UINT32 current_info = 0;
1173 UINT32 board_info = 0;
1174 UINT32 best_info = 0;
1175
1176 /* start to select the best entry*/
1177 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1178 {
1179 if (!dt_node_tmp1) {
1180 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1181 break;
1182 }
1183 switch (dtb_info) {
1184 case DTB_SOC:
1185 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1186 board_info = BoardPlatformChipVersion ();
1187 break;
1188 case DTB_MAJOR_MINOR:
1189 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1190 board_info = BoardTargetId () & 0x00ffff00;
1191 break;
1192 case DTB_PMIC0:
1193 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1194 board_info = BoardPmicTarget (0);
1195 break;
1196 case DTB_PMIC1:
1197 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1198 board_info = BoardPmicTarget (1);
1199 break;
1200 case DTB_PMIC2:
1201 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1202 board_info = BoardPmicTarget (2);
1203 break;
1204 case DTB_PMIC3:
1205 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1206 board_info = BoardPmicTarget (3);
1207 break;
1208 default:
1209 DEBUG ((EFI_D_ERROR,
1210 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1211 return 0;
1212 }
1213
1214 if (current_info == board_info) {
1215 best_info = current_info;
1216 break;
1217 }
1218 if ((current_info < board_info) && (current_info > best_info)) {
1219 best_info = current_info;
1220 }
1221 if (current_info < best_info) {
1222 DEBUG (
1223 (EFI_D_ERROR,
1224 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1225 dt_node_tmp1->dt_entry_m->platform_id,
1226 dt_node_tmp1->dt_entry_m->variant_id,
1227 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1228 dt_node_tmp1->dt_entry_m->soc_rev,
1229 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1230 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1231 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1232 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1233 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1234
1235 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1236 dt_entry_list_delete (dt_node_tmp1);
1237 dt_node_tmp1 = dt_node_tmp2;
1238 }
1239 }
1240
1241 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1242 {
1243 if (!dt_node_tmp1) {
1244 DEBUG ((EFI_D_ERROR, "Current node is the end\n"));
1245 break;
1246 }
1247 switch (dtb_info) {
1248 case DTB_SOC:
1249 current_info = dt_node_tmp1->dt_entry_m->soc_rev;
1250 break;
1251 case DTB_MAJOR_MINOR:
1252 current_info = ((dt_node_tmp1->dt_entry_m->variant_id) & 0x00ffff00);
1253 break;
1254 case DTB_PMIC0:
1255 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[0];
1256 break;
1257 case DTB_PMIC1:
1258 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[1];
1259 break;
1260 case DTB_PMIC2:
1261 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[2];
1262 break;
1263 case DTB_PMIC3:
1264 current_info = dt_node_tmp1->dt_entry_m->pmic_rev[3];
1265 break;
1266 default:
1267 DEBUG ((EFI_D_ERROR,
1268 "ERROR: Unsupported version (%d) in dt node check \n", dtb_info));
1269 return 0;
1270 }
1271
1272 if (current_info != best_info) {
1273 DEBUG (
1274 (EFI_D_VERBOSE,
1275 "Delete don't fit DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
1276 dt_node_tmp1->dt_entry_m->platform_id,
1277 dt_node_tmp1->dt_entry_m->variant_id,
1278 dt_node_tmp1->dt_entry_m->board_hw_subtype,
1279 dt_node_tmp1->dt_entry_m->soc_rev,
1280 dt_node_tmp1->dt_entry_m->pmic_rev[0],
1281 dt_node_tmp1->dt_entry_m->pmic_rev[1],
1282 dt_node_tmp1->dt_entry_m->pmic_rev[2],
1283 dt_node_tmp1->dt_entry_m->pmic_rev[3],
1284 dt_node_tmp1->dt_entry_m->offset, dt_node_tmp1->dt_entry_m->size));
1285
1286 dt_node_tmp2 = (struct dt_entry_node *)dt_node_tmp1->node.prev;
1287 dt_entry_list_delete (dt_node_tmp1);
1288 dt_node_tmp1 = dt_node_tmp2;
1289 }
1290 }
1291 return 1;
1292}
1293
1294STATIC struct dt_entry *
1295platform_dt_match_best (struct dt_entry_node *dt_list)
1296{
1297 struct dt_entry_node *dt_node_tmp1 = NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001298
lijuangc336a292017-08-22 19:48:49 +08001299 /* check Foundry id
1300 * the foundry id must exact match board founddry id, this is compatibility
1301 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1302 */
1303 platform_dt_absolute_compat_match (dt_list, DTB_FOUNDRY);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001304
lijuangc336a292017-08-22 19:48:49 +08001305 /* check PMIC model
1306 * the PMIC model must exact match board PMIC model, this is compatibility
1307 * check, if couldn't find the exact match from DTB, will exact match 0x0.
1308 */
1309 platform_dt_absolute_compat_match (dt_list, DTB_PMIC_MODEL);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001310
lijuangc336a292017-08-22 19:48:49 +08001311 /* check soc version
1312 * the suitable soc version must less than or equal to board soc version
1313 */
1314 update_dtb_entry_node (dt_list, DTB_SOC);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001315
lijuangc336a292017-08-22 19:48:49 +08001316 /*check major and minor version
1317 * the suitable major&minor version must less than or equal to board
1318 * major&minor version
1319 */
1320 update_dtb_entry_node (dt_list, DTB_MAJOR_MINOR);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001321
lijuangc336a292017-08-22 19:48:49 +08001322 /*check pmic info
1323 * the suitable pmic major&minor info must less than or equal to board pmic
1324 * major&minor version
1325 */
1326 update_dtb_entry_node (dt_list, DTB_PMIC0);
1327 update_dtb_entry_node (dt_list, DTB_PMIC1);
1328 update_dtb_entry_node (dt_list, DTB_PMIC2);
1329 update_dtb_entry_node (dt_list, DTB_PMIC3);
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001330
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001331 list_for_every_entry (&dt_list->node, dt_node_tmp1, dt_node, node)
1332 {
1333 if (!dt_node_tmp1) {
1334 DEBUG ((EFI_D_ERROR, "ERROR: Couldn't find the suitable DTB!\n"));
1335 return NULL;
1336 }
1337 if (dt_node_tmp1->dt_entry_m)
1338 return dt_node_tmp1->dt_entry_m;
1339 }
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001340
Jeevan Shriram17f173d2017-10-24 22:11:07 -07001341 return NULL;
Sridhar Parasuramc8f50022015-12-05 10:36:04 -08001342}