Example #1
0
int
fdt_reg_valid(uint32_t *reg, int len, int addr_cells, int size_cells)
{
	int cells_in_tuple, i, tuples, tuple_size;
	uint32_t cur_start, cur_size;

	cells_in_tuple = (addr_cells + size_cells);
	tuple_size = cells_in_tuple * sizeof(uint32_t);
	tuples = len / tuple_size;
	if (tuples == 0)
		return (EINVAL);

	for (i = 0; i < tuples; i++) {
		if (addr_cells == 2)
			cur_start = fdt64_to_cpu(reg[i * cells_in_tuple]);
		else
			cur_start = fdt32_to_cpu(reg[i * cells_in_tuple]);

		if (size_cells == 2)
			cur_size = fdt64_to_cpu(reg[i * cells_in_tuple + 2]);
		else
			cur_size = fdt32_to_cpu(reg[i * cells_in_tuple + 1]);

		if (cur_size == 0)
			return (EINVAL);

		debugf(" reg#%d (start: 0x%0x size: 0x%0x) valid!\n",
		    i, cur_start, cur_size);
	}
	return (0);
}
Example #2
0
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
	CHECK_HEADER(fdt);
	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
	return 0;
}
Example #3
0
int fdt_num_mem_rsv(const void *fdt)
{
	int i = 0;

	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
		i++;
	return i;
}
Example #4
0
u_long
fdt_data_get(void *data, int cells)
{

	if (cells == 1)
		return (fdt32_to_cpu(*((uint32_t *)data)));

	return (fdt64_to_cpu(*((uint64_t *)data)));
}
Example #5
0
/* memory reserve map의 개수를 구한다.*/ 
int fdt_num_mem_rsv(const void *fdt)
{
	int i = 0;

	/* size가 0이 아니면 reserve map이 있다고 판단한다. */
	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
		i++;
	return i;
}
Example #6
0
void platform_early_init(void)
{
    /* initialize the interrupt controller */
    arm_gic_init();

    arm_generic_timer_init(ARM_GENERIC_TIMER_PHYSICAL_INT, 0);

    uart_init_early();

    /* look for a flattened device tree just before the kernel */
    const void *fdt = (void *)KERNEL_BASE;
    int err = fdt_check_header(fdt);
    if (err >= 0) {
        /* walk the nodes, looking for 'memory' */
        int depth = 0;
        int offset = 0;
        for (;;) {
            offset = fdt_next_node(fdt, offset, &depth);
            if (offset < 0)
                break;

            /* get the name */
            const char *name = fdt_get_name(fdt, offset, NULL);
            if (!name)
                continue;

            /* look for the 'memory' property */
            if (strcmp(name, "memory") == 0) {
                int lenp;
                const void *prop_ptr = fdt_getprop(fdt, offset, "reg", &lenp);
                if (prop_ptr && lenp == 0x10) {
                    /* we're looking at a memory descriptor */
                    //uint64_t base = fdt64_to_cpu(*(uint64_t *)prop_ptr);
                    uint64_t len = fdt64_to_cpu(*((const uint64_t *)prop_ptr + 1));

                    /* trim size on certain platforms */
#if ARCH_ARM
                    if (len > 1024*1024*1024U) {
                        len = 1024*1024*1024; /* only use the first 1GB on ARM32 */
                        printf("trimming memory to 1GB\n");
                    }
#endif

                    /* set the size in the pmm arena */
                    arena.size = len;
                }
            }
        }
    }

    /* add the main memory arena */
    pmm_add_arena(&arena);

    /* reserve the first 64k of ram, which should be holding the fdt */
    struct list_node list = LIST_INITIAL_VALUE(list);
    pmm_alloc_range(MEMBASE, 0x10000 / PAGE_SIZE, &list);
}
Example #7
0
uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
		uint64_t default_val)
{
	const uint64_t *cell64;
	int length;

	cell64 = fdt_getprop(blob, node, prop_name, &length);
	if (!cell64 || length < sizeof(*cell64))
		return default_val;

	return fdt64_to_cpu(*cell64);
}
Example #8
0
static int mem_rsv_cmp(const void *p1, const void *p2)
{
	const struct fdt_reserve_entry *re1 = p1;
	const struct fdt_reserve_entry *re2 = p2;

	if (fdt64_to_cpu(re1->address) < fdt64_to_cpu(re2->address))
		return -1;
	else if (fdt64_to_cpu(re1->address) > fdt64_to_cpu(re2->address))
		return 1;

	if (fdt64_to_cpu(re1->size) < fdt64_to_cpu(re2->size))
		return -1;
	else if (fdt64_to_cpu(re1->size) > fdt64_to_cpu(re2->size))
		return 1;

	return 0;
}
Example #9
0
static __init u64 get_kaslr_seed(void *fdt)
{
	int node, len;
	fdt64_t *prop;
	u64 ret;

	node = fdt_path_offset(fdt, "/chosen");
	if (node < 0)
		return 0;

	prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len);
	if (!prop || len != sizeof(u64))
		return 0;

	ret = fdt64_to_cpu(*prop);
	*prop = 0;
	return ret;
}
Example #10
0
static void
bcm2835_late_init(platform_t plat)
{
	phandle_t system;
	pcell_t cells[2];
	int len;

	system = OF_finddevice("/system");
	if (system != 0) {
		len = OF_getprop(system, "linux,serial", &cells, sizeof(cells));
		if (len > 0)
			board_set_serial(fdt64_to_cpu(*((uint64_t *)cells)));

		len = OF_getprop(system, "linux,revision", &cells, sizeof(cells));
		if (len > 0)
			board_set_revision(fdt32_to_cpu(*((uint32_t *)cells)));
	}
}
Example #11
0
static uint32_t discover_processors(void)
{
#if defined(HAS_UBOOT)
  return QORIQ_CPU_COUNT;
#elif defined(U_BOOT_USE_FDT)
  const void *fdt = bsp_fdt_get();
  int cpus = fdt_path_offset(fdt, "/cpus");
  int node = fdt_first_subnode(fdt, cpus);
  uint32_t cpu = 0;
  uintptr_t last = 0;
  uintptr_t begin = last - 1;

  while (node >= 0) {
    int len;
    fdt64_t *addr_fdt = (fdt64_t *)
      fdt_getprop(fdt, node, "cpu-release-addr", &len);

    if (
      addr_fdt != NULL
        && cpu < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr)
    ) {
      uintptr_t addr = (uintptr_t) fdt64_to_cpu(*addr_fdt);

      if (addr < begin) {
        begin = addr;
      }

      if (addr > last) {
        last = addr;
      }

      qoriq_start_spin_table_addr[cpu] = (qoriq_start_spin_table *) addr;
      ++cpu;
    }

    node = fdt_next_subnode(fdt, node);
  }

  return cpu * QORIQ_THREAD_COUNT;
