1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <console/console.h>
7 #include <soc/otp.h>
8 #include <soc/sdram.h>
9 #include <cbfs.h>
10 #include <commonlib/device_tree.h>
11 #include <bootstate.h>
12 #include <mcall.h>
13 
do_fixup_mac(struct device_tree_node * node)14 static void do_fixup_mac(struct device_tree_node *node)
15 {
16 	uint32_t serial = otp_read_serial();
17 	static unsigned char mac[6] = { 0x70, 0xb3, 0xd5, 0x92, 0xf0, 0x00 };
18 	if (serial != ~0) {
19 		mac[5] |= (serial >>  0) & 0xff;
20 		mac[4] |= (serial >>  8) & 0xff;
21 		mac[3] |= (serial >> 16) & 0xff;
22 	}
23 	dt_add_bin_prop(node, "local-mac-address", mac, 6);
24 }
25 
fixup_mac(struct device_tree_node * parent)26 static void fixup_mac(struct device_tree_node *parent)
27 {
28 	struct device_tree_property *prop;
29 	const char *name = "local-mac-address";
30 
31 	list_for_each(prop, parent->properties, list_node) {
32 		if (!strcmp(name, prop->prop.name))
33 			do_fixup_mac(parent);
34 	}
35 
36 	struct device_tree_node *child;
37 	list_for_each(child, parent->children, list_node) {
38 		fixup_mac(child);
39 	}
40 }
41 
do_fixup_memory(struct device_tree_node * node)42 static void do_fixup_memory(struct device_tree_node *node)
43 {
44 	u64 addrs[1], sizes[1];
45 	addrs[0] = 0x80000000;
46 	sizes[0] = sdram_size_mb() * 1024 * 1024;
47 	dt_add_reg_prop(node, addrs, sizes, 1, 2, 2);
48 }
49 
fixup_memory(struct device_tree_node * parent)50 static void fixup_memory(struct device_tree_node *parent)
51 {
52 	struct device_tree_property *prop;
53 	const char *name = "device_type";
54 	const char *value = "memory";
55 
56 	list_for_each(prop, parent->properties, list_node) {
57 		if (!strcmp(name, prop->prop.name)) {
58 			if (!strcmp(value, (char *)prop->prop.data))
59 				do_fixup_memory(parent);
60 		}
61 	}
62 
63 	struct device_tree_node *child;
64 	list_for_each(child, parent->children, list_node) {
65 		fixup_memory(child);
66 	}
67 }
68 
fixup_fdt(void * unused)69 static void fixup_fdt(void *unused)
70 {
71 	void *fdt_rom;
72 	struct device_tree *tree;
73 
74 	/* load flat dt from cbfs */
75 	fdt_rom = cbfs_map("fallback/DTB", NULL);
76 
77 	if (fdt_rom == NULL) {
78 		printk(BIOS_ERR, "Unable to load fallback/DTB from CBFS\n");
79 		return;
80 	}
81 
82 	/* Expand DT into a tree */
83 	tree = fdt_unflatten(fdt_rom);
84 
85 	/* fixup tree */
86 	fixup_mac(tree->root);
87 	fixup_memory(tree->root);
88 
89 	/* convert the tree to a flat dt */
90 	void *dt = malloc(dt_flat_size(tree));
91 
92 	if (dt == NULL) {
93 		printk(BIOS_ERR, "Unable to allocate memory for flat device tree\n");
94 		return;
95 	}
96 
97 	dt_flatten(tree, dt);
98 
99 	/* update HLS */
100 	for (int i = 0; i < CONFIG_MAX_CPUS; i++)
101 		OTHER_HLS(i)->fdt = dt;
102 }
103 
104 BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_EXIT, fixup_fdt, NULL);
105