]>
Commit | Line | Data |
---|---|---|
9755e3db MS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
8174cd21 MS |
3 | * (C) Copyright 2014 - 2022, Xilinx, Inc. |
4 | * (C) Copyright 2022 - 2023, Advanced Micro Devices, Inc. | |
5 | * | |
6 | * Michal Simek <michal.simek@amd.com> | |
9755e3db MS |
7 | */ |
8 | ||
d678a59d | 9 | #include <common.h> |
741ef867 SG |
10 | #include <efi.h> |
11 | #include <efi_loader.h> | |
09140113 | 12 | #include <env.h> |
a32c3e9e | 13 | #include <image.h> |
fb737f1e | 14 | #include <init.h> |
6c4a7398 | 15 | #include <jffs2/load_kernel.h> |
a32c3e9e | 16 | #include <lmb.h> |
f7ae49fc | 17 | #include <log.h> |
401d1c4f | 18 | #include <asm/global_data.h> |
fc274a59 | 19 | #include <asm/sections.h> |
9755e3db MS |
20 | #include <dm/uclass.h> |
21 | #include <i2c.h> | |
a29511ee | 22 | #include <linux/sizes.h> |
d61728c8 | 23 | #include <malloc.h> |
6c4a7398 | 24 | #include <mtd_node.h> |
80fdef12 | 25 | #include "board.h" |
d61728c8 MS |
26 | #include <dm.h> |
27 | #include <i2c_eeprom.h> | |
28 | #include <net.h> | |
05af4834 | 29 | #include <generated/dt.h> |
a270099e | 30 | #include <rng.h> |
8174cd21 | 31 | #include <slre.h> |
80c0d38a | 32 | #include <soc.h> |
52ff1626 | 33 | #include <linux/ctype.h> |
741ef867 | 34 | #include <linux/kernel.h> |
ee5a4b87 | 35 | #include <uuid.h> |
9755e3db | 36 | |
f149b39c MS |
37 | #include "fru.h" |
38 | ||
71aa806d | 39 | #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) |
741ef867 SG |
40 | struct 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 | |
3d3cb285 | 48 | #if defined(XILINX_UBOOT_IMAGE_GUID) && defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) |
741ef867 SG |
49 | { |
50 | .image_type_id = XILINX_UBOOT_IMAGE_GUID, | |
51 | .fw_name = u"XILINX-UBOOT", | |
52 | .image_index = 2, | |
53 | }, | |
54 | #endif | |
55 | }; | |
56 | ||
57 | struct efi_capsule_update_info update_info = { | |
cccea188 | 58 | .num_images = ARRAY_SIZE(fw_images), |
741ef867 SG |
59 | .images = fw_images, |
60 | }; | |
61 | ||
741ef867 SG |
62 | #endif /* EFI_HAVE_CAPSULE_SUPPORT */ |
63 | ||
d61728c8 MS |
64 | #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 | |
ee5a4b87 | 71 | #define EEPROM_HDR_UUID_LEN 16 |
d61728c8 MS |
72 | |
73 | struct 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]; | |
ee5a4b87 | 80 | char uuid[EEPROM_HDR_UUID_LEN + 1]; |
d61728c8 MS |
81 | }; |
82 | ||
a03b5947 | 83 | static int highest_id = -1; |
d9c93c9e | 84 | static struct xilinx_board_description *board_info; |
d61728c8 | 85 | |
f149b39c | 86 | #define XILINX_I2C_DETECTION_BITS sizeof(struct fru_common_hdr) |
d61728c8 MS |
87 | |
88 | /* Variable which stores pointer to array which stores eeprom content */ | |
89 | struct xilinx_legacy_format { | |
90 | char board_sn[18]; /* 0x0 */ | |
91 | char unused0[14]; /* 0x12 */ | |
b86b135f | 92 | char eth_mac[ETH_ALEN]; /* 0x20 */ |
d61728c8 MS |
93 | 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 | ||
100 | static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size) | |
101 | { | |
102 | int i; | |
e1a193b9 | 103 | unsigned char byte; |
d61728c8 MS |
104 | |
105 | for (i = 0; i < size; i++) { | |
106 | byte = eeprom[i]; | |
107 | ||
f03f962c PZ |
108 | /* 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 > '~') { | |
d61728c8 | 116 | eeprom[i] = 0; |
e6c62537 MS |
117 | continue; |
118 | } | |
d61728c8 MS |
119 | |
120 | /* Convert strings to lower case */ | |
121 | if (byte >= 'A' && byte <= 'Z') | |
122 | eeprom[i] = byte + 'a' - 'A'; | |
123 | } | |
124 | } | |
125 | ||
126 | static 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 | ||
5563167e MS |
151 | /* 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); | |
d61728c8 MS |
158 | |
159 | eth_valid = is_valid_ethaddr((const u8 *)eeprom_content->eth_mac); | |
160 | if (eth_valid) | |
5563167e MS |
161 | memcpy(desc->mac_addr[0], eeprom_content->eth_mac, ETH_ALEN); |
162 | ||
163 | 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); | |
d61728c8 | 167 | |
d61728c8 | 168 | if (eth_valid) |
5563167e | 169 | printf(" Ethernet mac:\t%pM\n", desc->mac_addr); |
d61728c8 MS |
170 | |
171 | desc->header = EEPROM_HEADER_MAGIC; | |
172 | ||
173 | free(eeprom_content); | |
174 | ||
175 | return ret; | |
176 | } | |
177 | ||
178 | static 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 | ||
f149b39c MS |
193 | static int xilinx_read_eeprom_fru(struct udevice *dev, char *name, |
194 | struct xilinx_board_description *desc) | |
195 | { | |
530560b6 | 196 | int i, ret, eeprom_size; |
f149b39c | 197 | u8 *fru_content; |
7a036b67 | 198 | u8 id = 0; |
f149b39c MS |
199 | |
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__); | |
b262863b | 214 | goto end; |
f149b39c MS |
215 | } |
216 | ||
f149b39c | 217 | fru_capture((unsigned long)fru_content); |
866ec874 | 218 | if (gd->flags & GD_FLG_RELOC || (_DEBUG && IS_ENABLED(CONFIG_DTB_RESELECT))) { |
52ff1626 MS |
219 | 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 | } | |
f149b39c MS |
225 | } |
226 | ||
227 | if (desc->header == EEPROM_HEADER_MAGIC) { | |
228 | debug("Information already filled\n"); | |
b262863b MS |
229 | ret = -EINVAL; |
230 | goto end; | |
f149b39c MS |
231 | } |
232 | ||
233 | /* It is clear that FRU was captured and structures were filled */ | |
4a1bfcd7 | 234 | strlcpy(desc->manufacturer, (char *)fru_data.brd.manufacturer_name, |
f149b39c | 235 | sizeof(desc->manufacturer)); |
4a1bfcd7 | 236 | strlcpy(desc->uuid, (char *)fru_data.brd.uuid, |
ee5a4b87 | 237 | sizeof(desc->uuid)); |
4a1bfcd7 | 238 | strlcpy(desc->name, (char *)fru_data.brd.product_name, |
f149b39c | 239 | sizeof(desc->name)); |
530560b6 MS |
240 | for (i = 0; i < sizeof(desc->name); i++) { |
241 | if (desc->name[i] == ' ') | |
242 | desc->name[i] = '\0'; | |
243 | } | |
4a1bfcd7 | 244 | strlcpy(desc->revision, (char *)fru_data.brd.rev, |
f149b39c | 245 | sizeof(desc->revision)); |
93216276 MS |
246 | for (i = 0; i < sizeof(desc->revision); i++) { |
247 | if (desc->revision[i] == ' ') | |
248 | desc->revision[i] = '\0'; | |
249 | } | |
4a1bfcd7 | 250 | strlcpy(desc->serial, (char *)fru_data.brd.serial_number, |
f149b39c | 251 | sizeof(desc->serial)); |
7a036b67 ARS |
252 | |
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 | ||
f149b39c MS |
260 | desc->header = EEPROM_HEADER_MAGIC; |
261 | ||
b262863b MS |
262 | end: |
263 | free(fru_content); | |
264 | return ret; | |
f149b39c MS |
265 | } |
266 | ||
267 | static 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 | ||
d61728c8 MS |
292 | static 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 | ||
f8daba44 | 316 | if (IS_ENABLED(CONFIG_CMD_FRU) && xilinx_detect_fru(buffer)) |
f149b39c MS |
317 | return xilinx_read_eeprom_fru(dev, name, desc); |
318 | ||
d61728c8 MS |
319 | 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 | { | |
d9c93c9e | 327 | int id; |
d61728c8 | 328 | char name_buf[8]; /* 8 bytes should be enough for nvmem+number */ |
a03b5947 | 329 | struct xilinx_board_description *desc; |
d61728c8 MS |
330 | |
331 | highest_id = dev_read_alias_highest_id("nvmem"); | |
332 | /* No nvmem aliases present */ | |
333 | if (highest_id < 0) | |
334 | return -EINVAL; | |
335 | ||
d9c93c9e | 336 | board_info = calloc(1, sizeof(*desc) * (highest_id + 1)); |
d61728c8 MS |
337 | 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 | ||
a03b5947 | 346 | /* Alloc structure */ |
d9c93c9e | 347 | desc = &board_info[id]; |
a03b5947 | 348 | |
d61728c8 | 349 | /* Ignoring return value for supporting multiple chips */ |
d9c93c9e | 350 | xilinx_read_eeprom_single(name_buf, desc); |
d61728c8 MS |
351 | } |
352 | ||
a03b5947 MS |
353 | /* |
354 | * Consider to clean board_info structure when board/cards are not | |
355 | * detected. | |
356 | */ | |
d61728c8 MS |
357 | |
358 | return 0; | |
359 | } | |
360 | ||
f0631005 | 361 | #if defined(CONFIG_OF_BOARD) |
e7fb7896 | 362 | void *board_fdt_blob_setup(int *err) |
fec657be | 363 | { |
e2572b55 | 364 | void *fdt_blob; |
453bb77d | 365 | |
e7fb7896 | 366 | *err = 0; |
451b2ea2 MS |
367 | |
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 | ||
a672b987 MS |
375 | if (!IS_ENABLED(CONFIG_SPL_BUILD) && |
376 | !IS_ENABLED(CONFIG_VERSAL_NO_DDR) && | |
fc3c6fd7 | 377 | !IS_ENABLED(CONFIG_ZYNQMP_NO_DDR)) { |
506009fc | 378 | fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR; |
fec657be | 379 | |
506009fc MS |
380 | if (fdt_magic(fdt_blob) == FDT_MAGIC) |
381 | return fdt_blob; | |
fec657be | 382 | |
506009fc MS |
383 | debug("DTB is not passed via %p\n", fdt_blob); |
384 | } | |
fc274a59 | 385 | |
506009fc MS |
386 | 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)) | |
ccea96f4 | 392 | fdt_blob = (ulong *)_image_binary_end; |
506009fc | 393 | else |
ccea96f4 | 394 | fdt_blob = (ulong *)__bss_end; |
506009fc MS |
395 | } else { |
396 | /* FDT is at end of image */ | |
ccea96f4 | 397 | fdt_blob = (ulong *)_end; |
506009fc | 398 | } |
fc274a59 MS |
399 | |
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 | ||
f0631005 | 405 | *err = -EINVAL; |
fc274a59 | 406 | return NULL; |
fec657be IE |
407 | } |
408 | #endif | |
80fdef12 | 409 | |
7c553ac0 | 410 | #if defined(CONFIG_BOARD_LATE_INIT) |
a03b5947 MS |
411 | static 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 | ||
80fdef12 MS |
423 | int board_late_init_xilinx(void) |
424 | { | |
ca0f6165 | 425 | u32 ret = 0; |
a03b5947 MS |
426 | int i, id, macid = 0; |
427 | struct xilinx_board_description *desc; | |
e6e3b9d7 | 428 | phys_size_t bootm_size = gd->ram_top - gd->ram_base; |
0bbc962e | 429 | u64 bootscr_flash_offset, bootscr_flash_size; |
d388cedd | 430 | |
0c22cdca | 431 | if (!IS_ENABLED(CONFIG_MICROBLAZE)) { |
d388cedd | 432 | ulong scriptaddr; |
5528f797 ASS |
433 | u64 bootscr_address; |
434 | u64 bootscr_offset; | |
435 | ||
436 | /* 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 | } | |
d388cedd | 452 | } |
2570cc64 | 453 | |
0bbc962e MS |
454 | 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 | ||
0c22cdca | 464 | if (IS_ENABLED(CONFIG_ARCH_ZYNQ) || IS_ENABLED(CONFIG_MICROBLAZE)) |
2570cc64 | 465 | bootm_size = min(bootm_size, (phys_size_t)(SZ_512M + SZ_256M)); |
80fdef12 | 466 | |
ca0f6165 | 467 | ret |= env_set_addr("bootm_low", (void *)gd->ram_base); |
2570cc64 | 468 | ret |= env_set_addr("bootm_size", (void *)bootm_size); |
ca0f6165 | 469 | |
a03b5947 | 470 | for (id = 0; id <= highest_id; id++) { |
d9c93c9e | 471 | desc = &board_info[id]; |
a03b5947 MS |
472 | 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); | |
d61728c8 | 485 | |
ee5a4b87 | 486 | if (desc->uuid[0]) { |
e1a193b9 VYA |
487 | unsigned char uuid[UUID_STR_LEN + 1]; |
488 | unsigned char *t = desc->uuid; | |
ee5a4b87 MS |
489 | |
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 | ||
d61728c8 MS |
499 | if (!CONFIG_IS_ENABLED(NET)) |
500 | continue; | |
501 | ||
a03b5947 | 502 | for (i = 0; i < EEPROM_HDR_NO_OF_MAC_ADDR; i++) { |
a03b5947 MS |
503 | 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 | } | |
d61728c8 MS |
507 | } |
508 | } | |
509 | ||
ca0f6165 MS |
510 | if (ret) |
511 | printf("%s: Saving run time variables FAILED\n", __func__); | |
c8da6513 | 512 | |
80fdef12 MS |
513 | return 0; |
514 | } | |
7c553ac0 | 515 | #endif |
05af4834 | 516 | |
57f71032 MS |
517 | static char *board_name = DEVICE_TREE; |
518 | ||
05af4834 MS |
519 | int __maybe_unused board_fit_config_name_match(const char *name) |
520 | { | |
57f71032 | 521 | debug("%s: Check %s, default %s\n", __func__, name, board_name); |
05af4834 | 522 | |
8174cd21 | 523 | #if !defined(CONFIG_SPL_BUILD) |
eca09868 | 524 | if (IS_ENABLED(CONFIG_REGEX)) { |
8174cd21 MS |
525 | 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 | ||
57f71032 | 538 | if (!strcmp(name, board_name)) |
05af4834 MS |
539 | return 0; |
540 | ||
541 | return -1; | |
542 | } | |
80c0d38a | 543 | |
866ec874 | 544 | #if IS_ENABLED(CONFIG_DTB_RESELECT) |
52ff1626 MS |
545 | #define MAX_NAME_LENGTH 50 |
546 | ||
88232532 MS |
547 | char * __maybe_unused __weak board_name_decode(void) |
548 | { | |
52ff1626 MS |
549 | 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 | ||
607 | error: | |
608 | free(board_local_name); | |
88232532 MS |
609 | return NULL; |
610 | } | |
611 | ||
612 | bool __maybe_unused __weak board_detection(void) | |
613 | { | |
52ff1626 MS |
614 | 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 | ||
88232532 MS |
621 | return false; |
622 | } | |
623 | ||
39d3c3cf MS |
624 | bool __maybe_unused __weak soc_detection(void) |
625 | { | |
626 | return false; | |
627 | } | |
628 | ||
629 | char * __maybe_unused __weak soc_name_decode(void) | |
630 | { | |
631 | return NULL; | |
632 | } | |
633 | ||
88232532 MS |
634 | int embedded_dtb_select(void) |
635 | { | |
39d3c3cf MS |
636 | 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 | ||
88232532 MS |
651 | 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; | |
52ff1626 | 657 | printf("Detected name: %s\n", board_name); |
88232532 MS |
658 | |
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 | |
a32c3e9e MS |
668 | |
669 | #if defined(CONFIG_LMB) | |
7576ab2f MS |
670 | |
671 | #ifndef MMU_SECTION_SIZE | |
672 | #define MMU_SECTION_SIZE (1 * 1024 * 1024) | |
673 | #endif | |
674 | ||
d768dd88 | 675 | phys_addr_t board_get_usable_ram_top(phys_size_t total_size) |
a32c3e9e MS |
676 | { |
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 | |
a270099e VYA |
700 | |
701 | #ifdef CONFIG_OF_BOARD_SETUP | |
702 | #define MAX_RAND_SIZE 8 | |
703 | int 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 | ||
6c4a7398 JH |
710 | 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 | ||
a270099e VYA |
717 | 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 |