Esempio n. 1
0
int fdt_get_resource(const void *fdt, int node, const char *property,
		     unsigned int index, struct fdt_resource *res)
{
	const fdt32_t *ptr, *end;
	int na, ns, len, parent;
	unsigned int i = 0;

	parent = fdt_parent_offset(fdt, node);
	if (parent < 0)
		return parent;

	na = fdt_address_cells(fdt, parent);
	ns = fdt_size_cells(fdt, parent);

	ptr = fdt_getprop(fdt, node, property, &len);
	if (!ptr)
		return len;

	end = ptr + len / sizeof(*ptr);

	while (ptr + na + ns <= end) {
		if (i == index) {
			res->start = res->end = fdtdec_get_number(ptr, na);
			res->end += fdtdec_get_number(&ptr[na], ns) - 1;
			return 0;
		}

		ptr += na + ns;
		i++;
	}

	return -FDT_ERR_NOTFOUND;
}
Esempio n. 2
0
fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
		int node, const char *prop_name, int index, fdt_size_t *sizep,
		bool translate)
{
	int na, ns;

	debug("%s: ", __func__);

	na = fdt_address_cells(blob, parent);
	if (na < 1) {
		debug("(bad #address-cells)\n");
		return FDT_ADDR_T_NONE;
	}

	ns = fdt_size_cells(blob, parent);
	if (ns < 0) {
		debug("(bad #size-cells)\n");
		return FDT_ADDR_T_NONE;
	}

	debug("na=%d, ns=%d, ", na, ns);

	return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na,
					  ns, sizep, translate);
}
Esempio n. 3
0
fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
		const char *prop_name, fdt_size_t *sizep)
{
	const fdt32_t *ptr, *end;
	int parent, na, ns, len;
	fdt_addr_t addr;

	debug("%s: %s: ", __func__, prop_name);

	parent = fdt_parent_offset(blob, node);
	if (parent < 0) {
		debug("(no parent found)\n");
		return FDT_ADDR_T_NONE;
	}

	na = fdt_address_cells(blob, parent);
	ns = fdt_size_cells(blob, parent);

	ptr = fdt_getprop(blob, node, prop_name, &len);
	if (!ptr) {
		debug("(not found)\n");
		return FDT_ADDR_T_NONE;
	}

	end = ptr + len / sizeof(*ptr);

	if (ptr + na + ns > end) {
		debug("(not enough data: expected %d bytes, got %d bytes)\n",
		      (na + ns) * 4, len);
		return FDT_ADDR_T_NONE;
	}

	addr = fdtdec_get_number(ptr, na);

	if (sizep) {
		*sizep = fdtdec_get_number(ptr + na, ns);
		debug("addr=%pa, size=%pa\n", &addr, sizep);
	} else {
		debug("%pa\n", &addr);
	}

	return addr;
}
Esempio n. 4
0
/*
 * fdt_pack_reg - pack address and size array into the "reg"-suitable stream
 */
