blob: f5117012d62c9ffe7c7337a365e45fa12bd56790 [file] [log] [blame]
Michal Simek9755e3d2019-01-21 15:25:02 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
Michal Simek8174cd22023-01-06 09:38:52 +01003 * (C) Copyright 2014 - 2022, Xilinx, Inc.
4 * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc.
5 *
6 * Michal Simek <michal.simek@amd.com>
Michal Simek9755e3d2019-01-21 15:25:02 +01007 */
8
9#include <common.h>
Sughosh Ganu741ef862022-04-15 11:29:34 +053010#include <efi.h>
11#include <efi_loader.h>
Simon Glass09140112020-05-10 11:40:03 -060012#include <env.h>
Michal Simeka32c3e92022-08-25 14:23:10 +020013#include <image.h>
Algapally Santosh Sagarfb737f12023-01-19 22:36:14 -070014#include <init.h>
James Hilliard6c4a7392024-03-31 17:28:59 -060015#include <jffs2/load_kernel.h>
Michal Simeka32c3e92022-08-25 14:23:10 +020016#include <lmb.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060017#include <log.h>
Simon Glass401d1c42020-10-30 21:38:53 -060018#include <asm/global_data.h>
Michal Simekfc274a52019-12-19 17:45:15 +010019#include <asm/sections.h>
Michal Simek9755e3d2019-01-21 15:25:02 +010020#include <dm/uclass.h>
21#include <i2c.h>
Michal Simeka29511e2020-04-08 10:51:36 +020022#include <linux/sizes.h>
Michal Simekd61728c2020-08-03 13:01:45 +020023#include <malloc.h>
James Hilliard6c4a7392024-03-31 17:28:59 -060024#include <mtd_node.h>
Michal Simek80fdef12020-03-31 12:39:37 +020025#include "board.h"
Michal Simekd61728c2020-08-03 13:01:45 +020026#include <dm.h>
27#include <i2c_eeprom.h>
28#include <net.h>
Michal Simek05af4832020-10-26 12:26:13 +010029#include <generated/dt.h>
Venkatesh Yadav Abbarapua2700992024-01-17 08:50:13 +053030#include <rng.h>
Michal Simek8174cd22023-01-06 09:38:52 +010031#include <slre.h>
T Karthik Reddy80c0d382021-08-10 06:50:20 -060032#include <soc.h>
Michal Simek52ff1622021-08-11 14:23:54 +020033#include <linux/ctype.h>
Sughosh Ganu741ef862022-04-15 11:29:34 +053034#include <linux/kernel.h>
Michal Simekee5a4b82022-07-21 16:19:17 +020035#include <uuid.h>
Michal Simek9755e3d2019-01-21 15:25:02 +010036
Michal Simekf149b392020-08-03 16:14:23 +020037#include "fru.h"
38
Simon Glass71aa8062023-02-05 15:39:42 -070039#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
Sughosh Ganu741ef862022-04-15 11:29:34 +053040struct efi_fw_image fw_images[] = {
41#if defined(XILINX_BOOT_IMAGE_GUID)
42 {
43 .image_type_id = XILINX_BOOT_IMAGE_GUID,
44 .fw_name = u"XILINX-BOOT",
45 .image_index = 1,
46 },
47#endif
Michal Simek3d3cb282024-02-23 17:18:42 +010048#if defined(XILINX_UBOOT_IMAGE_GUID) && defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME)
Sughosh Ganu741ef862022-04-15 11:29:34 +053049 {
50 .image_type_id = XILINX_UBOOT_IMAGE_GUID,
51 .fw_name = u"XILINX-UBOOT",
52 .image_index = 2,
53 },
54#endif
55};
56
57struct efi_capsule_update_info update_info = {
Masahisa Kojimacccea182023-06-07 14:41:51 +090058 .num_images = ARRAY_SIZE(fw_images),
Sughosh Ganu741ef862022-04-15 11:29:34 +053059 .images = fw_images,
60};
61
Sughosh Ganu741ef862022-04-15 11:29:34 +053062#endif /* EFI_HAVE_CAPSULE_SUPPORT */
63
Michal Simekd61728c2020-08-03 13:01:45 +020064#define EEPROM_HEADER_MAGIC 0xdaaddeed
65#define EEPROM_HDR_MANUFACTURER_LEN 16
66#define EEPROM_HDR_NAME_LEN 16
67#define EEPROM_HDR_REV_LEN 8
68#define EEPROM_HDR_SERIAL_LEN 20
69#define EEPROM_HDR_NO_OF_MAC_ADDR 4
70#define EEPROM_HDR_ETH_ALEN ETH_ALEN
Michal Simekee5a4b82022-07-21 16:19:17 +020071#define EEPROM_HDR_UUID_LEN 16
Michal Simekd61728c2020-08-03 13:01:45 +020072
73struct xilinx_board_description {
74 u32 header;
75 char manufacturer[EEPROM_HDR_MANUFACTURER_LEN + 1];
76 char name[EEPROM_HDR_NAME_LEN + 1];
77 char revision[EEPROM_HDR_REV_LEN + 1];
78 char serial[EEPROM_HDR_SERIAL_LEN + 1];
79 u8 mac_addr[EEPROM_HDR_NO_OF_MAC_ADDR][EEPROM_HDR_ETH_ALEN + 1];
Michal Simekee5a4b82022-07-21 16:19:17 +020080 char uuid[EEPROM_HDR_UUID_LEN + 1];
Michal Simekd61728c2020-08-03 13:01:45 +020081};
82
Michal Simeka03b5942020-08-03 12:57:05 +020083static int highest_id = -1;
Michal Simekd9c93c92021-08-12 12:30:36 +020084static struct xilinx_board_description *board_info;
Michal Simekd61728c2020-08-03 13:01:45 +020085
Michal Simekf149b392020-08-03 16:14:23 +020086#define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr)
Michal Simekd61728c2020-08-03 13:01:45 +020087
88/* Variable which stores pointer to array which stores eeprom content */
89struct xilinx_legacy_format {
90 char board_sn[18]; /* 0x0 */
91 char unused0[14]; /* 0x12 */
Michal Simekb86b1352023-01-24 16:19:26 +010092 char eth_mac[ETH_ALEN]; /* 0x20 */
Michal Simekd61728c2020-08-03 13:01:45 +020093 char unused1[170]; /* 0x26 */
94 char board_name[11]; /* 0xd0 */
95 char unused2[5]; /* 0xdc */
96 char board_revision[3]; /* 0xe0 */
97 char unused3[29]; /* 0xe3 */
98};
99
100static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size)
101{
102 int i;
Venkatesh Yadav Abbarapue1a193b2022-09-26 12:22:42 +0530103 unsigned char byte;
Michal Simekd61728c2020-08-03 13:01:45 +0200104
105 for (i = 0; i < size; i++) {
106 byte = eeprom[i];
107
Michal Simeke6c62532023-01-24 16:19:27 +0100108 /* Remove all non printable chars but ignore MAC address */
109 if ((i < offsetof(struct xilinx_legacy_format, eth_mac) ||
110 i >= offsetof(struct xilinx_legacy_format, unused1)) &&
111 (byte < '!' || byte > '~')) {
Michal Simekd61728c2020-08-03 13:01:45 +0200112 eeprom[i] = 0;
Michal Simeke6c62532023-01-24 16:19:27 +0100113 continue;
114 }
Michal Simekd61728c2020-08-03 13:01:45 +0200115
116 /* Convert strings to lower case */
117 if (byte >= 'A' && byte <= 'Z')
118 eeprom[i] = byte + 'a' - 'A';
119 }
120}
121
122static int xilinx_read_eeprom_legacy(struct udevice *dev, char *name,
123 struct xilinx_board_description *desc)
124{
125 int ret, size;
126 struct xilinx_legacy_format *eeprom_content;
127 bool eth_valid = false;
128
129 size = sizeof(*eeprom_content);
130
131 eeprom_content = calloc(1, size);
132 if (!eeprom_content)
133 return -ENOMEM;
134
135 debug("%s: I2C EEPROM read pass data at %p\n", __func__,
136 eeprom_content);
137
138 ret = dm_i2c_read(dev, 0, (uchar *)eeprom_content, size);
139 if (ret) {
140 debug("%s: I2C EEPROM read failed\n", __func__);
141 free(eeprom_content);
142 return ret;
143 }
144
145 xilinx_eeprom_legacy_cleanup((char *)eeprom_content, size);
146
Michal Simek55631672023-01-24 16:19:28 +0100147 /* Terminating \0 chars are the part of desc fields already */
148 strlcpy(desc->name, eeprom_content->board_name,
149 sizeof(eeprom_content->board_name) + 1);
150 strlcpy(desc->revision, eeprom_content->board_revision,
151 sizeof(eeprom_content->board_revision) + 1);
152 strlcpy(desc->serial, eeprom_content->board_sn,
153 sizeof(eeprom_content->board_sn) + 1);
Michal Simekd61728c2020-08-03 13:01:45 +0200154
155 eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac);
156 if (eth_valid)
Michal Simekd61728c2020-08-03 13:01:45 +0200157 memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN);
158
Michal Simek55631672023-01-24 16:19:28 +0100159 printf("Xilinx I2C Legacy format at %s:\n", name);
160 printf(" Board name:\t%s\n", desc->name);
161 printf(" Board rev:\t%s\n", desc->revision);
162 printf(" Board SN:\t%s\n", desc->serial);
163
164 if (eth_valid)
165 printf(" Ethernet mac:\t%pM\n", desc->mac_addr);
166
Michal Simekd61728c2020-08-03 13:01:45 +0200167 desc->header = EEPROM_HEADER_MAGIC;
168
169 free(eeprom_content);
170
171 return ret;
172}
173
174static bool xilinx_detect_legacy(u8 *buffer)
175{
176 int i;
177 char c;
178
179 for (i = 0; i < XILINX_I2C_DETECTION_BITS; i++) {
180 c = buffer[i];
181
182 if (c < '0' || c > '9')
183 return false;
184 }
185
186 return true;
187}
188
Michal Simekf149b392020-08-03 16:14:23 +0200189static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
190 struct xilinx_board_description *desc)
191{
Michal Simek530560b2021-08-12 11:03:49 +0200192 int i, ret, eeprom_size;
Michal Simekf149b392020-08-03 16:14:23 +0200193 u8 *fru_content;
Ashok Reddy Soma7a036b62022-02-23 15:00:59 +0100194 u8 id = 0;
Michal Simekf149b392020-08-03 16:14:23 +0200195
196 /* FIXME this is shortcut - if eeprom type is wrong it will fail */
197 eeprom_size = i2c_eeprom_size(dev);
198
199 fru_content = calloc(1, eeprom_size);
200 if (!fru_content)
201 return -ENOMEM;
202
203 debug("%s: I2C EEPROM read pass data at %p\n", __func__,
204 fru_content);
205
206 ret = dm_i2c_read(dev, 0, (uchar *)fru_content,
207 eeprom_size);
208 if (ret) {
209 debug("%s: I2C EEPROM read failed\n", __func__);
Michal Simekb2628632021-08-13 09:17:10 +0200210 goto end;
Michal Simekf149b392020-08-03 16:14:23 +0200211 }
212
Michal Simekf149b392020-08-03 16:14:23 +0200213 fru_capture((unsigned long)fru_content);
Simon Glass866ec872023-02-05 15:39:38 -0700214 if (gd->flags & GD_FLG_RELOC || (_DEBUG && IS_ENABLED(CONFIG_DTB_RESELECT))) {
Michal Simek52ff1622021-08-11 14:23:54 +0200215 printf("Xilinx I2C FRU format at %s:\n", name);
216 ret = fru_display(0);
217 if (ret) {
218 printf("FRU format decoding failed.\n");
219 goto end;
220 }
Michal Simekf149b392020-08-03 16:14:23 +0200221 }
222
223 if (desc->header == EEPROM_HEADER_MAGIC) {
224 debug("Information already filled\n");
Michal Simekb2628632021-08-13 09:17:10 +0200225 ret = -EINVAL;
226 goto end;
Michal Simekf149b392020-08-03 16:14:23 +0200227 }
228
229 /* It is clear that FRU was captured and structures were filled */
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200230 strlcpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
Michal Simekf149b392020-08-03 16:14:23 +0200231 sizeof(desc->manufacturer));
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200232 strlcpy(desc->uuid, (char *)fru_data.brd.uuid,
Michal Simekee5a4b82022-07-21 16:19:17 +0200233 sizeof(desc->uuid));
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200234 strlcpy(desc->name, (char *)fru_data.brd.product_name,
Michal Simekf149b392020-08-03 16:14:23 +0200235 sizeof(desc->name));
Michal Simek530560b2021-08-12 11:03:49 +0200236 for (i = 0; i < sizeof(desc->name); i++) {
237 if (desc->name[i] == ' ')
238 desc->name[i] = '\0';
239 }
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200240 strlcpy(desc->revision, (char *)fru_data.brd.rev,
Michal Simekf149b392020-08-03 16:14:23 +0200241 sizeof(desc->revision));
Michal Simek93216272022-06-06 09:31:27 +0200242 for (i = 0; i < sizeof(desc->revision); i++) {
243 if (desc->revision[i] == ' ')
244 desc->revision[i] = '\0';
245 }
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200246 strlcpy(desc->serial, (char *)fru_data.brd.serial_number,
Michal Simekf149b392020-08-03 16:14:23 +0200247 sizeof(desc->serial));
Ashok Reddy Soma7a036b62022-02-23 15:00:59 +0100248
249 while (id < EEPROM_HDR_NO_OF_MAC_ADDR) {
250 if (is_valid_ethaddr((const u8 *)fru_data.mac.macid[id]))
251 memcpy(&desc->mac_addr[id],
252 (char *)fru_data.mac.macid[id], ETH_ALEN);
253 id++;
254 }
255
Michal Simekf149b392020-08-03 16:14:23 +0200256 desc->header = EEPROM_HEADER_MAGIC;
257
Michal Simekb2628632021-08-13 09:17:10 +0200258end:
259 free(fru_content);
260 return ret;
Michal Simekf149b392020-08-03 16:14:23 +0200261}
262
263static bool xilinx_detect_fru(u8 *buffer)
264{
265 u8 checksum = 0;
266 int i;
267
268 checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr));
269 if (checksum) {
270 debug("%s Common header CRC FAIL\n", __func__);
271 return false;
272 }
273
274 bool all_zeros = true;
275 /* Checksum over all zeros is also zero that's why detect this case */
276 for (i = 0; i < sizeof(struct fru_common_hdr); i++) {
277 if (buffer[i] != 0)
278 all_zeros = false;
279 }
280
281 if (all_zeros)
282 return false;
283
284 debug("%s Common header CRC PASS\n", __func__);
285 return true;
286}
287
Michal Simekd61728c2020-08-03 13:01:45 +0200288static int xilinx_read_eeprom_single(char *name,
289 struct xilinx_board_description *desc)
290{
291 int ret;
292 struct udevice *dev;
293 ofnode eeprom;
294 u8 buffer[XILINX_I2C_DETECTION_BITS];
295
296 eeprom = ofnode_get_aliases_node(name);
297 if (!ofnode_valid(eeprom))
298 return -ENODEV;
299
300 ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
301 if (ret)
302 return ret;
303
304 ret = dm_i2c_read(dev, 0, buffer, sizeof(buffer));
305 if (ret) {
306 debug("%s: I2C EEPROM read failed\n", __func__);
307 return ret;
308 }
309
310 debug("%s: i2c memory detected: %s\n", __func__, name);
311
Simon Glassf8daba42023-02-05 15:36:31 -0700312 if (IS_ENABLED(CONFIG_CMD_FRU) && xilinx_detect_fru(buffer))
Michal Simekf149b392020-08-03 16:14:23 +0200313 return xilinx_read_eeprom_fru(dev, name, desc);
314
Michal Simekd61728c2020-08-03 13:01:45 +0200315 if (xilinx_detect_legacy(buffer))
316 return xilinx_read_eeprom_legacy(dev, name, desc);
317
318 return -ENODEV;
319}
320
321__maybe_unused int xilinx_read_eeprom(void)
322{
Michal Simekd9c93c92021-08-12 12:30:36 +0200323 int id;
Michal Simekd61728c2020-08-03 13:01:45 +0200324 char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
Michal Simeka03b5942020-08-03 12:57:05 +0200325 struct xilinx_board_description *desc;
Michal Simekd61728c2020-08-03 13:01:45 +0200326
327 highest_id = dev_read_alias_highest_id("nvmem");
328 /* No nvmem aliases present */
329 if (highest_id < 0)
330 return -EINVAL;
331
Michal Simekd9c93c92021-08-12 12:30:36 +0200332 board_info = calloc(1, sizeof(*desc) * (highest_id + 1));
Michal Simekd61728c2020-08-03 13:01:45 +0200333 if (!board_info)
334 return -ENOMEM;
335
336 debug("%s: Highest ID %d, board_info %p\n", __func__,
337 highest_id, board_info);
338
339 for (id = 0; id <= highest_id; id++) {
340 snprintf(name_buf, sizeof(name_buf), "nvmem%d", id);
341
Michal Simeka03b5942020-08-03 12:57:05 +0200342 /* Alloc structure */
Michal Simekd9c93c92021-08-12 12:30:36 +0200343 desc = &board_info[id];
Michal Simeka03b5942020-08-03 12:57:05 +0200344
Michal Simekd61728c2020-08-03 13:01:45 +0200345 /* Ignoring return value for supporting multiple chips */
Michal Simekd9c93c92021-08-12 12:30:36 +0200346 xilinx_read_eeprom_single(name_buf, desc);
Michal Simekd61728c2020-08-03 13:01:45 +0200347 }
348
Michal Simeka03b5942020-08-03 12:57:05 +0200349 /*
350 * Consider to clean board_info structure when board/cards are not
351 * detected.
352 */
Michal Simekd61728c2020-08-03 13:01:45 +0200353
354 return 0;
355}
356
Michal Simekf0631002022-02-17 14:28:38 +0100357#if defined(CONFIG_OF_BOARD)
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300358void *board_fdt_blob_setup(int *err)
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100359{
Michal Simeke2572b52020-09-04 16:21:47 +0200360 void *fdt_blob;
Michal Simek453bb772020-03-19 10:23:56 +0100361
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300362 *err = 0;
Michal Simek451b2ea2024-02-14 12:52:33 +0100363
364 if (IS_ENABLED(CONFIG_TARGET_XILINX_MBV)) {
365 fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
366
367 if (fdt_magic(fdt_blob) == FDT_MAGIC)
368 return fdt_blob;
369 }
370
Michal Simeka672b982021-01-04 11:07:28 +0100371 if (!IS_ENABLED(CONFIG_SPL_BUILD) &&
372 !IS_ENABLED(CONFIG_VERSAL_NO_DDR) &&
Michal Simekfc3c6fd2021-02-02 13:33:22 +0100373 !IS_ENABLED(CONFIG_ZYNQMP_NO_DDR)) {
Michal Simek506009f2021-01-04 11:03:36 +0100374 fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100375
Michal Simek506009f2021-01-04 11:03:36 +0100376 if (fdt_magic(fdt_blob) == FDT_MAGIC)
377 return fdt_blob;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100378
Michal Simek506009f2021-01-04 11:03:36 +0100379 debug("DTB is not passed via %p\n", fdt_blob);
380 }
Michal Simekfc274a52019-12-19 17:45:15 +0100381
Michal Simek506009f2021-01-04 11:03:36 +0100382 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
383 /*
384 * FDT is at end of BSS unless it is in a different memory
385 * region
386 */
387 if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
Shiji Yangccea96f2023-08-03 09:47:17 +0800388 fdt_blob = (ulong *)_image_binary_end;
Michal Simek506009f2021-01-04 11:03:36 +0100389 else
Shiji Yangccea96f2023-08-03 09:47:17 +0800390 fdt_blob = (ulong *)__bss_end;
Michal Simek506009f2021-01-04 11:03:36 +0100391 } else {
392 /* FDT is at end of image */
Shiji Yangccea96f2023-08-03 09:47:17 +0800393 fdt_blob = (ulong *)_end;
Michal Simek506009f2021-01-04 11:03:36 +0100394 }
Michal Simekfc274a52019-12-19 17:45:15 +0100395
396 if (fdt_magic(fdt_blob) == FDT_MAGIC)
397 return fdt_blob;
398
399 debug("DTB is also not passed via %p\n", fdt_blob);
400
Michal Simekf0631002022-02-17 14:28:38 +0100401 *err = -EINVAL;
Michal Simekfc274a52019-12-19 17:45:15 +0100402 return NULL;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100403}
404#endif
Michal Simek80fdef12020-03-31 12:39:37 +0200405
Michal Simek7c553ac2020-10-22 11:14:20 +0200406#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simeka03b5942020-08-03 12:57:05 +0200407static int env_set_by_index(const char *name, int index, char *data)
408{
409 char var[32];
410
411 if (!index)
412 sprintf(var, "board_%s", name);
413 else
414 sprintf(var, "card%d_%s", index, name);
415
416 return env_set(var, data);
417}
418
Michal Simek80fdef12020-03-31 12:39:37 +0200419int board_late_init_xilinx(void)
420{
Michal Simekca0f6162020-08-12 12:16:49 +0200421 u32 ret = 0;
Michal Simeka03b5942020-08-03 12:57:05 +0200422 int i, id, macid = 0;
423 struct xilinx_board_description *desc;
Ricardo Salvetie6e3b9d2022-01-20 16:17:30 -0300424 phys_size_t bootm_size = gd->ram_top - gd->ram_base;
Michal Simek0bbc9622023-08-31 09:04:28 +0200425 u64 bootscr_flash_offset, bootscr_flash_size;
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600426
Simon Glass0c22cdc2023-02-05 15:40:14 -0700427 if (!IS_ENABLED(CONFIG_MICROBLAZE)) {
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600428 ulong scriptaddr;
Algapally Santosh Sagar5528f792023-08-31 08:59:06 +0200429 u64 bootscr_address;
430 u64 bootscr_offset;
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600431
Algapally Santosh Sagar5528f792023-08-31 08:59:06 +0200432 /* Fetch bootscr_address/bootscr_offset from DT and update */
433 if (!ofnode_read_bootscript_address(&bootscr_address,
434 &bootscr_offset)) {
435 if (bootscr_offset)
436 ret |= env_set_hex("scriptaddr",
437 gd->ram_base +
438 bootscr_offset);
439 else
440 ret |= env_set_hex("scriptaddr",
441 bootscr_address);
442 } else {
443 /* Update scriptaddr(bootscr offset) from env */
444 scriptaddr = env_get_hex("scriptaddr", 0);
445 ret |= env_set_hex("scriptaddr",
446 gd->ram_base + scriptaddr);
447 }
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600448 }
Michal Simek2570cc62020-08-12 12:17:53 +0200449
Michal Simek0bbc9622023-08-31 09:04:28 +0200450 if (!ofnode_read_bootscript_flash(&bootscr_flash_offset,
451 &bootscr_flash_size)) {
452 ret |= env_set_hex("script_offset_f", bootscr_flash_offset);
453 ret |= env_set_hex("script_size_f", bootscr_flash_size);
454 } else {
455 debug("!!! Please define bootscr-flash-offset via DT !!!\n");
456 ret |= env_set_hex("script_offset_f",
457 CONFIG_BOOT_SCRIPT_OFFSET);
458 }
459
Simon Glass0c22cdc2023-02-05 15:40:14 -0700460 if (IS_ENABLED(CONFIG_ARCH_ZYNQ) || IS_ENABLED(CONFIG_MICROBLAZE))
Michal Simek2570cc62020-08-12 12:17:53 +0200461 bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M));
Michal Simek80fdef12020-03-31 12:39:37 +0200462
Michal Simekca0f6162020-08-12 12:16:49 +0200463 ret |= env_set_addr("bootm_low", (void *)gd->ram_base);
Michal Simek2570cc62020-08-12 12:17:53 +0200464 ret |= env_set_addr("bootm_size", (void *)bootm_size);
Michal Simekca0f6162020-08-12 12:16:49 +0200465
Michal Simeka03b5942020-08-03 12:57:05 +0200466 for (id = 0; id <= highest_id; id++) {
Michal Simekd9c93c92021-08-12 12:30:36 +0200467 desc = &board_info[id];
Michal Simeka03b5942020-08-03 12:57:05 +0200468 if (desc && desc->header == EEPROM_HEADER_MAGIC) {
469 if (desc->manufacturer[0])
470 ret |= env_set_by_index("manufacturer", id,
471 desc->manufacturer);
472 if (desc->name[0])
473 ret |= env_set_by_index("name", id,
474 desc->name);
475 if (desc->revision[0])
476 ret |= env_set_by_index("rev", id,
477 desc->revision);
478 if (desc->serial[0])
479 ret |= env_set_by_index("serial", id,
480 desc->serial);
Michal Simekd61728c2020-08-03 13:01:45 +0200481
Michal Simekee5a4b82022-07-21 16:19:17 +0200482 if (desc->uuid[0]) {
Venkatesh Yadav Abbarapue1a193b2022-09-26 12:22:42 +0530483 unsigned char uuid[UUID_STR_LEN + 1];
484 unsigned char *t = desc->uuid;
Michal Simekee5a4b82022-07-21 16:19:17 +0200485
486 memset(uuid, 0, UUID_STR_LEN + 1);
487
488 sprintf(uuid, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
489 t[0], t[1], t[2], t[3], t[4], t[5],
490 t[6], t[7], t[8], t[9], t[10], t[11],
491 t[12], t[13], t[14], t[15]);
492 ret |= env_set_by_index("uuid", id, uuid);
493 }
494
Michal Simekd61728c2020-08-03 13:01:45 +0200495 if (!CONFIG_IS_ENABLED(NET))
496 continue;
497
Michal Simeka03b5942020-08-03 12:57:05 +0200498 for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
Michal Simeka03b5942020-08-03 12:57:05 +0200499 if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
500 ret |= eth_env_set_enetaddr_by_index("eth",
501 macid++, desc->mac_addr[i]);
502 }
Michal Simekd61728c2020-08-03 13:01:45 +0200503 }
504 }
505
Michal Simekca0f6162020-08-12 12:16:49 +0200506 if (ret)
507 printf("%s: Saving run time variables FAILED\n", __func__);
Michal Simekc8da6512020-07-09 15:57:56 +0200508
Michal Simek80fdef12020-03-31 12:39:37 +0200509 return 0;
510}
Michal Simek7c553ac2020-10-22 11:14:20 +0200511#endif
Michal Simek05af4832020-10-26 12:26:13 +0100512
Michal Simek57f71032021-07-23 09:55:59 +0200513static char *board_name = DEVICE_TREE;
514
Michal Simek05af4832020-10-26 12:26:13 +0100515int __maybe_unused board_fit_config_name_match(const char *name)
516{
Michal Simek57f71032021-07-23 09:55:59 +0200517 debug("%s: Check %s, default %s\n", __func__, name, board_name);
Michal Simek05af4832020-10-26 12:26:13 +0100518
Michal Simek8174cd22023-01-06 09:38:52 +0100519#if !defined(CONFIG_SPL_BUILD)
Simon Glasseca09862023-02-05 15:40:37 -0700520 if (IS_ENABLED(CONFIG_REGEX)) {
Michal Simek8174cd22023-01-06 09:38:52 +0100521 struct slre slre;
522 int ret;
523
524 ret = slre_compile(&slre, name);
525 if (ret) {
526 ret = slre_match(&slre, board_name, strlen(board_name),
527 NULL);
528 debug("%s: name match ret = %d\n", __func__, ret);
529 return !ret;
530 }
531 }
532#endif
533
Michal Simek57f71032021-07-23 09:55:59 +0200534 if (!strcmp(name, board_name))
Michal Simek05af4832020-10-26 12:26:13 +0100535 return 0;
536
537 return -1;
538}
T Karthik Reddy80c0d382021-08-10 06:50:20 -0600539
Simon Glass866ec872023-02-05 15:39:38 -0700540#if IS_ENABLED(CONFIG_DTB_RESELECT)
Michal Simek52ff1622021-08-11 14:23:54 +0200541#define MAX_NAME_LENGTH 50
542
Michal Simek88232532021-07-23 09:59:59 +0200543char * __maybe_unused __weak board_name_decode(void)
544{
Michal Simek52ff1622021-08-11 14:23:54 +0200545 char *board_local_name;
546 struct xilinx_board_description *desc;
547 int i, id;
548
549 board_local_name = calloc(1, MAX_NAME_LENGTH);
550 if (!board_info)
551 return NULL;
552
553 for (id = 0; id <= highest_id; id++) {
554 desc = &board_info[id];
555
556 /* No board description */
557 if (!desc)
558 goto error;
559
560 /* Board is not detected */
561 if (desc->header != EEPROM_HEADER_MAGIC)
562 continue;
563
564 /* The first string should be soc name */
565 if (!id)
566 strcat(board_local_name, CONFIG_SYS_BOARD);
567
568 /*
569 * For two purpose here:
570 * soc_name- eg: zynqmp-
571 * and between base board and CC eg: ..revA-sck...
572 */
573 strcat(board_local_name, "-");
574
575 if (desc->name[0]) {
576 /* For DT composition name needs to be lowercase */
577 for (i = 0; i < sizeof(desc->name); i++)
578 desc->name[i] = tolower(desc->name[i]);
579
580 strcat(board_local_name, desc->name);
581 }
582 if (desc->revision[0]) {
583 strcat(board_local_name, "-rev");
584
585 /* And revision needs to be uppercase */
586 for (i = 0; i < sizeof(desc->revision); i++)
587 desc->revision[i] = toupper(desc->revision[i]);
588
589 strcat(board_local_name, desc->revision);
590 }
591 }
592
593 /*
594 * Longer strings will end up with buffer overflow and potential
595 * attacks that's why check it
596 */
597 if (strlen(board_local_name) >= MAX_NAME_LENGTH)
598 panic("Board name can't be determined\n");
599
600 if (strlen(board_local_name))
601 return board_local_name;
602
603error:
604 free(board_local_name);
Michal Simek88232532021-07-23 09:59:59 +0200605 return NULL;
606}
607
608bool __maybe_unused __weak board_detection(void)
609{
Michal Simek52ff1622021-08-11 14:23:54 +0200610 if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) {
611 int ret;
612
613 ret = xilinx_read_eeprom();
614 return !ret ? true : false;
615 }
616
Michal Simek88232532021-07-23 09:59:59 +0200617 return false;
618}
619
Michal Simek39d3c3c2022-09-06 12:40:41 +0200620bool __maybe_unused __weak soc_detection(void)
621{
622 return false;
623}
624
625char * __maybe_unused __weak soc_name_decode(void)
626{
627 return NULL;
628}
629
Michal Simek88232532021-07-23 09:59:59 +0200630int embedded_dtb_select(void)
631{
Michal Simek39d3c3c2022-09-06 12:40:41 +0200632 if (soc_detection()) {
633 char *soc_local_name;
634
635 soc_local_name = soc_name_decode();
636 if (soc_local_name) {
637 board_name = soc_local_name;
638 printf("Detected SOC name: %s\n", board_name);
639
640 /* Time to change DTB on fly */
641 /* Both ways should work here */
642 /* fdtdec_resetup(&rescan); */
643 return fdtdec_setup();
644 }
645 }
646
Michal Simek88232532021-07-23 09:59:59 +0200647 if (board_detection()) {
648 char *board_local_name;
649
650 board_local_name = board_name_decode();
651 if (board_local_name) {
652 board_name = board_local_name;
Michal Simek52ff1622021-08-11 14:23:54 +0200653 printf("Detected name: %s\n", board_name);
Michal Simek88232532021-07-23 09:59:59 +0200654
655 /* Time to change DTB on fly */
656 /* Both ways should work here */
657 /* fdtdec_resetup(&rescan); */
658 fdtdec_setup();
659 }
660 }
661 return 0;
662}
663#endif
Michal Simeka32c3e92022-08-25 14:23:10 +0200664
665#if defined(CONFIG_LMB)
Michal Simek7576ab22023-11-06 12:56:47 +0100666
667#ifndef MMU_SECTION_SIZE
668#define MMU_SECTION_SIZE (1 * 1024 * 1024)
669#endif
670
Heinrich Schuchardtd768dd82023-08-12 20:16:58 +0200671phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Michal Simeka32c3e92022-08-25 14:23:10 +0200672{
673 phys_size_t size;
674 phys_addr_t reg;
675 struct lmb lmb;
676
677 if (!total_size)
678 return gd->ram_top;
679
680 if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
681 panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
682
683 /* found enough not-reserved memory to relocated U-Boot */
684 lmb_init(&lmb);
685 lmb_add(&lmb, gd->ram_base, gd->ram_size);
686 boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
687 size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
688 reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
689
690 if (!reg)
691 reg = gd->ram_top - size;
692
693 return reg + size;
694}
695#endif
Venkatesh Yadav Abbarapua2700992024-01-17 08:50:13 +0530696
697#ifdef CONFIG_OF_BOARD_SETUP
698#define MAX_RAND_SIZE 8
699int ft_board_setup(void *blob, struct bd_info *bd)
700{
701 size_t n = MAX_RAND_SIZE;
702 struct udevice *dev;
703 u8 buf[MAX_RAND_SIZE];
704 int nodeoffset, ret;
705
James Hilliard6c4a7392024-03-31 17:28:59 -0600706 static const struct node_info nodes[] = {
707 { "arm,pl353-nand-r2p1", MTD_DEV_TYPE_NAND, },
708 };
709
710 if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
711 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
712
Venkatesh Yadav Abbarapua2700992024-01-17 08:50:13 +0530713 if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
714 debug("No RNG device\n");
715 return 0;
716 }
717
718 if (dm_rng_read(dev, buf, n)) {
719 debug("Reading RNG failed\n");
720 return 0;
721 }
722
723 if (!blob) {
724 debug("No FDT memory address configured. Please configure\n"
725 "the FDT address via \"fdt addr <address>\" command.\n"
726 "Aborting!\n");
727 return 0;
728 }
729
730 ret = fdt_check_header(blob);
731 if (ret < 0) {
732 debug("fdt_chosen: %s\n", fdt_strerror(ret));
733 return ret;
734 }
735
736 nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
737 if (nodeoffset < 0) {
738 debug("Reading chosen node failed\n");
739 return nodeoffset;
740 }
741
742 ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
743 if (ret < 0) {
744 debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
745 return ret;
746 }
747
748 return 0;
749}
750#endif