Date: Sat, 26 Mar 2016 06:55:55 +0000 (UTC) From: Michal Meloun <mmel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297284 - in head/sys/arm: arm at91 conf include Message-ID: <201603260655.u2Q6ttWj077457@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mmel Date: Sat Mar 26 06:55:55 2016 New Revision: 297284 URL: https://svnweb.freebsd.org/changeset/base/297284 Log: ARM: Teach LINUX_BOOT_ABI to recognize DT blob. This allow us to boot FreeBSD kernel (using uImage encapsulation) directly from U-boot using 'bootm' command or by Android fastboot loader. For now, kernel uImage must be marked as Linux, but we can add support for FreeBSD into U-Boot later. Modified: head/sys/arm/arm/machdep.c head/sys/arm/at91/board_tsc4370.c head/sys/arm/conf/TEGRA124 head/sys/arm/include/machdep.h Modified: head/sys/arm/arm/machdep.c ============================================================================== --- head/sys/arm/arm/machdep.c Sat Mar 26 03:46:12 2016 (r297283) +++ head/sys/arm/arm/machdep.c Sat Mar 26 06:55:55 2016 (r297284) @@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$"); #include <machine/sysarch.h> #ifdef FDT +#include <contrib/libfdt/libfdt.h> #include <dev/fdt/fdt_common.h> #include <dev/ofw/openfirm.h> #endif @@ -959,7 +960,8 @@ makectx(struct trapframe *tf, struct pcb * 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, void *dtb_ptr, + size_t dtb_size) { #ifdef DDB vm_offset_t zstart = 0, zend = 0; @@ -997,6 +999,16 @@ fake_preload_metadata(struct arm_boot_pa } else #endif lastaddr = (vm_offset_t)&end; + if (dtb_ptr != NULL) { + /* Copy DTB to KVA space and insert it into module chain. */ + lastaddr = roundup(lastaddr, sizeof(int)); + fake_preload[i++] = MODINFO_METADATA | MODINFOMD_DTBP; + fake_preload[i++] = sizeof(uint32_t); + fake_preload[i++] = (uint32_t)lastaddr; + memmove((void *)lastaddr, dtb_ptr, dtb_size); + lastaddr += dtb_size; + lastaddr = roundup(lastaddr, sizeof(int)); + } fake_preload[i++] = 0; fake_preload[i] = 0; preload_metadata = (void *)fake_preload; @@ -1023,20 +1035,35 @@ linux_parse_boot_param(struct arm_boot_p struct arm_lbabi_tag *walker; uint32_t revision; uint64_t serial; +#ifdef FDT + struct fdt_header *dtb_ptr; + uint32_t dtb_size; +#endif /* * Linux boot ABI: r0 = 0, r1 is the board type (!= 0) and r2 * is atags or dtb pointer. If all of these aren't satisfied, - * then punt. + * then punt. Unfortunately, it looks like DT enabled kernels + * doesn't uses board type and U-Boot delivers 0 in r1 for them. */ - if (!(abp->abp_r0 == 0 && abp->abp_r1 != 0 && abp->abp_r2 != 0)) - return 0; + if (abp->abp_r0 != 0 || abp->abp_r2 == 0) + return (0); +#ifdef FDT + /* Test if r2 point to valid DTB. */ + dtb_ptr = (struct fdt_header *)abp->abp_r2; + if (fdt_check_header(dtb_ptr) == 0) { + dtb_size = fdt_totalsize(dtb_ptr); + return (fake_preload_metadata(abp, dtb_ptr, dtb_size)); + } +#endif + /* Old, ATAG based boot must have board type set. */ + if (abp->abp_r1 == 0) + return (0); board_id = abp->abp_r1; walker = (struct arm_lbabi_tag *) (abp->abp_r2 + KERNVIRTADDR - abp->abp_physaddr); - /* xxx - Need to also look for binary device tree */ if (ATAG_TAG(walker) != ATAG_CORE) return 0; @@ -1077,7 +1104,7 @@ linux_parse_boot_param(struct arm_boot_p init_static_kenv(NULL, 0); - return fake_preload_metadata(abp); + return fake_preload_metadata(abp, NULL, 0); } #endif @@ -1135,7 +1162,7 @@ default_parse_boot_param(struct arm_boot return lastaddr; #endif /* Fall back to hardcoded metadata. */ - lastaddr = fake_preload_metadata(abp); + lastaddr = fake_preload_metadata(abp, NULL, 0); return lastaddr; } Modified: head/sys/arm/at91/board_tsc4370.c ============================================================================== --- head/sys/arm/at91/board_tsc4370.c Sat Mar 26 03:46:12 2016 (r297283) +++ head/sys/arm/at91/board_tsc4370.c Sat Mar 26 06:55:55 2016 (r297284) @@ -601,7 +601,7 @@ parse_boot_param(struct arm_boot_params inkernel_bootinfo = *(struct tsc_bootinfo *)(abp->abp_r1); } - return fake_preload_metadata(abp); + return fake_preload_metadata(abp, NULL, 0); } ARM_BOARD(NONE, "TSC4370 Controller Board"); Modified: head/sys/arm/conf/TEGRA124 ============================================================================== --- head/sys/arm/conf/TEGRA124 Sat Mar 26 03:46:12 2016 (r297283) +++ head/sys/arm/conf/TEGRA124 Sat Mar 26 06:55:55 2016 (r297284) @@ -28,6 +28,7 @@ options SCHED_ULE # ULE scheduler options PLATFORM # Platform based SoC options PLATFORM_SMP options SMP # Enable multiple cores +options LINUX_BOOT_ABI # Debugging for use in -current makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols Modified: head/sys/arm/include/machdep.h ============================================================================== --- head/sys/arm/include/machdep.h Sat Mar 26 03:46:12 2016 (r297283) +++ head/sys/arm/include/machdep.h Sat Mar 26 06:55:55 2016 (r297284) @@ -37,7 +37,8 @@ struct arm_boot_params; vm_offset_t default_parse_boot_param(struct arm_boot_params *abp); vm_offset_t freebsd_parse_boot_param(struct arm_boot_params *abp); vm_offset_t linux_parse_boot_param(struct arm_boot_params *abp); -vm_offset_t fake_preload_metadata(struct arm_boot_params *abp); +vm_offset_t fake_preload_metadata(struct arm_boot_params *abp, + void *dtb_ptr, size_t dtb_size); vm_offset_t parse_boot_param(struct arm_boot_params *abp); void arm_generic_initclocks(void);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603260655.u2Q6ttWj077457>