static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
			int n)
{
	int i;
	int address_cells = fdt_address_cells(fdt, 0);
	int size_cells = fdt_size_cells(fdt, 0);
	char *p = buf;

	for (i = 0; i < n; i++) {
		if (address_cells == 2)
			*(fdt64_t *)p = cpu_to_fdt64(address[i]);
		else
			*(fdt32_t *)p = cpu_to_fdt32(address[i]);
		p += 4 * address_cells;

		if (size_cells == 2)
			*(fdt64_t *)p = cpu_to_fdt64(size[i]);
		else
			*(fdt32_t *)p = cpu_to_fdt32(size[i]);
		p += 4 * size_cells;
	}

	return p - (char *)buf;
}
Esempio n. 5
0
ssize_t _fdt_reg_size(const void *fdt, int offs)
{
	const uint32_t *reg;
	uint32_t sz;
	int n;
	int len;
	int parent;

	parent = fdt_parent_offset(fdt, offs);
	if (parent < 0)
		return (paddr_t)-1;

	reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len);
	if (!reg)
		return -1;

	n = fdt_address_cells(fdt, parent);
	if (n < 1 || n > 2)
		return -1;

	reg += n;

	n = fdt_size_cells(fdt, parent);
	if (n < 1 || n > 2)
		return -1;

	sz = fdt32_to_cpu(*reg);
	if (n == 2) {
		if (sz)
			return -1;
		reg++;
		sz = fdt32_to_cpu(*reg);
	}

	return sz;
}
Esempio n. 6
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));
}
Esempio n. 7
0
static void load_ranges(const char *dtb)
{
	// First iterate through to count the total number of simple-bus
	//  items
	int soc = fdt_node_offset_by_compatible(dtb, -1, "simple-bus");
	sr_items = 0;
	while(soc != -FDT_ERR_NOTFOUND)
	{
		int ac = fdt_address_cells(dtb, soc);
		int sc = fdt_size_cells(dtb, soc);
		int ranges_plen;
		const void *ranges = fdt_getprop(dtb, soc, "ranges", &ranges_plen);
		if(ranges)
			sr_items += ranges_plen / ((2 * ac + sc) * 4);
		soc = fdt_node_offset_by_compatible(dtb, soc, "simple-bus");
	}

	if(sr)
		free(sr);
	sr = (struct soc_range *)malloc(sr_items * sizeof(struct soc_range));

	// Now re-iterate to get the actual values
	int cur_sr_item = 0;
	soc = fdt_node_offset_by_compatible(dtb, -1, "simple-bus");
	while(soc != -FDT_ERR_NOTFOUND)
	{
		int ac = fdt_address_cells(dtb, soc);
		int sc = fdt_size_cells(dtb, soc);
		int ranges_plen;
		const void *ranges = fdt_getprop(dtb, soc, "ranges", &ranges_plen);
		if(ranges)
		{
#ifdef DEBUG	
			printf("DTB: soc %i, ac %i, sc %i, plen %i\n", soc, ac, sc, ranges_plen);
#endif

			int num_ranges = ranges_plen / ((2 * ac + sc) * 4);

			int offset = 0;
			// if more than one 4-byte word is specified for address
			// we take the last one only (DTB is big-endian)
			for(int i = 0; i < num_ranges; i++, cur_sr_item++)
			{
				uint32_t cur_child = 0;
				uint32_t cur_parent = 0;
				uint32_t cur_len = 0;
				for(int j = 0; j < ac; j++)
				{
					cur_child = read_wordbe(ranges, offset);
					offset += 4;
				}
				for(int j = 0; j < ac; j++)
				{
					cur_parent = read_wordbe(ranges, offset);
					offset += 4;
				}
				for(int j = 0; j < sc; j++)
				{
					cur_len = read_wordbe(ranges, offset);
					offset += 4;
				}

#ifdef DEBUG
				printf("DTB: ranges: child: %x, parent: %x; len: %x\n",
					cur_child, cur_parent, cur_len);
#endif

				sr[cur_sr_item].soc_node = soc;
				sr[cur_sr_item].child_addr = cur_child;
				sr[cur_sr_item].parent_addr = cur_parent;
				sr[cur_sr_item].length = cur_len;
			}
		}
		soc = fdt_node_offset_by_compatible(dtb, soc, "simple-bus");
	}
}
Esempio n. 8
0
int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id,
			   phys_addr_t *basep, phys_size_t *sizep, bd_t *bd)
{
	int addr_cells, size_cells;
	const u32 *cell, *end;
	u64 total_size, size, addr;
	int node, child;
	bool auto_size;
	int bank;
	int len;

	debug("%s: board_id=%d\n", __func__, board_id);
	if (!area)
		area = "/memory";
	node = fdt_path_offset(blob, area);
	if (node < 0) {
		debug("No %s node found\n", area);
		return -ENOENT;
	}

	cell = fdt_getprop(blob, node, "reg", &len);
	if (!cell) {
		debug("No reg property found\n");
		return -ENOENT;
	}

	addr_cells = fdt_address_cells(blob, node);
	size_cells = fdt_size_cells(blob, node);

	/* Check the board id and mask */
	for (child = fdt_first_subnode(blob, node);
	     child >= 0;
	     child = fdt_next_subnode(blob, child)) {
		int match_mask, match_value;

		match_mask = fdtdec_get_int(blob, child, "match-mask", -1);
		match_value = fdtdec_get_int(blob, child, "match-value", -1);

		if (match_value >= 0 &&
		    ((board_id & match_mask) == match_value)) {
			/* Found matching mask */
			debug("Found matching mask %d\n", match_mask);
			node = child;
			cell = fdt_getprop(blob, node, "reg", &len);
			if (!cell) {
				debug("No memory-banks property found\n");
				return -EINVAL;
			}
			break;
		}
	}
	/* Note: if no matching subnode was found we use the parent node */

	if (bd) {
		memset(bd->bi_dram, '\0', sizeof(bd->bi_dram[0]) *
						CONFIG_NR_DRAM_BANKS);
	}

	auto_size = fdtdec_get_bool(blob, node, "auto-size");

	total_size = 0;
	end = cell + len / 4 - addr_cells - size_cells;
	debug("cell at %p, end %p\n", cell, end);
	for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
		if (cell > end)
			break;
		addr = 0;
		if (addr_cells == 2)
			addr += (u64)fdt32_to_cpu(*cell++) << 32UL;
		addr += fdt32_to_cpu(*cell++);
		if (bd)
			bd->bi_dram[bank].start = addr;
		if (basep && !bank)
			*basep = (phys_addr_t)addr;

		size = 0;
		if (size_cells == 2)
			size += (u64)fdt32_to_cpu(*cell++) << 32UL;
		size += fdt32_to_cpu(*cell++);

		if (auto_size) {
			u64 new_size;

			debug("Auto-sizing %llx, size %llx: ", addr, size);
			new_size = get_ram_size((long *)(uintptr_t)addr, size);
			if (new_size == size) {
				debug("OK\n");
			} else {
				debug("sized to %llx\n", new_size);
				size = new_size;
			}
		}

		if (bd)
			bd->bi_dram[bank].size = size;
		total_size += size;
	}

	debug("Memory size %llu\n", total_size);
	if (sizep)
		*sizep = (phys_size_t)total_size;

	return 0;
}
Esempio n. 9
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);
}
Esempio n. 10
0
//__attribute__((no_sanitize("all")))
void kernel_start(uintptr_t magic, uintptr_t addrin)
{
  kprintf("Magic %zx addrin %zx\n",magic,addrin);

  __init_sanity_checks();

  cpu_print_current_el();
  //its a "RAM address 0"
  const struct fdt_property *prop;
  int addr_cells = 0, size_cells = 0;
  int proplen;

  //TODO find this somewhere ?.. although it is at memory 0x00
  uint64_t fdt_addr=0x40000000;
  char *fdt=(char*)fdt_addr;


  //OK so these get overidden in the for loop which should return a map of memory and not just a single one
  uint64_t addr = 0;
  uint64_t size = 0;

  //checks both magic and version
  if ( fdt_check_header(fdt) != 0 )
  {
    kprint("FDT Header check failed\r\n");
    return;
  }

  size_cells = fdt_size_cells(fdt,0);
  print_le_named32("size_cells :",(char *)&size_cells);
  addr_cells = fdt_address_cells(fdt, 0);//fdt32_ld((const fdt32_t *)prop->data);
  print_le_named32("addr_cells :",(char *)&addr_cells);

  const int mem_offset = fdt_path_offset(fdt, "/memory");
  if (mem_offset < 0)
    return;

  print_le_named32("mem_offset :",(char *)&mem_offset);

  prop = fdt_get_property(fdt, mem_offset, "reg", &proplen);
  int cellslen = (int)sizeof(uint32_t) * (addr_cells + size_cells);

  for (int i = 0; i < proplen / cellslen; ++i) {

  	for (int j = 0; j < addr_cells; ++j) {
  		int offset = (cellslen * i) + (sizeof(uint32_t) * j);

  		addr |= (uint64_t)fdt32_ld((const fdt32_t *)((char *)prop->data + offset)) <<
  			((addr_cells - j - 1) * 32);
  	}
  	for (int j = 0; j < size_cells; ++j) {
  		int offset = (cellslen * i) +
  			(sizeof(uint32_t) * (j + addr_cells));

  		size |= (uint64_t)fdt32_ld((const fdt32_t *)((char *)prop->data + offset)) <<
  			((size_cells - j - 1) * 32);
  	}
	}

  print_le_named64("RAM BASE :",(char *)&addr);
  print_le_named64("RAM SIZE :",(char *)&size);

  uint64_t mem_end=addr+size;

  extern char _end;
  uintptr_t free_mem_begin = reinterpret_cast<uintptr_t>(&_end);

    //ok now its sane
  free_mem_begin += _move_symbols(free_mem_begin);

  // Initialize .bss
  _init_bss();

  // Instantiate machine
  size_t memsize = mem_end - free_mem_begin;
  __machine = os::Machine::create((void*)free_mem_begin, memsize);

  _init_elf_parser();
  // Begin portable HAL initialization
  __machine->init();

  // Initialize system calls
  _init_syscalls();

  //probably not very sane!
  cpu_debug_enable();
  cpu_fiq_enable();
  cpu_irq_enable();
  cpu_serror_enable();

  aarch64::init_libc((uintptr_t)fdt_addr);

}