svn commit: r328505 - head/stand/fdt

Kyle Evans kevans at FreeBSD.org
Sun Jan 28 03:07:23 UTC 2018


Author: kevans
Date: Sun Jan 28 03:07:22 2018
New Revision: 328505
URL: https://svnweb.freebsd.org/changeset/base/328505

Log:
  stand/fdt: Check /compatible property on overlay if it exists
  
  Example overlays seen in other places use a compatible property on root node
  of an overlay to specify SOC compatibility. These don't get merged into base
  FDT as they're not part of a fragment, but it's expected that consumers of
  the overlay may want to check it.
  
  If /compatible on the overlay is missing, just apply it. This is the "I know
  what I'm doing" mode for those wanting to whip up a quick overlay and apply
  it. An overlay intended for distribution should include /compatible so as
  not to break a user's system.
  
  If /compatible on the overlay exists, honor it and cross-check it with
  /compatible on the base FDT. If /compatible on the base FDT is missing in
  this case, don't apply the overlay rather than risk breaking the system.
  
  Move the COPYOUT of overlay material to before we allocate space for
  next_fdtp so that we can avoid the allocation and copy into next_fdtp if we
  already know that the overlay can't apply.
  
  This gives way to the possibility of autoloading overlays found in
  /boot/overlays, since this provides a means of filtering out overlays not
  applicable to the current board.
  
  Reviewed by:	gonzo
  MFC after:	1 week
  Differential Revision:	https://reviews.freebsd.org/D13969

Modified:
  head/stand/fdt/fdt_loader_cmd.c

Modified: head/stand/fdt/fdt_loader_cmd.c
==============================================================================
--- head/stand/fdt/fdt_loader_cmd.c	Sun Jan 28 01:22:15 2018	(r328504)
+++ head/stand/fdt/fdt_loader_cmd.c	Sun Jan 28 03:07:22 2018	(r328505)
@@ -74,6 +74,7 @@ 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);
@@ -374,6 +375,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()
 {
@@ -408,6 +465,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);
@@ -425,7 +489,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 new_fdtp may be modified in place */
 		rv = fdt_overlay_apply(next_fdtp, overlay);
 		if (rv == 0) {


More information about the svn-src-head mailing list