#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/bus.h>
-#include <sys/cons.h>
+ #include <sys/cons.h>
#include <sys/cpu.h>
#include <sys/efi.h>
#include <sys/exec.h>
#ifdef FDT
#include <dev/fdt/fdt_common.h>
+#include <libfdt.h>
#include <dev/ofw/openfirm.h>
#endif
uint32_t memstart[LBABI_MAX_BANKS];
uint32_t memsize[LBABI_MAX_BANKS];
uint32_t membanks;
+
#endif
static uint32_t board_revision;
* Fake up a boot descriptor table
*/
vm_offset_t
-fake_preload_metadata(struct arm_boot_params *abp __unused)
+fake_preload_metadata(struct arm_boot_params *abp __unused,
+ vm_offset_t fdt_addr)
{
#ifdef DDB
vm_offset_t zstart = 0, zend = 0;
#endif
vm_offset_t lastaddr;
int i = 0;
- static uint32_t fake_preload[35];
+ static uint32_t fake_preload[38];
fake_preload[i++] = MODINFO_NAME;
fake_preload[i++] = strlen("kernel") + 1;
fake_preload[i++] = MODINFO_SIZE;
fake_preload[i++] = sizeof(uint32_t);
fake_preload[i++] = (uint32_t)&end - KERNVIRTADDR;
+ fake_preload[i++] = MODINFOMD_DTBP | MODINFO_METADATA;
+ fake_preload[i++] = sizeof(vm_offset_t);
+ fake_preload[i++] = fdt_addr;
#ifdef DDB
if (*(uint32_t *)KERNVIRTADDR == MAGIC_TRAMP_NUMBER) {
fake_preload[i++] = MODINFO_METADATA|MODINFOMD_SSYM;
vm_offset_t
linux_parse_boot_param(struct arm_boot_params *abp)
{
+ void *ptr;
struct arm_lbabi_tag *walker;
uint32_t revision;
uint64_t serial;
return 0;
board_id = abp->abp_r1;
- walker = (struct arm_lbabi_tag *)
- (abp->abp_r2 + KERNVIRTADDR - abp->abp_physaddr);
+ ptr = (void *)(abp->abp_r2 + KERNVIRTADDR - abp->abp_physaddr);
+
+#ifdef FDT
+ if (!fdt_check_header(ptr))
+ return fake_preload_metadata(abp, (vm_offset_t)ptr);
+#endif
+
+ walker = ptr;
- /* xxx - Need to also look for binary device tree */
if (ATAG_TAG(walker) != ATAG_CORE)
return 0;
bcopy(atag_list, atags,
(char *)walker - (char *)atag_list + ATAG_SIZE(walker));
- return fake_preload_metadata(abp);
+ return fake_preload_metadata(abp, 0);
}
#endif
return lastaddr;
#endif
/* Fall back to hardcoded metadata. */
- lastaddr = fake_preload_metadata(abp);
+ lastaddr = fake_preload_metadata(abp, 0);
return lastaddr;
}
struct mem_region mem_regions[FDT_MEM_REGIONS];
struct pv_addr kernel_l1pt;
struct pv_addr dpcpu;
+ struct pv_addr fdtpage;
vm_offset_t dtbp, freemempos, l2_start, lastaddr;
uint32_t memsize, l2size;
char *env;
void *kmdp;
u_int l1pagetable;
int i, j, err_devmap, mem_regions_sz;
+ vm_paddr_t fdt_paddr;
+ vm_size_t fdt_size;
lastaddr = parse_boot_param(abp);
arm_physmem_kernaddr = abp->abp_physaddr;
if (OF_init((void *)dtbp) != 0)
panic("OF_init failed with the found device tree");
+ /* Get the physical address of the device tree. This will be used
+ * later to correctly map the FDT in virtual memory when Linux boot
+ * ABI loader is used
+ */
+ fdt_paddr = (dtbp - KERNVIRTADDR + abp->abp_physaddr);
+ fdt_size = fdt_totalsize(dtbp);
+
/* Grab physical memory regions information from device tree. */
if (fdt_get_mem_regions(mem_regions, &mem_regions_sz, &memsize) != 0)
panic("Cannot get physical memory regions");
arm_physmem_exclude_regions(mem_regions, mem_regions_sz,
EXFLAG_NODUMP | EXFLAG_NOALLOC);
+ /* TODO: get correctly the DTB size */
+ arm_physmem_exclude_region(fdt_paddr, fdt_size,
+ EXFLAG_NODUMP | EXFLAG_NOALLOC);
+
/* Platform-specific initialisation */
platform_probe_and_attach();
valloc_pages(kernelstack, kstack_pages * MAXCPU);
valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE);
+ /* Allocate virtual address for the device tree */
+ fdt_size = round_page(fdt_size + fdt_paddr & PAGE_MASK);
+ valloc_pages(fdtpage, fdt_size >> PAGE_SHIFT);
+ fdtpage.pv_pa = trunc_page(fdt_paddr);
+
/*
* Now we start construction of the L1 page table
* We start by mapping the L2 page tables into the L1.
pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE, PTE_CACHE);
+ /* Map the DTB */
+ pmap_map_entry(l1pagetable, fdtpage.pv_va, fdtpage.pv_pa,
+ VM_PROT_READ, PTE_CACHE);
+
/* Establish static device mappings. */
err_devmap = platform_devmap_init();
arm_devmap_bootstrap(l1pagetable, NULL);
cpu_tlb_flushID();
cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2));
+ /* We need to reinitalize OF subsystem to system the new DTB pointer */
+ /* TODO: Find a nicer way... */
+ dtbp = fdtpage.pv_va + (fdt_paddr - fdtpage.pv_pa);
+ if (OF_init((void *)dtbp) != 0)
+ panic("OF_init failed to update the DTB virtual address");
+
/*
* Now that proper page tables are installed, call cpu_setup() to enable
* instruction and data caches and other chip-specific features.