#endif
}
Example #12
0
static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
{
	const char *end = p + len;
	assert(len % width == 0);

	for (; p < end; p += width) {
		switch (width) {
		case 1:
			fprintf(f, " %02"PRIx8, *(const uint8_t*)p);
			break;
		case 2:
			fprintf(f, " 0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
			break;
		case 4:
			fprintf(f, " 0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
			break;
		case 8:
			fprintf(f, " 0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
			break;
		}
	}
}
Example #13
0
static int getprop_u64(const void *fdt, int nodeoffset, const char *name, uint64_t *val)
{
	int len;
	const fdt64_t *prop;

	prop = fdt_getprop(fdt, nodeoffset, name, &len);
	if (!prop && len == -FDT_ERR_NOTFOUND)
		return -1;

	if (!prop) {
		fprintf(stderr, "getprop_u64 %s returned %d\n", name, len);
		return -1;
	}

	if (len != sizeof(uint64_t)) {
		fprintf(stderr, "getprop_u64 %s unexpected length %d\n", name, len);
		return -1;
	}

	*val = fdt64_to_cpu(*prop);
	return 0;
}
Example #14
0
static uint64
fdt_get_range_offset(const void* fdt, int32 node)
{
	// Obtain the offset of the device by searching
	// for the first ranges start in parents.

	// It could be possible that there are multiple
	// offset ranges in several parents + children.
	// Lets hope that no system designer is that insane.
	int depth = fdt_node_depth(fdt, node);
	int32 examineNode = node;
	uint64 pathOffset = 0x0;

	while (depth > 0) {
		int len;
		const void* prop;
		prop = fdt_getprop(fdt, examineNode, "ranges", &len);
		if (prop) {
			int32 regAddressCells = 1;
			int32 regSizeCells = 1;
			fdt_get_cell_count(fdt, examineNode, regAddressCells, regSizeCells);

			const uint32 *p = (const uint32 *)prop;
			// All we are interested in is the start offset
			if (regAddressCells == 2)
				pathOffset = fdt64_to_cpu(*(uint64_t *)p);
			else
				pathOffset = fdt32_to_cpu(*(uint32_t *)p);
			break;
		}
		int32 parentNode = fdt_parent_offset(fdt, examineNode);
		depth = fdt_node_depth(fdt, parentNode);
		examineNode = parentNode;
	}

	TRACE("%s: range offset: 0x%" B_PRIx64 "\n", __func__, pathOffset);

	return pathOffset;
}
Example #15
0
static int fit_image_addr(const void *itb, int img, const char *name,
                          hwaddr *addr)
{
    const void *prop;
    int len;

    prop = fdt_getprop(itb, img, name, &len);
    if (!prop) {
        return -ENOENT;
    }

    switch (len) {
    case 4:
        *addr = fdt32_to_cpu(*(fdt32_t *)prop);
        return 0;
    case 8:
        *addr = fdt64_to_cpu(*(fdt64_t *)prop);
        return 0;
    default:
        error_printf("invalid %s address length %d\n", name, len);
        return -EINVAL;
    }
}
Example #16
0
File: bspsmp.c Project: AoLaD/rtems
static uint32_t discover_processors(void)
{
  const void *fdt = bsp_fdt_get();
  int cpus = fdt_path_offset(fdt, "/cpus");
  int node = fdt_first_subnode(fdt, cpus);
  uint32_t cpu = 0;

  while (node >= 0 && cpu < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr)) {
    int len;
    fdt64_t *addr_fdt = (fdt64_t *)
      fdt_getprop(fdt, node, "cpu-release-addr", &len);

    if (addr_fdt != NULL) {
      uintptr_t addr = (uintptr_t) fdt64_to_cpu(*addr_fdt);

      qoriq_start_spin_table_addr[cpu] = (qoriq_start_spin_table *) addr;
    }

    ++cpu;
    node = fdt_next_subnode(fdt, node);
  }

  return cpu * QORIQ_THREAD_COUNT;
}
Example #17
0
phys_addr_t
fdt_get_device_reg(const void* fdt, int node, bool physical)
{
	const void *prop = NULL;
	int len;
	uint64 baseDevice = 0x0;

	int32 regAddressCells = 1;
	int32 regSizeCells = 1;
	fdt_get_cell_count(fdt, node, regAddressCells, regSizeCells);

	// TODO: check for virtual-reg, and don't -= fdt_get_range_offset?

	// XXX: not sure #address-cells & #size-cells actually apply to virtual-reg
	if (!physical) {
		prop = fdt_getprop(fdt, node, "virtual-reg", &len);
		if (prop != NULL) {
			baseDevice = fdt32_to_cpu(*(uint32_t *)prop);
			return baseDevice;
		}
	}

	prop = fdt_getprop(fdt, node, "reg", &len);

	if (!prop) {
		dprintf("%s: reg property not found on node in FDT!\n", __func__);
		return 0;
	}

	const uint32 *p = (const uint32 *)prop;

	// soc base address cells
	if (regAddressCells == 2)
		baseDevice = fdt64_to_cpu(*(uint64_t *)p);
	else
		baseDevice = fdt32_to_cpu(*(uint32_t *)p);
	//p += regAddressCells;

	// subtract the range offset (X) on the parent node (ranges = X Y Z)
	baseDevice -= fdt_get_range_offset(fdt, node);

	// find the start of the parent (X) and add to base (regs = X Y)
	int parentNode = fdt_parent_offset(fdt, node);
	if (!parentNode)
		return baseDevice;

	fdt_get_cell_count(fdt, parentNode, regAddressCells, regSizeCells);
	prop = fdt_getprop(fdt, parentNode, "reg", &len);

	if (!prop)
		return baseDevice;
	p = (const uint32 *)prop;

	uint64 parentReg = 0x0;
	// soc base address cells
	if (regAddressCells == 2)
		parentReg = fdt64_to_cpu(*(uint64_t *)p);
	else
		parentReg = fdt32_to_cpu(*(uint32_t *)p);

	// add parent reg base to property
	baseDevice += parentReg;

	return baseDevice;
}
Example #18
0
void kexec_memory_map(void *fdt, int reserve_initrd)
{
	uint64_t start, size, end;
	int nodeoffset;
	int lpar = 0;

	kexec_map = simple_init();

	/* Work out if we are in LPAR mode */
	nodeoffset = fdt_path_offset(fdt, "/rtas");
	if (nodeoffset >= 0) {
		if (fdt_getprop(fdt, nodeoffset, "ibm,hypertas-functions", NULL))
			lpar = 1;
	}

	/* First find our memory */
	nodeoffset = fdt_path_offset(fdt, "/");
	if (nodeoffset < 0) {
		fprintf(stderr, "Device tree has no root node\n");
		exit(1);
	}

	while (1) {
		const char *type;
		int len;
		const fdt64_t *reg;

		nodeoffset = fdt_next_node(fdt, nodeoffset, NULL);
		if (nodeoffset < 0)
			break;

		type = fdt_getprop(fdt, nodeoffset, "device_type", NULL);

		if (!type || strcmp(type, "memory"))
			continue;

		reg = fdt_getprop(fdt, nodeoffset, "reg", &len);

		while (len) {
			start = fdt64_to_cpu(*reg++);
			size = fdt64_to_cpu(*reg++);
			len -= 2 * sizeof(uint64_t);

			if (lpar == 1) {
				/* Only use the RMA region for LPAR */
				if (start == 0) {
					if (size > MEMORY_CAP)
						size = MEMORY_CAP;
					simple_free(kexec_map, 0, size);
					mem_top = size;
				}
			} else {
				if (start >= MEMORY_CAP)
					continue;

				if ((start + size) > MEMORY_CAP)
					size = MEMORY_CAP - start;

				simple_free(kexec_map, start, size);

				if ((start + size) > mem_top)
					mem_top = start + size;
			}
		}
	}

	/* Reserve the kernel */
	nodeoffset = fdt_path_offset(fdt, "/chosen");
	if (nodeoffset < 0) {
		fprintf(stderr, "Device tree has no chosen node\n");
		exit(1);
	}

	/*
	 * XXX FIXME: Need to add linux,kernel-start property to the
	 * kernel to handle relocatable kernels.
	 */
	start = 0;
	if (getprop_u64(fdt, nodeoffset, "linux,kernel-end", &end)) {
		fprintf(stderr, "getprop linux,kernel-end failed\n");
		exit(1);
	}

	simple_alloc_at(kexec_map, start, end - start);

	/* Reserve the MMU hashtable in non LPAR mode */
	if (lpar == 0) {
		if (getprop_u64(fdt, nodeoffset, "linux,htab-base", &start) ||
		    getprop_u64(fdt, nodeoffset, "linux,htab-size", &size)) {
			fprintf(stderr, "Could not find linux,htab-base or "
				"linux,htab-size properties\n");
			exit(1);
		}

		if (start < mem_top)
			simple_alloc_at(kexec_map, start, size);
	}

	/* XXX FIXME: Reserve TCEs in kexec_map */

	if (new_style_reservation(fdt, reserve_initrd))
		return;

	/* Reserve the initrd if requested */
	if (reserve_initrd &&
            !getprop_u64(fdt, nodeoffset, "linux,initrd-start", &start) &&
	    !getprop_u64(fdt, nodeoffset, "linux,initrd-end", &end)) {

		if (start < mem_top)
			simple_alloc_at(kexec_map, start, end - start);
	}

	/* Reserve RTAS */
	nodeoffset = fdt_path_offset(fdt, "/rtas");
	if (nodeoffset > 0) {
		uint32_t rtas_start, rtas_size;

		if (getprop_u32(fdt, nodeoffset, "linux,rtas-base", &rtas_start)) {
			fprintf(stderr, "getprop linux,rtas-base failed\n");
			exit(1);
		}

		if (getprop_u32(fdt, nodeoffset, "rtas-size", &rtas_size)) {
			fprintf(stderr, "getprop rtas-size failed\n");
			exit(1);
		}

		simple_alloc_at(kexec_map, rtas_start, rtas_size);

		if (fdt_add_mem_rsv(fdt, rtas_start, rtas_size))
			perror("fdt_add_mem_rsv");
	}

	nodeoffset = fdt_path_offset(fdt, "/ibm,opal");
	if (nodeoffset > 0) {
		uint64_t opal_start, opal_size;

		if (getprop_u64(fdt, nodeoffset, "opal-base-address",
				&opal_start)) {
			fprintf(stderr, "getprop opal-base-address failed\n");
			exit(1);
		}

		if (getprop_u64(fdt, nodeoffset, "opal-runtime-size",
				&opal_size)) {
			fprintf(stderr, "getprop opal-runtime-size failed\n");
			exit(1);
		}

		simple_alloc_at(kexec_map, opal_start, opal_size);

		if (fdt_add_mem_rsv(fdt, opal_start, opal_size))
			perror("fdt_add_mem_rsv");
	}
}
Example #19
0
static int new_style_reservation(void *fdt, int reserve_initrd)
{
	int nodeoffset;
	const void *p;
	fdt64_t *ranges, *range;
	char *names, *name;
	int ranges_len, names_len;

	nodeoffset = fdt_path_offset(fdt, "/");
	if (nodeoffset < 0) {
		fprintf(stderr, "Device tree has no root node\n");
		exit(1);
	}

	p = fdt_getprop(fdt, nodeoffset, "reserved-ranges", &ranges_len);
	if (!p && ranges_len == -FDT_ERR_NOTFOUND)
		return 0;

	if (!p) {
		fprintf(stderr, "getprop reserved-ranges returned %d\n",
			ranges_len);
		exit(1);
	}

	ranges = malloc(ranges_len);
	if (!ranges) {
		perror("malloc");
		exit(1);
	}
	memcpy(ranges, p, ranges_len);

	p = fdt_getprop(fdt, nodeoffset, "reserved-names", &names_len);
	if (!p && names_len == -FDT_ERR_NOTFOUND)
		return 0;

	if (!p) {
		fprintf(stderr, "getprop reserved-names returned %d\n",
			names_len);
		exit(1);
	}

	names = malloc(names_len);
	if (!names) {
		perror("malloc");
		exit(1);
	}
	memcpy(names, p, names_len);

	name = names;
	range = ranges;
	while (ranges_len > 0 && names_len > 0) {
		uint64_t start, size;

		start = fdt64_to_cpu(*range++);
		size = fdt64_to_cpu(*range++);

#ifdef DEBUG
		printf("%s %lx %lx\n", name, start, size);
#endif

		if (!reserve_initrd && !strcmp(name, "linux,initramfs"))
			continue;

		simple_alloc_at(kexec_map, start, size);

		if (fdt_add_mem_rsv(fdt, start, size))
			perror("fdt_add_mem_rsv");

		ranges_len -= 2 * sizeof(uint64_t);
		names_len -= strlen(name) + 1;
		name += strlen(name) + 1;
	}

	free(ranges);
	free(names);

	return 1;
}
Example #20
0
/**
 * display_fdt_by_regions() - Display regions of an FDT source
 *
 * This dumps an FDT as source, but only certain regions of it. This is the
 * final stage of the grep - we have a list of regions we want to display,
 * and this function displays them.
 *
 * @disp:	Display structure, holding info about our options
 * @blob:	FDT blob to display
 * @region:	List of regions to display
 * @count:	Number of regions
 */
static int display_fdt_by_regions(struct display_info *disp, const void *blob,
		struct fdt_region region[], int count)
{
	struct fdt_region *reg = region, *reg_end = region + count;
	uint32_t off_mem_rsvmap = fdt_off_mem_rsvmap(blob);
	int base = fdt_off_dt_struct(blob);
	int version = fdt_version(blob);
	int offset, nextoffset;
	int tag, depth, shift;
	FILE *f = disp->fout;
	uint64_t addr, size;
	int in_region;
	int file_ofs;
	int i;

	if (disp->show_dts_version)
		fprintf(f, "/dts-v1/;\n");

	if (disp->header) {
		fprintf(f, "// magic:\t\t0x%x\n", fdt_magic(blob));
		fprintf(f, "// totalsize:\t\t0x%x (%d)\n", fdt_totalsize(blob),
			fdt_totalsize(blob));
		fprintf(f, "// off_dt_struct:\t0x%x\n",
			fdt_off_dt_struct(blob));
		fprintf(f, "// off_dt_strings:\t0x%x\n",
			fdt_off_dt_strings(blob));
		fprintf(f, "// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
		fprintf(f, "// version:\t\t%d\n", version);
		fprintf(f, "// last_comp_version:\t%d\n",
			fdt_last_comp_version(blob));
		if (version >= 2) {
			fprintf(f, "// boot_cpuid_phys:\t0x%x\n",
				fdt_boot_cpuid_phys(blob));
		}
		if (version >= 3) {
			fprintf(f, "// size_dt_strings:\t0x%x\n",
				fdt_size_dt_strings(blob));
		}
		if (version >= 17) {
			fprintf(f, "// size_dt_struct:\t0x%x\n",
				fdt_size_dt_struct(blob));
		}
		fprintf(f, "\n");
	}

	if (disp->flags & FDT_REG_ADD_MEM_RSVMAP) {
		const struct fdt_reserve_entry *p_rsvmap;

		p_rsvmap = (const struct fdt_reserve_entry *)
				((const char *)blob + off_mem_rsvmap);
		for (i = 0; ; i++) {
			addr = fdt64_to_cpu(p_rsvmap[i].address);
			size = fdt64_to_cpu(p_rsvmap[i].size);
			if (addr == 0 && size == 0)
				break;

			fprintf(f, "/memreserve/ %llx %llx;\n",
				(unsigned long long)addr,
				(unsigned long long)size);
		}
	}

	depth = 0;
	nextoffset = 0;
	shift = 4;	/* 4 spaces per indent */
	do {
		const struct fdt_property *prop;
		const char *name;
		int show;
		int len;

		offset = nextoffset;

		/*
		 * Work out the file offset of this offset, and decide
		 * whether it is in the region list or not
		 */
		file_ofs = base + offset;
		if (reg < reg_end && file_ofs >= reg->offset + reg->size)
			reg++;
		in_region = reg < reg_end && file_ofs >= reg->offset &&
				file_ofs < reg->offset + reg->size;
		tag = fdt_next_tag(blob, offset, &nextoffset);

		if (tag == FDT_END)
			break;
		show = in_region || disp->all;
		if (show && disp->diff)
			fprintf(f, "%c", in_region ? '+' : '-');

		if (!show) {
			/* Do this here to avoid 'if (show)' in every 'case' */
			if (tag == FDT_BEGIN_NODE)
				depth++;
			else if (tag == FDT_END_NODE)
				depth--;
			continue;
		}
		if (tag != FDT_END) {
			if (disp->show_addr)
				fprintf(f, "%4x: ", file_ofs);
			if (disp->show_offset)
				fprintf(f, "%4x: ", file_ofs - base);
		}

		/* Green means included, red means excluded */
		if (disp->colour)
			print_ansi_colour(f, in_region ? COL_GREEN : COL_RED);

		switch (tag) {
		case FDT_PROP:
			prop = fdt_get_property_by_offset(blob, offset, NULL);
			name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
			fprintf(f, "%*s%s", depth * shift, "", name);
			utilfdt_print_data(prop->data,
					   fdt32_to_cpu(prop->len));
			fprintf(f, ";");
			break;

		case FDT_NOP:
			fprintf(f, "%*s// [NOP]", depth * shift, "");
			break;

		case FDT_BEGIN_NODE:
			name = fdt_get_name(blob, offset, &len);
			fprintf(f, "%*s%s {", depth++ * shift, "",
				*name ? name : "/");
			break;

		case FDT_END_NODE:
			fprintf(f, "%*s};", --depth * shift, "");
			break;
		}

		/* Reset colour back to normal before end of line */
		if (disp->colour)
			print_ansi_colour(f, COL_NONE);
		fprintf(f, "\n");
	} while (1);

	/* Print a list of strings if requested */
	if (disp->list_strings) {
		const char *str;
		int str_base = fdt_off_dt_strings(blob);

		for (offset = 0; offset < fdt_size_dt_strings(blob);
				offset += strlen(str) + 1) {
			str = fdt_string(blob, offset);
			int len = strlen(str) + 1;
			int show;

			/* Only print strings that are in the region */
			file_ofs = str_base + offset;
			in_region = reg < reg_end &&
					file_ofs >= reg->offset &&
					file_ofs + len < reg->offset +
						reg->size;
			show = in_region || disp->all;
			if (show && disp->diff)
				printf("%c", in_region ? '+' : '-');
			if (disp->show_addr)
				printf("%4x: ", file_ofs);
			if (disp->show_offset)
				printf("%4x: ", offset);
			printf("%s\n", str);
		}
	}

	return 0;
}
Example #21
0
/*
 * fdt_get_reg - Fill buffer by information from DT
 */
static phys_size_t fdt_get_reg(const void *fdt, int nodeoffset, void *buf,
			       const u32 *cell, int n)
{
	int i = 0, b, banks;
	int parent_offset = fdt_parent_offset(fdt, nodeoffset);
	int address_cells = fdt_address_cells(fdt, parent_offset);
	int size_cells = fdt_size_cells(fdt, parent_offset);
	char *p = buf;
	phys_addr_t val;
	phys_size_t vals;

	debug("%s: addr_cells=%x, size_cell=%x, buf=%p, cell=%p\n",
	      __func__, address_cells, size_cells, buf, cell);

	/* Check memory bank setup */
	banks = n % (address_cells + size_cells);
	if (banks)
		panic("Incorrect memory setup cells=%d, ac=%d, sc=%d\n",
		      n, address_cells, size_cells);

	banks = n / (address_cells + size_cells);

	for (b = 0; b < banks; b++) {
		debug("%s: Bank #%d:\n", __func__, b);
		if (address_cells == 2) {
			val = cell[i + 1];
			val <<= 32;
			val |= cell[i];
			val = fdt64_to_cpu(val);
			debug("%s: addr64=%llx, ptr=%p, cell=%p\n",
			      __func__, val, p, &cell[i]);
			*(phys_addr_t *)p = val;
		} else {
			debug("%s: addr32=%x, ptr=%p\n",
			      __func__, fdt32_to_cpu(cell[i]), p);
			*(phys_addr_t *)p = fdt32_to_cpu(cell[i]);
		}
		p += sizeof(phys_addr_t);
		i += address_cells;

		debug("%s: pa=%p, i=%x, size=%zu\n", __func__, p, i,
		      sizeof(phys_addr_t));

		if (size_cells == 2) {
			vals = cell[i + 1];
			vals <<= 32;
			vals |= cell[i];
			vals = fdt64_to_cpu(vals);

			debug("%s: size64=%llx, ptr=%p, cell=%p\n",
			      __func__, vals, p, &cell[i]);
			*(phys_size_t *)p = vals;
		} else {
			debug("%s: size32=%x, ptr=%p\n",
			      __func__, fdt32_to_cpu(cell[i]), p);
			*(phys_size_t *)p = fdt32_to_cpu(cell[i]);
		}
		p += sizeof(phys_size_t);
		i += size_cells;

		debug("%s: ps=%p, i=%x, size=%zu\n",
		      __func__, p, i, sizeof(phys_size_t));
	}

	/* Return the first address size */
	return *(phys_size_t *)((char *)buf + sizeof(phys_addr_t));
}
Example #22
0
void dt_platform_init_fdt(void *fdt)
{
    int rv;
    system_fdt = fdt;

    printf("fdt_platform_init %p\n", fdt);

    // Check header
    if ((rv = fdt_check_header(fdt))) {
        panic("Bad FDT: %s\n", fdt_strerror(rv));
    }

    // Process memory reservations
    printf("rsv %p\n", fdt);
    int num_rsv = fdt_num_mem_rsv(fdt);
    for (int i = 0; i < num_rsv; i++) {
        printf("get\n");
        gd_memory_map_entry ent;
        ent.type = gd_reserved_memory_type;
        ent.attributes = 0;
        fdt_get_mem_rsv(fdt, i, &ent.physical_start, &ent.size);
        printf("got\n");
        ent.virtual_start = ent.physical_start;

        printf("Adding reserved memory region: %" PRIX64 " len=%" PRIX64 "\n",
            ent.physical_start, ent.size);

        mmap_add_entry(ent);
    }

    // Process root note memory entries
    printf("root\n");
    int root = fdt_next_node(fdt, -1, NULL);

    unsigned addr_cells = fdt_address_cells(fdt, root);
    unsigned size_cells = fdt_size_cells(fdt, root);
    unsigned cells      = addr_cells + size_cells;

    int mem_offs = fdt_subnode_offset(fdt, root, "memory");
    if (mem_offs < 0) {
        panic("Unable to locate memory node (%s)\n", fdt_strerror(mem_offs));
    }

    int memlen;
    const uint32_t *p = fdt_getprop(system_fdt, mem_offs, "reg", &memlen);
    for (int i = 0; i < memlen / 4; i+= cells) {
        uint64_t base_addr = 0, base_size = 0;
        if (addr_cells == 1) {
            base_addr = fdt32_to_cpu(p[i]);
        } else if (addr_cells == 2) {
            base_addr = fdt64_to_cpu(((uint64_t) p[i + 1]) << 32 | p[i]);
        }

        if (size_cells == 1) {
            base_size = fdt32_to_cpu(p[i + addr_cells]);
        } else if (size_cells == 2) {
            base_size = fdt64_to_cpu(((uint64_t) p[i + addr_cells + 1]) << 32
            | p[i + addr_cells]);
        }

        printf("Adding memory range %16" PRIX64 " len %16" PRIX64 "\n",
            base_addr, base_size);

        gd_memory_map_entry ent = { 0 };
        ent.type       = gd_conventional_memory;
        ent.attributes = 0;
        ent.virtual_start = ent.physical_start = base_addr;
        ent.size = base_size;
        mmap_add_entry(ent);
    }

    dt_root = add_device_fdt(NULL, fdt, root, 0);
}
Example #23
0
/**
  Initialize the system (or sometimes called permanent) memory

  This memory is generally represented by the DRAM.

  This function is called from InitializeMemory() in MemoryInitPeim, in the PEI
  phase.
**/
VOID
ArmPlatformInitializeSystemMemory (
  VOID
  )
{
  VOID         *DeviceTreeBase;
  INT32        Node, Prev;
  UINT64       NewBase;
  UINT64       NewSize;
  CONST CHAR8  *Type;
  INT32        Len;
  CONST UINT64 *RegProp;

  NewBase = 0;
  NewSize = 0;

  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
  ASSERT (DeviceTreeBase != NULL);

  //
  // Make sure we have a valid device tree blob
  //
  ASSERT (fdt_check_header (DeviceTreeBase) == 0);

  //
  // Look for a memory node
  //
  for (Prev = 0;; Prev = Node) {
    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
    if (Node < 0) {
      break;
    }

    //
    // Check for memory node
    //
    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
      //
      // Get the 'reg' property of this node. For now, we will assume
      // two 8 byte quantities for base and size, respectively.
      //
      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {

        NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
        NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));

        //
        // Make sure the start of DRAM matches our expectation
        //
        ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase);
        PcdSet64 (PcdSystemMemorySize, NewSize);

        DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n",
               __FUNCTION__, NewBase, NewBase + NewSize - 1));
      } else {
        DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n",
               __FUNCTION__));
      }
      break;
    }
  }

  //
  // We need to make sure that the machine we are running on has at least
  // 128 MB of memory configured, and is currently executing this binary from
  // NOR flash. This prevents a device tree image in DRAM from getting
  // clobbered when our caller installs permanent PEI RAM, before we have a
  // chance of marking its location as reserved or copy it to a freshly
  // allocated block in the permanent PEI RAM in the platform PEIM.
  //
  ASSERT (NewSize >= SIZE_128MB);
  ASSERT (
    (((UINT64)PcdGet64 (PcdFdBaseAddress) +
      (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) ||
    ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize)));
}
STATIC
UINT64
SerialPortGetBaseAddress (
  VOID
  )
{
  UINT64              BaudRate;
  UINT32              ReceiveFifoDepth;
  EFI_PARITY_TYPE     Parity;
  UINT8               DataBits;
  EFI_STOP_BITS_TYPE  StopBits;
  VOID                *DeviceTreeBase;
  INT32               Node, Prev;
  INT32               Len;
  CONST CHAR8         *Compatible;
  CONST CHAR8         *NodeStatus;
  CONST CHAR8         *CompatibleItem;
  CONST UINT64        *RegProperty;
  UINTN               UartBase;
  RETURN_STATUS       Status;

  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);

  if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) {
    return 0;
  }

  //
  // Enumerate all FDT nodes looking for a PL011 and capture its base address
  //
  for (Prev = 0;; Prev = Node) {
    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
    if (Node < 0) {
      break;
    }

    Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
    if (Compatible == NULL) {
      continue;
    }

    //
    // Iterate over the NULL-separated items in the compatible string
    //
    for (CompatibleItem = Compatible; CompatibleItem < Compatible + Len;
      CompatibleItem += 1 + AsciiStrLen (CompatibleItem)) {

      if (AsciiStrCmp (CompatibleItem, "arm,pl011") == 0) {
        NodeStatus = fdt_getprop (DeviceTreeBase, Node, "status", &Len);
        if (NodeStatus != NULL && AsciiStrCmp (NodeStatus, "okay") != 0) {
          continue;
        }

        RegProperty = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
        if (Len != 16) {
          return 0;
        }
        UartBase = (UINTN)fdt64_to_cpu (ReadUnaligned64 (RegProperty));

        BaudRate = (UINTN)FixedPcdGet64 (PcdUartDefaultBaudRate);
        ReceiveFifoDepth = 0; // Use the default value for Fifo depth
        Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
        DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
        StopBits = (EFI_STOP_BITS_TYPE) FixedPcdGet8 (PcdUartDefaultStopBits);

        Status = PL011UartInitializePort (
                   UartBase,
                   FixedPcdGet32 (PL011UartClkInHz),
                   &BaudRate,
                   &ReceiveFifoDepth,
                   &Parity,
                   &DataBits,
                   &StopBits
                   );
        if (!EFI_ERROR (Status)) {
          return UartBase;
        }
      }
    }
  }
  return 0;
}
Example #25
0
static void dump_blob(void *blob)
{
	struct fdt_header *bph = blob;
	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
	struct fdt_reserve_entry *p_rsvmap =
		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
	const char *p_struct = (const char *)blob + off_dt;
	const char *p_strings = (const char *)blob + off_str;
	uint32_t version = fdt32_to_cpu(bph->version);
	uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
	uint32_t tag;
	const char *p, *s, *t;
	int depth, sz, shift;
	int i;
	uint64_t addr, size;

	depth = 0;
	shift = 4;

	printf("/dts-v1/;\n");
	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
	printf("// off_dt_struct:\t0x%x\n", off_dt);
	printf("// off_dt_strings:\t0x%x\n", off_str);
	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
	printf("// version:\t\t%d\n", version);
	printf("// last_comp_version:\t%d\n",
	       fdt32_to_cpu(bph->last_comp_version));
	if (version >= 2)
		printf("// boot_cpuid_phys:\t0x%x\n",
		       fdt32_to_cpu(bph->boot_cpuid_phys));

	if (version >= 3)
		printf("// size_dt_strings:\t0x%x\n",
		       fdt32_to_cpu(bph->size_dt_strings));
	if (version >= 17)
		printf("// size_dt_struct:\t0x%x\n",
		       fdt32_to_cpu(bph->size_dt_struct));
	printf("\n");

	for (i = 0; ; i++) {
		addr = fdt64_to_cpu(p_rsvmap[i].address);
		size = fdt64_to_cpu(p_rsvmap[i].size);
		if (addr == 0 && size == 0)
			break;

		printf("/memreserve/ %llx %llx;\n",
		       (unsigned long long)addr, (unsigned long long)size);
	}

	p = p_struct;
	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {

		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */

		if (tag == FDT_BEGIN_NODE) {
			s = p;
			p = PALIGN(p + strlen(s) + 1, 4);

			if (*s == '\0')
				s = "/";

			printf("%*s%s {\n", depth * shift, "", s);

			depth++;
			continue;
		}

		if (tag == FDT_END_NODE) {
			depth--;

			printf("%*s};\n", depth * shift, "");
			continue;
		}

		if (tag == FDT_NOP) {
			printf("%*s// [NOP]\n", depth * shift, "");
			continue;
		}

		if (tag != FDT_PROP) {
			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
			break;
		}
		sz = fdt32_to_cpu(GET_CELL(p));
		s = p_strings + fdt32_to_cpu(GET_CELL(p));
		if (version < 16 && sz >= 8)
			p = PALIGN(p, 8);
		t = p;

		p = PALIGN(p + sz, 4);

		printf("%*s%s", depth * shift, "", s);
		print_data(t, sz);
		printf(";\n");
	}
}
Example #26
0
static void dump_blob(void *blob, bool debug)
{
	uintptr_t blob_off = (uintptr_t)blob;
	struct fdt_header *bph = blob;
	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
	struct fdt_reserve_entry *p_rsvmap =
		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
	const char *p_struct = (const char *)blob + off_dt;
	/* Get offset to the strings */
	const char *p_strings = (const char *)blob + off_str;
	uint32_t version = fdt32_to_cpu(bph->version);
	uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
	uint32_t tag;
	const char *p, *s, *t;
	int depth, sz, shift;
	int i;
	uint64_t addr, size;

	char *buffer;
	buffer = (char *)malloc(MAX_LEN);

	depth = 0;
	shift = 4;

	uint32_t off_total_size = fdt32_to_cpu(bph->totalsize);

	/* TODO: Remove this additional info. Do I need it? */

	dprintf(buffer, "totalsize: %d\n", off_total_size);

	dprintf(buffer, "// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
	dprintf(buffer, "// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
	dprintf(buffer, "// off_dt_struct:\t0x%x\n", off_dt);
	dprintf(buffer, "// off_dt_strings:\t0x%x\n", off_str);
	dprintf(buffer, "// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
	dprintf(buffer, "// version:\t\t%d\n", version);
	dprintf(buffer, "// last_comp_version:\t%d\n",
	       fdt32_to_cpu(bph->last_comp_version));
	if (version >= 2)	
		dprintf(buffer, "// boot_cpuid_phys:\t0x%x\n",
		       fdt32_to_cpu(bph->boot_cpuid_phys));

	if (version >= 3)
		dprintf(buffer, "// size_dt_strings:\t0x%x\n",
		       fdt32_to_cpu(bph->size_dt_strings));
	if (version >= 17)
		dprintf(buffer, "// size_dt_struct:\t0x%x\n",
		       fdt32_to_cpu(bph->size_dt_struct));
	dprintf(buffer, "\n");

	for (i = 0; ; i++) {
		addr = fdt64_to_cpu(p_rsvmap[i].address);
		size = fdt64_to_cpu(p_rsvmap[i].size);
		if (addr == 0 && size == 0)
			break;

		dprintf(buffer, "/memreserve/ %#llx %#llx;\n",
		       (unsigned long long)addr, (unsigned long long)size);
	}

	p = p_struct;
	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
		dumpf("%04zx: tag: 0x%08x (%s)\n",
		        (uintptr_t)p - blob_off - 4, tag, tagname(tag));

		if (tag == FDT_BEGIN_NODE) {
			s = p;
			p = PALIGN(p + strlen(s) + 1, 4);

			if (*s == '\0')
				s = "/";

			dprintf(buffer, "%*s%s {\n", depth * shift, "", s);

			depth++;
			continue;
		}

		if (tag == FDT_END_NODE) {
			depth--;

			dprintf(buffer, "%*s};\n", depth * shift, "");
			continue;
		}

		if (tag == FDT_NOP) {
			dprintf(buffer, "%*s// [NOP]\n", depth * shift, "");
			continue;
		}

		if (tag != FDT_PROP) {
			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
			break;
		}
		/* sz - length of the returned values in bytes */
		sz = fdt32_to_cpu(GET_CELL(p));
		/* s - pointer to the property name */
		s = p_strings + fdt32_to_cpu(GET_CELL(p));
		if (version < 16 && sz >= 8)
			p = PALIGN(p, 8);
		t = p;

		p = PALIGN(p + sz, 4);

		dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
		dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
		dprintf(buffer, "%*s%s", depth * shift, "", s);
		my_utilfdt_print_data(t, sz, buffer);
		dprintf(buffer, ";\n");
	}
		printf("%s", buffer);
}