#include <common.h>
#include <boot_fit.h>
#include <dm.h>
+#include <hang.h>
+#include <init.h>
+#include <malloc.h>
#include <dm/of_extra.h>
+#include <env.h>
#include <errno.h>
#include <fdtdec.h>
#include <fdt_support.h>
+#include <gzip.h>
#include <mapmem.h>
#include <linux/libfdt.h>
#include <serial.h>
}
#if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI)
-int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
- const char *prop_name, struct fdt_pci_addr *addr)
-{
- const u32 *cell;
- int len;
- int ret = -ENOENT;
-
- debug("%s: %s: ", __func__, prop_name);
-
- /*
- * If we follow the pci bus bindings strictly, we should check
- * the value of the node's parent node's #address-cells and
- * #size-cells. They need to be 3 and 2 accordingly. However,
- * for simplicity we skip the check here.
- */
- cell = fdt_getprop(blob, node, prop_name, &len);
- if (!cell)
- goto fail;
-
- if ((len % FDT_PCI_REG_SIZE) == 0) {
- int num = len / FDT_PCI_REG_SIZE;
- int i;
-
- for (i = 0; i < num; i++) {
- debug("pci address #%d: %08lx %08lx %08lx\n", i,
- (ulong)fdt32_to_cpu(cell[0]),
- (ulong)fdt32_to_cpu(cell[1]),
- (ulong)fdt32_to_cpu(cell[2]));
- if ((fdt32_to_cpu(*cell) & type) == type) {
- addr->phys_hi = fdt32_to_cpu(cell[0]);
- addr->phys_mid = fdt32_to_cpu(cell[1]);
- addr->phys_lo = fdt32_to_cpu(cell[1]);
- break;
- }
-
- cell += (FDT_PCI_ADDR_CELLS +
- FDT_PCI_SIZE_CELLS);
- }
-
- if (i == num) {
- ret = -ENXIO;
- goto fail;
- }
-
- return 0;
- }
-
- ret = -EINVAL;
-
-fail:
- debug("(not found)\n");
- return ret;
-}
-
int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
{
const char *list, *end;
return -ENOENT;
}
-int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr,
+int fdtdec_get_pci_bar32(const struct udevice *dev, struct fdt_pci_addr *addr,
u32 *bar)
{
int barnum;
uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
uint64_t default_val)
{
- const uint64_t *cell64;
+ const unaligned_fdt64_t *cell64;
int length;
cell64 = fdt_getprop(blob, node, prop_name, &length);
return rc;
}
-int fdtdec_get_child_count(const void *blob, int node)
-{
- int subnode;
- int num = 0;
-
- fdt_for_each_subnode(subnode, blob, node)
- num++;
-
- return num;
-}
-
int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
u8 *array, int count)
{
}
#endif
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size)
+{
+ const char *path;
+ int offset, err;
+
+ if (!is_valid_ethaddr(mac))
+ return -EINVAL;
+
+ path = fdt_get_alias(fdt, "ethernet");
+ if (!path)
+ return 0;
+
+ debug("ethernet alias found: %s\n", path);
+
+ offset = fdt_path_offset(fdt, path);
+ if (offset < 0) {
+ debug("ethernet alias points to absent node %s\n", path);
+ return -ENOENT;
+ }
+
+ err = fdt_setprop_inplace(fdt, offset, "local-mac-address", mac, size);
+ if (err < 0)
+ return err;
+
+ debug("MAC address: %pM\n", mac);
+
+ return 0;
+}
+
static int fdtdec_init_reserved_memory(void *blob)
{
int na, ns, node, err;
fdt32_t cells[4] = {}, *ptr = cells;
uint32_t upper, lower, phandle;
int parent, node, na, ns, err;
+ fdt_size_t size;
char name[64];
/* create an empty /reserved-memory node if one doesn't exist */
continue;
}
- if (addr == carveout->start && (addr + size) == carveout->end) {
- *phandlep = fdt_get_phandle(blob, node);
+ if (addr == carveout->start && (addr + size - 1) ==
+ carveout->end) {
+ if (phandlep)
+ *phandlep = fdt_get_phandle(blob, node);
return 0;
}
}
* Unpack the start address and generate the name of the new node
* base on the basename and the unit-address.
*/
- lower = fdt_addr_unpack(carveout->start, &upper);
+ upper = upper_32_bits(carveout->start);
+ lower = lower_32_bits(carveout->start);
if (na > 1 && upper > 0)
snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
if (node < 0)
return node;
- err = fdt_generate_phandle(blob, &phandle);
- if (err < 0)
- return err;
+ if (phandlep) {
+ err = fdt_generate_phandle(blob, &phandle);
+ if (err < 0)
+ return err;
- err = fdtdec_set_phandle(blob, node, phandle);
- if (err < 0)
- return err;
+ err = fdtdec_set_phandle(blob, node, phandle);
+ if (err < 0)
+ return err;
+ }
/* store one or two address cells */
if (na > 1)
*ptr++ = cpu_to_fdt32(lower);
/* store one or two size cells */
- lower = fdt_size_unpack(carveout->end - carveout->start + 1, &upper);
+ size = carveout->end - carveout->start + 1;
+ upper = upper_32_bits(size);
+ lower = lower_32_bits(size);
if (ns > 1)
*ptr++ = cpu_to_fdt32(upper);
const struct fdt_memory *carveout)
{
uint32_t phandle;
- int err, offset;
+ int err, offset, len;
fdt32_t value;
-
- /* XXX implement support for multiple phandles */
- if (index > 0) {
- debug("invalid index %u\n", index);
- return -FDT_ERR_BADOFFSET;
- }
+ void *prop;
err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
if (err < 0) {
value = cpu_to_fdt32(phandle);
- err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
+ if (!fdt_getprop(blob, offset, prop_name, &len)) {
+ if (len == -FDT_ERR_NOTFOUND)
+ len = 0;
+ else
+ return len;
+ }
+
+ if ((index + 1) * sizeof(value) > len) {
+ err = fdt_setprop_placeholder(blob, offset, prop_name,
+ (index + 1) * sizeof(value),
+ &prop);
+ if (err < 0) {
+ debug("failed to resize reserved memory property: %s\n",
+ fdt_strerror(err));
+ return err;
+ }
+ }
+
+ err = fdt_setprop_inplace_namelen_partial(blob, offset, prop_name,
+ strlen(prop_name),
+ index * sizeof(value),
+ &value, sizeof(value));
if (err < 0) {
- debug("failed to set %s property for node %s: %d\n", prop_name,
- node, err);
+ debug("failed to update %s property for node %s: %s\n",
+ prop_name, node, fdt_strerror(err));
return err;
}
puts("Failed to read control FDT\n");
return -1;
}
+# elif defined(CONFIG_OF_PRIOR_STAGE)
+ gd->fdt_blob = (void *)prior_stage_fdt_address;
# endif
# ifndef CONFIG_SPL_BUILD
/* Allow the early environment to override the fdt address */
-# if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
- gd->fdt_blob = (void *)prior_stage_fdt_address;
-# else
gd->fdt_blob = map_sysmem
(env_get_ulong("fdtcontroladdr", 16,
(unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
-# endif
# endif
# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)