Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Feb 2018 05:55:44 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r329152 - stable/11/stand/fdt
Message-ID:  <201802120555.w1C5tiZ1017010@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Mon Feb 12 05:55:44 2018
New Revision: 329152
URL: https://svnweb.freebsd.org/changeset/base/329152

Log:
  MFC r328505,r328659: stand/fdt improvements
  
  r328505: stand/fdt: Check /compatible property on overlay if it exists
  
  r328659: stand/fdt: Rip out FDT VA tracking

Modified:
  stable/11/stand/fdt/fdt_loader_cmd.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/stand/fdt/fdt_loader_cmd.c
==============================================================================
--- stable/11/stand/fdt/fdt_loader_cmd.c	Mon Feb 12 05:28:52 2018	(r329151)
+++ stable/11/stand/fdt/fdt_loader_cmd.c	Mon Feb 12 05:55:44 2018	(r329152)
@@ -67,13 +67,10 @@ static struct fdt_header *fdt_to_load = NULL;
 static struct fdt_header *fdtp = NULL;
 /* Size of FDT blob */
 static size_t fdtp_size = 0;
-/* Location of FDT in kernel or module. */
-/* This won't be set if FDT is loaded from disk or memory. */
-/* If it is set, we'll update it when fdt_copy() gets called. */
-static vm_offset_t fdtp_va = 0;
 
 static int fdt_load_dtb(vm_offset_t va);
 static void fdt_print_overlay_load_error(int err, const char *filename);
+static int fdt_check_overlay_compatible(void *base_fdt, void *overlay_fdt);
 
 static int fdt_cmd_nyi(int argc, char *argv[]);
 static int fdt_load_dtb_overlays_string(const char * filenames);
@@ -220,7 +217,6 @@ fdt_load_dtb(vm_offset_t va)
 		return (1);
 	}
 
-	fdtp_va = va;
 	COPYOUT(va, fdtp, fdtp_size);
 	debugf("DTB blob found at 0x%jx, size: 0x%jx\n", (uintmax_t)va, (uintmax_t)fdtp_size);
 
@@ -247,7 +243,6 @@ fdt_load_dtb_addr(struct fdt_header *header)
 		return (1);
 	}
 
-	fdtp_va = 0; // Don't write this back into module or kernel.
 	bcopy(header, fdtp, fdtp_size);
 	return (0);
 }
@@ -374,6 +369,62 @@ fdt_load_dtb_overlays_string(const char * filenames)
 	return (0);
 }
 
+/*
+ * fdt_check_overlay_compatible - check that the overlay_fdt is compatible with
+ * base_fdt before we attempt to apply it. It will need to re-calculate offsets
+ * in the base every time, rather than trying to cache them earlier in the
+ * process, because the overlay application process can/will invalidate a lot of
+ * offsets.
+ */
+static int
+fdt_check_overlay_compatible(void *base_fdt, void *overlay_fdt)
+{
+	const char *compat;
+	int compat_len, ocompat_len;
+	int oroot_offset, root_offset;
+	int slidx, sllen;
+
+	oroot_offset = fdt_path_offset(overlay_fdt, "/");
+	if (oroot_offset < 0)
+		return (oroot_offset);
+	/*
+	 * If /compatible in the overlay does not exist or if it is empty, then
+	 * we're automatically compatible. We do this for the sake of rapid
+	 * overlay development for overlays that aren't intended to be deployed.
+	 * The user assumes the risk of using an overlay without /compatible.
+	 */
+	if (fdt_get_property(overlay_fdt, oroot_offset, "compatible",
+	    &ocompat_len) == NULL || ocompat_len == 0)
+		return (0);
+	root_offset = fdt_path_offset(base_fdt, "/");
+	if (root_offset < 0)
+		return (root_offset);
+	/*
+	 * However, an empty or missing /compatible on the base is an error,
+	 * because allowing this offers no advantages.
+	 */
+	if (fdt_get_property(base_fdt, root_offset, "compatible",
+	    &compat_len) == NULL)
+		return (compat_len);
+	else if(compat_len == 0)
+		return (1);
+
+	slidx = 0;
+	compat = fdt_stringlist_get(overlay_fdt, oroot_offset, "compatible",
+	    slidx, &sllen);
+	while (compat != NULL) {
+		if (fdt_stringlist_search(base_fdt, root_offset, "compatible",
+		    compat) >= 0)
+			return (0);
+		++slidx;
+		compat = fdt_stringlist_get(overlay_fdt, oroot_offset,
+		    "compatible", slidx, &sllen);
+	};
+
+	/* We've exhausted the overlay's /compatible property... no match */
+	return (1);
+}
+
 void
 fdt_apply_overlays()
 {
@@ -406,6 +457,13 @@ fdt_apply_overlays()
 	current_fdtp = fdtp;
 	current_fdtp_size = fdtp_size;
 	for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) {
+		COPYOUT(fp->f_addr, overlay, fp->f_size);
+		/* Check compatible first to avoid unnecessary allocation */
+		rv = fdt_check_overlay_compatible(current_fdtp, overlay);
+		if (rv != 0) {
+			printf("DTB overlay '%s' not compatible\n", fp->f_name);
+			continue;
+		}
 		printf("applying DTB overlay '%s'\n", fp->f_name);
 		next_fdtp_size = current_fdtp_size + fp->f_size;
 		next_fdtp = malloc(next_fdtp_size);
@@ -423,7 +481,6 @@ fdt_apply_overlays()
 			printf("failed to open base dtb into overlay base\n");
 			continue;
 		}
-		COPYOUT(fp->f_addr, overlay, fp->f_size);
 		/* Both overlay and next_fdtp may be modified in place */
 		rv = fdt_overlay_apply(next_fdtp, overlay);
 		if (rv == 0) {
@@ -899,11 +956,6 @@ fdt_copy(vm_offset_t va)
 	if (fdt_fixup() == 0)
 		return (0);
 
-	if (fdtp_va != 0) {
-		/* Overwrite the FDT with the fixed version. */
-		/* XXX Is this really appropriate? */
-		COPYIN(fdtp, fdtp_va, fdtp_size);
-	}
 	COPYIN(fdtp, va, fdtp_size);
 	return (fdtp_size);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802120555.w1C5tiZ1017010>