blob: b47d2d23f913dbff20250e762947573c9ca20873 [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
Petr Zejdlf03f9622024-04-04 13:44:22 +0200108 /* Ignore MAC address */
109 if (i >= offsetof(struct xilinx_legacy_format, eth_mac) &&
110 i < offsetof(struct xilinx_legacy_format, unused1)) {
111 continue;
112 }
113
114 /* Remove all non printable chars */
115 if (byte < '!' || byte > '~') {
Michal Simekd61728c2020-08-03 13:01:45 +0200116 eeprom[i] = 0;
Michal Simeke6c62532023-01-24 16:19:27 +0100117 continue;
118 }
Michal Simekd61728c2020-08-03 13:01:45 +0200119
120 /* Convert strings to lower case */
121 if (byte >= 'A' && byte <= 'Z')
122 eeprom[i] = byte + 'a' - 'A';
123 }
124}
125
126static int xilinx_read_eeprom_legacy(struct udevice *dev, char *name,
127 struct xilinx_board_description *desc)
128{
129 int ret, size;
130 struct xilinx_legacy_format *eeprom_content;
131 bool eth_valid = false;
132
133 size = sizeof(*eeprom_content);
134
135 eeprom_content = calloc(1, size);
136 if (!eeprom_content)
137 return -ENOMEM;
138
139 debug("%s: I2C EEPROM read pass data at %p\n", __func__,
140 eeprom_content);
141
142 ret = dm_i2c_read(dev, 0, (uchar *)eeprom_content, size);
143 if (ret) {
144 debug("%s: I2C EEPROM read failed\n", __func__);
145 free(eeprom_content);
146 return ret;
147 }
148
149 xilinx_eeprom_legacy_cleanup((char *)eeprom_content, size);
150
Michal Simek55631672023-01-24 16:19:28 +0100151 /* Terminating \0 chars are the part of desc fields already */
152 strlcpy(desc->name, eeprom_content->board_name,
153 sizeof(eeprom_content->board_name) + 1);
154 strlcpy(desc->revision, eeprom_content->board_revision,
155 sizeof(eeprom_content->board_revision) + 1);
156 strlcpy(desc->serial, eeprom_content->board_sn,
157 sizeof(eeprom_content->board_sn) + 1);
Michal Simekd61728c2020-08-03 13:01:45 +0200158
159 eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac);
160 if (eth_valid)
Michal Simekd61728c2020-08-03 13:01:45 +0200161 memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN);
162
Michal Simek55631672023-01-24 16:19:28 +0100163 printf("Xilinx I2C Legacy format at %s:\n", name);
164 printf(" Board name:\t%s\n", desc->name);
165 printf(" Board rev:\t%s\n", desc->revision);
166 printf(" Board SN:\t%s\n", desc->serial);
167
168 if (eth_valid)
169 printf(" Ethernet mac:\t%pM\n", desc->mac_addr);
170
Michal Simekd61728c2020-08-03 13:01:45 +0200171 desc->header = EEPROM_HEADER_MAGIC;
172
173 free(eeprom_content);
174
175 return ret;
176}
177
178static bool xilinx_detect_legacy(u8 *buffer)
179{
180 int i;
181 char c;
182
183 for (i = 0; i < XILINX_I2C_DETECTION_BITS; i++) {
184 c = buffer[i];
185
186 if (c < '0' || c > '9')
187 return false;
188 }
189
190 return true;
191}
192
Michal Simekf149b392020-08-03 16:14:23 +0200193static int xilinx_read_eeprom_fru(struct udevice *dev, char *name,
194 struct xilinx_board_description *desc)
195{
Michal Simek530560b2021-08-12 11:03:49 +0200196 int i, ret, eeprom_size;
Michal Simekf149b392020-08-03 16:14:23 +0200197 u8 *fru_content;
Ashok Reddy Soma7a036b62022-02-23 15:00:59 +0100198 u8 id = 0;
Michal Simekf149b392020-08-03 16:14:23 +0200199
200 /* FIXME this is shortcut - if eeprom type is wrong it will fail */
201 eeprom_size = i2c_eeprom_size(dev);
202
203 fru_content = calloc(1, eeprom_size);
204 if (!fru_content)
205 return -ENOMEM;
206
207 debug("%s: I2C EEPROM read pass data at %p\n", __func__,
208 fru_content);
209
210 ret = dm_i2c_read(dev, 0, (uchar *)fru_content,
211 eeprom_size);
212 if (ret) {
213 debug("%s: I2C EEPROM read failed\n", __func__);
Michal Simekb2628632021-08-13 09:17:10 +0200214 goto end;
Michal Simekf149b392020-08-03 16:14:23 +0200215 }
216
Michal Simekf149b392020-08-03 16:14:23 +0200217 fru_capture((unsigned long)fru_content);
Simon Glass866ec872023-02-05 15:39:38 -0700218 if (gd->flags & GD_FLG_RELOC || (_DEBUG && IS_ENABLED(CONFIG_DTB_RESELECT))) {
Michal Simek52ff1622021-08-11 14:23:54 +0200219 printf("Xilinx I2C FRU format at %s:\n", name);
220 ret = fru_display(0);
221 if (ret) {
222 printf("FRU format decoding failed.\n");
223 goto end;
224 }
Michal Simekf149b392020-08-03 16:14:23 +0200225 }
226
227 if (desc->header == EEPROM_HEADER_MAGIC) {
228 debug("Information already filled\n");
Michal Simekb2628632021-08-13 09:17:10 +0200229 ret = -EINVAL;
230 goto end;
Michal Simekf149b392020-08-03 16:14:23 +0200231 }
232
233 /* It is clear that FRU was captured and structures were filled */
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200234 strlcpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name,
Michal Simekf149b392020-08-03 16:14:23 +0200235 sizeof(desc->manufacturer));
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200236 strlcpy(desc->uuid, (char *)fru_data.brd.uuid,
Michal Simekee5a4b82022-07-21 16:19:17 +0200237 sizeof(desc->uuid));
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200238 strlcpy(desc->name, (char *)fru_data.brd.product_name,
Michal Simekf149b392020-08-03 16:14:23 +0200239 sizeof(desc->name));
Michal Simek530560b2021-08-12 11:03:49 +0200240 for (i = 0; i < sizeof(desc->name); i++) {
241 if (desc->name[i] == ' ')
242 desc->name[i] = '\0';
243 }
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200244 strlcpy(desc->revision, (char *)fru_data.brd.rev,
Michal Simekf149b392020-08-03 16:14:23 +0200245 sizeof(desc->revision));
Michal Simek93216272022-06-06 09:31:27 +0200246 for (i = 0; i < sizeof(desc->revision); i++) {
247 if (desc->revision[i] == ' ')
248 desc->revision[i] = '\0';
249 }
Michal Simek4a1bfcd2022-07-21 16:19:18 +0200250 strlcpy(desc->serial, (char *)fru_data.brd.serial_number,
Michal Simekf149b392020-08-03 16:14:23 +0200251 sizeof(desc->serial));
Ashok Reddy Soma7a036b62022-02-23 15:00:59 +0100252
253 while (id < EEPROM_HDR_NO_OF_MAC_ADDR) {
254 if (is_valid_ethaddr((const u8 *)fru_data.mac.macid[id]))
255 memcpy(&desc->mac_addr[id],
256 (char *)fru_data.mac.macid[id], ETH_ALEN);
257 id++;
258 }
259
Michal Simekf149b392020-08-03 16:14:23 +0200260 desc->header = EEPROM_HEADER_MAGIC;
261
Michal Simekb2628632021-08-13 09:17:10 +0200262end:
263 free(fru_content);
264 return ret;
Michal Simekf149b392020-08-03 16:14:23 +0200265}
266
267static bool xilinx_detect_fru(u8 *buffer)
268{
269 u8 checksum = 0;
270 int i;
271
272 checksum = fru_checksum((u8 *)buffer, sizeof(struct fru_common_hdr));
273 if (checksum) {
274 debug("%s Common header CRC FAIL\n", __func__);
275 return false;
276 }
277
278 bool all_zeros = true;
279 /* Checksum over all zeros is also zero that's why detect this case */
280 for (i = 0; i < sizeof(struct fru_common_hdr); i++) {
281 if (buffer[i] != 0)
282 all_zeros = false;
283 }
284
285 if (all_zeros)
286 return false;
287
288 debug("%s Common header CRC PASS\n", __func__);
289 return true;
290}
291
Michal Simekd61728c2020-08-03 13:01:45 +0200292static int xilinx_read_eeprom_single(char *name,
293 struct xilinx_board_description *desc)
294{
295 int ret;
296 struct udevice *dev;
297 ofnode eeprom;
298 u8 buffer[XILINX_I2C_DETECTION_BITS];
299
300 eeprom = ofnode_get_aliases_node(name);
301 if (!ofnode_valid(eeprom))
302 return -ENODEV;
303
304 ret = uclass_get_device_by_ofnode(UCLASS_I2C_EEPROM, eeprom, &dev);
305 if (ret)
306 return ret;
307
308 ret = dm_i2c_read(dev, 0, buffer, sizeof(buffer));
309 if (ret) {
310 debug("%s: I2C EEPROM read failed\n", __func__);
311 return ret;
312 }
313
314 debug("%s: i2c memory detected: %s\n", __func__, name);
315
Simon Glassf8daba42023-02-05 15:36:31 -0700316 if (IS_ENABLED(CONFIG_CMD_FRU) && xilinx_detect_fru(buffer))
Michal Simekf149b392020-08-03 16:14:23 +0200317 return xilinx_read_eeprom_fru(dev, name, desc);
318
Michal Simekd61728c2020-08-03 13:01:45 +0200319 if (xilinx_detect_legacy(buffer))
320 return xilinx_read_eeprom_legacy(dev, name, desc);
321
322 return -ENODEV;
323}
324
325__maybe_unused int xilinx_read_eeprom(void)
326{
Michal Simekd9c93c92021-08-12 12:30:36 +0200327 int id;
Michal Simekd61728c2020-08-03 13:01:45 +0200328 char name_buf[8]; /* 8 bytes should be enough for nvmem+number */
Michal Simeka03b5942020-08-03 12:57:05 +0200329 struct xilinx_board_description *desc;
Michal Simekd61728c2020-08-03 13:01:45 +0200330
331 highest_id = dev_read_alias_highest_id("nvmem");
332 /* No nvmem aliases present */
333 if (highest_id < 0)
334 return -EINVAL;
335
Michal Simekd9c93c92021-08-12 12:30:36 +0200336 board_info = calloc(1, sizeof(*desc) * (highest_id + 1));
Michal Simekd61728c2020-08-03 13:01:45 +0200337 if (!board_info)
338 return -ENOMEM;
339
340 debug("%s: Highest ID %d, board_info %p\n", __func__,
341 highest_id, board_info);
342
343 for (id = 0; id <= highest_id; id++) {
344 snprintf(name_buf, sizeof(name_buf), "nvmem%d", id);
345
Michal Simeka03b5942020-08-03 12:57:05 +0200346 /* Alloc structure */
Michal Simekd9c93c92021-08-12 12:30:36 +0200347 desc = &board_info[id];
Michal Simeka03b5942020-08-03 12:57:05 +0200348
Michal Simekd61728c2020-08-03 13:01:45 +0200349 /* Ignoring return value for supporting multiple chips */
Michal Simekd9c93c92021-08-12 12:30:36 +0200350 xilinx_read_eeprom_single(name_buf, desc);
Michal Simekd61728c2020-08-03 13:01:45 +0200351 }
352
Michal Simeka03b5942020-08-03 12:57:05 +0200353 /*
354 * Consider to clean board_info structure when board/cards are not
355 * detected.
356 */
Michal Simekd61728c2020-08-03 13:01:45 +0200357
358 return 0;
359}
360
Michal Simekf0631002022-02-17 14:28:38 +0100361#if defined(CONFIG_OF_BOARD)
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300362void *board_fdt_blob_setup(int *err)
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100363{
Michal Simeke2572b52020-09-04 16:21:47 +0200364 void *fdt_blob;
Michal Simek453bb772020-03-19 10:23:56 +0100365
Ilias Apalodimase7fb7892021-10-26 09:12:33 +0300366 *err = 0;
Michal Simek451b2ea2024-02-14 12:52:33 +0100367
368 if (IS_ENABLED(CONFIG_TARGET_XILINX_MBV)) {
369 fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
370
371 if (fdt_magic(fdt_blob) == FDT_MAGIC)
372 return fdt_blob;
373 }
374
Michal Simeka672b982021-01-04 11:07:28 +0100375 if (!IS_ENABLED(CONFIG_SPL_BUILD) &&
376 !IS_ENABLED(CONFIG_VERSAL_NO_DDR) &&
Michal Simekfc3c6fd2021-02-02 13:33:22 +0100377 !IS_ENABLED(CONFIG_ZYNQMP_NO_DDR)) {
Michal Simek506009f2021-01-04 11:03:36 +0100378 fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100379
Michal Simek506009f2021-01-04 11:03:36 +0100380 if (fdt_magic(fdt_blob) == FDT_MAGIC)
381 return fdt_blob;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100382
Michal Simek506009f2021-01-04 11:03:36 +0100383 debug("DTB is not passed via %p\n", fdt_blob);
384 }
Michal Simekfc274a52019-12-19 17:45:15 +0100385
Michal Simek506009f2021-01-04 11:03:36 +0100386 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
387 /*
388 * FDT is at end of BSS unless it is in a different memory
389 * region
390 */
391 if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
Shiji Yangccea96f2023-08-03 09:47:17 +0800392 fdt_blob = (ulong *)_image_binary_end;
Michal Simek506009f2021-01-04 11:03:36 +0100393 else
Shiji Yangccea96f2023-08-03 09:47:17 +0800394 fdt_blob = (ulong *)__bss_end;
Michal Simek506009f2021-01-04 11:03:36 +0100395 } else {
396 /* FDT is at end of image */
Shiji Yangccea96f2023-08-03 09:47:17 +0800397 fdt_blob = (ulong *)_end;
Michal Simek506009f2021-01-04 11:03:36 +0100398 }
Michal Simekfc274a52019-12-19 17:45:15 +0100399
400 if (fdt_magic(fdt_blob) == FDT_MAGIC)
401 return fdt_blob;
402
403 debug("DTB is also not passed via %p\n", fdt_blob);
404
Michal Simekf0631002022-02-17 14:28:38 +0100405 *err = -EINVAL;
Michal Simekfc274a52019-12-19 17:45:15 +0100406 return NULL;
Ibai Erkiagafec657b2019-10-02 15:57:36 +0100407}
408#endif
Michal Simek80fdef12020-03-31 12:39:37 +0200409
Michal Simek7c553ac2020-10-22 11:14:20 +0200410#if defined(CONFIG_BOARD_LATE_INIT)
Michal Simeka03b5942020-08-03 12:57:05 +0200411static int env_set_by_index(const char *name, int index, char *data)
412{
413 char var[32];
414
415 if (!index)
416 sprintf(var, "board_%s", name);
417 else
418 sprintf(var, "card%d_%s", index, name);
419
420 return env_set(var, data);
421}
422
Michal Simek80fdef12020-03-31 12:39:37 +0200423int board_late_init_xilinx(void)
424{
Michal Simekca0f6162020-08-12 12:16:49 +0200425 u32 ret = 0;
Michal Simeka03b5942020-08-03 12:57:05 +0200426 int i, id, macid = 0;
427 struct xilinx_board_description *desc;
Ricardo Salvetie6e3b9d2022-01-20 16:17:30 -0300428 phys_size_t bootm_size = gd->ram_top - gd->ram_base;
Michal Simek0bbc9622023-08-31 09:04:28 +0200429 u64 bootscr_flash_offset, bootscr_flash_size;
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600430
Simon Glass0c22cdc2023-02-05 15:40:14 -0700431 if (!IS_ENABLED(CONFIG_MICROBLAZE)) {
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600432 ulong scriptaddr;
Algapally Santosh Sagar5528f792023-08-31 08:59:06 +0200433 u64 bootscr_address;
434 u64 bootscr_offset;
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600435
Algapally Santosh Sagar5528f792023-08-31 08:59:06 +0200436 /* Fetch bootscr_address/bootscr_offset from DT and update */
437 if (!ofnode_read_bootscript_address(&bootscr_address,
438 &bootscr_offset)) {
439 if (bootscr_offset)
440 ret |= env_set_hex("scriptaddr",
441 gd->ram_base +
442 bootscr_offset);
443 else
444 ret |= env_set_hex("scriptaddr",
445 bootscr_address);
446 } else {
447 /* Update scriptaddr(bootscr offset) from env */
448 scriptaddr = env_get_hex("scriptaddr", 0);
449 ret |= env_set_hex("scriptaddr",
450 gd->ram_base + scriptaddr);
451 }
T Karthik Reddyd388ced2020-04-01 06:01:21 -0600452 }
Michal Simek2570cc62020-08-12 12:17:53 +0200453
Michal Simek0bbc9622023-08-31 09:04:28 +0200454 if (!ofnode_read_bootscript_flash(&bootscr_flash_offset,
455 &bootscr_flash_size)) {
456 ret |= env_set_hex("script_offset_f", bootscr_flash_offset);
457 ret |= env_set_hex("script_size_f", bootscr_flash_size);
458 } else {
459 debug("!!! Please define bootscr-flash-offset via DT !!!\n");
460 ret |= env_set_hex("script_offset_f",
461 CONFIG_BOOT_SCRIPT_OFFSET);
462 }
463
Simon Glass0c22cdc2023-02-05 15:40:14 -0700464 if (IS_ENABLED(CONFIG_ARCH_ZYNQ) || IS_ENABLED(CONFIG_MICROBLAZE))
Michal Simek2570cc62020-08-12 12:17:53 +0200465 bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M));
Michal Simek80fdef12020-03-31 12:39:37 +0200466
Michal Simekca0f6162020-08-12 12:16:49 +0200467 ret |= env_set_addr("bootm_low", (void *)gd->ram_base);
Michal Simek2570cc62020-08-12 12:17:53 +0200468 ret |= env_set_addr("bootm_size", (void *)bootm_size);
Michal Simekca0f6162020-08-12 12:16:49 +0200469
Michal Simeka03b5942020-08-03 12:57:05 +0200470 for (id = 0; id <= highest_id; id++) {
Michal Simekd9c93c92021-08-12 12:30:36 +0200471 desc = &board_info[id];
Michal Simeka03b5942020-08-03 12:57:05 +0200472 if (desc && desc->header == EEPROM_HEADER_MAGIC) {
473 if (desc->manufacturer[0])
474 ret |= env_set_by_index("manufacturer", id,
475 desc->manufacturer);
476 if (desc->name[0])
477 ret |= env_set_by_index("name", id,
478 desc->name);
479 if (desc->revision[0])
480 ret |= env_set_by_index("rev", id,
481 desc->revision);
482 if (desc->serial[0])
483 ret |= env_set_by_index("serial", id,
484 desc->serial);
Michal Simekd61728c2020-08-03 13:01:45 +0200485
Michal Simekee5a4b82022-07-21 16:19:17 +0200486 if (desc->uuid[0]) {
Venkatesh Yadav Abbarapue1a193b2022-09-26 12:22:42 +0530487 unsigned char uuid[UUID_STR_LEN + 1];
488 unsigned char *t = desc->uuid;
Michal Simekee5a4b82022-07-21 16:19:17 +0200489
490 memset(uuid, 0, UUID_STR_LEN + 1);
491
492 sprintf(uuid, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
493 t[0], t[1], t[2], t[3], t[4], t[5],
494 t[6], t[7], t[8], t[9], t[10], t[11],
495 t[12], t[13], t[14], t[15]);
496 ret |= env_set_by_index("uuid", id, uuid);
497 }
498
Michal Simekd61728c2020-08-03 13:01:45 +0200499 if (!CONFIG_IS_ENABLED(NET))
500 continue;
501
Michal Simeka03b5942020-08-03 12:57:05 +0200502 for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) {
Michal Simeka03b5942020-08-03 12:57:05 +0200503 if (is_valid_ethaddr((const u8 *)desc->mac_addr[i]))
504 ret |= eth_env_set_enetaddr_by_index("eth",
505 macid++, desc->mac_addr[i]);
506 }
Michal Simekd61728c2020-08-03 13:01:45 +0200507 }
508 }
509
Michal Simekca0f6162020-08-12 12:16:49 +0200510 if (ret)
511 printf("%s: Saving run time variables FAILED\n", __func__);
Michal Simekc8da6512020-07-09 15:57:56 +0200512
Michal Simek80fdef12020-03-31 12:39:37 +0200513 return 0;
514}
Michal Simek7c553ac2020-10-22 11:14:20 +0200515#endif
Michal Simek05af4832020-10-26 12:26:13 +0100516
Michal Simek57f71032021-07-23 09:55:59 +0200517static char *board_name = DEVICE_TREE;
518
Michal Simek05af4832020-10-26 12:26:13 +0100519int __maybe_unused board_fit_config_name_match(const char *name)
520{
Michal Simek57f71032021-07-23 09:55:59 +0200521 debug("%s: Check %s, default %s\n", __func__, name, board_name);
Michal Simek05af4832020-10-26 12:26:13 +0100522
Michal Simek8174cd22023-01-06 09:38:52 +0100523#if !defined(CONFIG_SPL_BUILD)
Simon Glasseca09862023-02-05 15:40:37 -0700524 if (IS_ENABLED(CONFIG_REGEX)) {
Michal Simek8174cd22023-01-06 09:38:52 +0100525 struct slre slre;
526 int ret;
527
528 ret = slre_compile(&slre, name);
529 if (ret) {
530 ret = slre_match(&slre, board_name, strlen(board_name),
531 NULL);
532 debug("%s: name match ret = %d\n", __func__, ret);
533 return !ret;
534 }
535 }
536#endif
537
Michal Simek57f71032021-07-23 09:55:59 +0200538 if (!strcmp(name, board_name))
Michal Simek05af4832020-10-26 12:26:13 +0100539 return 0;
540
541 return -1;
542}
T Karthik Reddy80c0d382021-08-10 06:50:20 -0600543
Simon Glass866ec872023-02-05 15:39:38 -0700544#if IS_ENABLED(CONFIG_DTB_RESELECT)
Michal Simek52ff1622021-08-11 14:23:54 +0200545#define MAX_NAME_LENGTH 50
546
Michal Simek88232532021-07-23 09:59:59 +0200547char * __maybe_unused __weak board_name_decode(void)
548{
Michal Simek52ff1622021-08-11 14:23:54 +0200549 char *board_local_name;
550 struct xilinx_board_description *desc;
551 int i, id;
552
553 board_local_name = calloc(1, MAX_NAME_LENGTH);
554 if (!board_info)
555 return NULL;
556
557 for (id = 0; id <= highest_id; id++) {
558 desc = &board_info[id];
559
560 /* No board description */
561 if (!desc)
562 goto error;
563
564 /* Board is not detected */
565 if (desc->header != EEPROM_HEADER_MAGIC)
566 continue;
567
568 /* The first string should be soc name */
569 if (!id)
570 strcat(board_local_name, CONFIG_SYS_BOARD);
571
572 /*
573 * For two purpose here:
574 * soc_name- eg: zynqmp-
575 * and between base board and CC eg: ..revA-sck...
576 */
577 strcat(board_local_name, "-");
578
579 if (desc->name[0]) {
580 /* For DT composition name needs to be lowercase */
581 for (i = 0; i < sizeof(desc->name); i++)
582 desc->name[i] = tolower(desc->name[i]);
583
584 strcat(board_local_name, desc->name);
585 }
586 if (desc->revision[0]) {
587 strcat(board_local_name, "-rev");
588
589 /* And revision needs to be uppercase */
590 for (i = 0; i < sizeof(desc->revision); i++)
591 desc->revision[i] = toupper(desc->revision[i]);
592
593 strcat(board_local_name, desc->revision);
594 }
595 }
596
597 /*
598 * Longer strings will end up with buffer overflow and potential
599 * attacks that's why check it
600 */
601 if (strlen(board_local_name) >= MAX_NAME_LENGTH)
602 panic("Board name can't be determined\n");
603
604 if (strlen(board_local_name))
605 return board_local_name;
606
607error:
608 free(board_local_name);
Michal Simek88232532021-07-23 09:59:59 +0200609 return NULL;
610}
611
612bool __maybe_unused __weak board_detection(void)
613{
Michal Simek52ff1622021-08-11 14:23:54 +0200614 if (CONFIG_IS_ENABLED(DM_I2C) && CONFIG_IS_ENABLED(I2C_EEPROM)) {
615 int ret;
616
617 ret = xilinx_read_eeprom();
618 return !ret ? true : false;
619 }
620
Michal Simek88232532021-07-23 09:59:59 +0200621 return false;
622}
623
Michal Simek39d3c3c2022-09-06 12:40:41 +0200624bool __maybe_unused __weak soc_detection(void)
625{
626 return false;
627}
628
629char * __maybe_unused __weak soc_name_decode(void)
630{
631 return NULL;
632}
633
Michal Simek88232532021-07-23 09:59:59 +0200634int embedded_dtb_select(void)
635{
Michal Simek39d3c3c2022-09-06 12:40:41 +0200636 if (soc_detection()) {
637 char *soc_local_name;
638
639 soc_local_name = soc_name_decode();
640 if (soc_local_name) {
641 board_name = soc_local_name;
642 printf("Detected SOC name: %s\n", board_name);
643
644 /* Time to change DTB on fly */
645 /* Both ways should work here */
646 /* fdtdec_resetup(&rescan); */
647 return fdtdec_setup();
648 }
649 }
650
Michal Simek88232532021-07-23 09:59:59 +0200651 if (board_detection()) {
652 char *board_local_name;
653
654 board_local_name = board_name_decode();
655 if (board_local_name) {
656 board_name = board_local_name;
Michal Simek52ff1622021-08-11 14:23:54 +0200657 printf("Detected name: %s\n", board_name);
Michal Simek88232532021-07-23 09:59:59 +0200658
659 /* Time to change DTB on fly */
660 /* Both ways should work here */
661 /* fdtdec_resetup(&rescan); */
662 fdtdec_setup();
663 }
664 }
665 return 0;
666}
667#endif
Michal Simeka32c3e92022-08-25 14:23:10 +0200668
669#if defined(CONFIG_LMB)
Michal Simek7576ab22023-11-06 12:56:47 +0100670
671#ifndef MMU_SECTION_SIZE
672#define MMU_SECTION_SIZE (1 * 1024 * 1024)
673#endif
674
Heinrich Schuchardtd768dd82023-08-12 20:16:58 +0200675phys_addr_t board_get_usable_ram_top(phys_size_t total_size)
Michal Simeka32c3e92022-08-25 14:23:10 +0200676{
677 phys_size_t size;
678 phys_addr_t reg;
679 struct lmb lmb;
680
681 if (!total_size)
682 return gd->ram_top;
683
684 if (!IS_ALIGNED((ulong)gd->fdt_blob, 0x8))
685 panic("Not 64bit aligned DT location: %p\n", gd->fdt_blob);
686
687 /* found enough not-reserved memory to relocated U-Boot */
688 lmb_init(&lmb);
689 lmb_add(&lmb, gd->ram_base, gd->ram_size);
690 boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob);
691 size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE);
692 reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE);
693
694 if (!reg)
695 reg = gd->ram_top - size;
696
697 return reg + size;
698}
699#endif
Venkatesh Yadav Abbarapua2700992024-01-17 08:50:13 +0530700
701#ifdef CONFIG_OF_BOARD_SETUP
702#define MAX_RAND_SIZE 8
703int ft_board_setup(void *blob, struct bd_info *bd)
704{
705 size_t n = MAX_RAND_SIZE;
706 struct udevice *dev;
707 u8 buf[MAX_RAND_SIZE];
708 int nodeoffset, ret;
709
James Hilliard6c4a7392024-03-31 17:28:59 -0600710 static const struct node_info nodes[] = {
711 { "arm,pl353-nand-r2p1", MTD_DEV_TYPE_NAND, },
712 };
713
714 if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ))
715 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
716
Venkatesh Yadav Abbarapua2700992024-01-17 08:50:13 +0530717 if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) {
718 debug("No RNG device\n");
719 return 0;
720 }
721
722 if (dm_rng_read(dev, buf, n)) {
723 debug("Reading RNG failed\n");
724 return 0;
725 }
726
727 if (!blob) {
728 debug("No FDT memory address configured. Please configure\n"
729 "the FDT address via \"fdt addr <address>\" command.\n"
730 "Aborting!\n");
731 return 0;
732 }
733
734 ret = fdt_check_header(blob);
735 if (ret < 0) {
736 debug("fdt_chosen: %s\n", fdt_strerror(ret));
737 return ret;
738 }
739
740 nodeoffset = fdt_find_or_add_subnode(blob, 0, "chosen");
741 if (nodeoffset < 0) {
742 debug("Reading chosen node failed\n");
743 return nodeoffset;
744 }
745
746 ret = fdt_setprop(blob, nodeoffset, "kaslr-seed", buf, sizeof(buf));
747 if (ret < 0) {
748 debug("Unable to set kaslr-seed on chosen node: %s\n", fdt_strerror(ret));
749 return ret;
750 }
751
752 return 0;
753}
754#endif