From owner-svn-src-head@freebsd.org Mon Jan 15 05:00:28 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 36468E7D195; Mon, 15 Jan 2018 05:00:28 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 0D3067E9FB; Mon, 15 Jan 2018 05:00:28 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 412424356; Mon, 15 Jan 2018 05:00:27 +0000 (UTC) (envelope-from kevans@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w0F50Roa047397; Mon, 15 Jan 2018 05:00:27 GMT (envelope-from kevans@FreeBSD.org) Received: (from kevans@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w0F50RGV047396; Mon, 15 Jan 2018 05:00:27 GMT (envelope-from kevans@FreeBSD.org) Message-Id: <201801150500.w0F50RGV047396@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kevans set sender to kevans@FreeBSD.org using -f From: Kyle Evans Date: Mon, 15 Jan 2018 05:00:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r327991 - head/stand/fdt X-SVN-Group: head X-SVN-Commit-Author: kevans X-SVN-Commit-Paths: head/stand/fdt X-SVN-Commit-Revision: 327991 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Jan 2018 05:00:28 -0000 Author: kevans Date: Mon Jan 15 05:00:26 2018 New Revision: 327991 URL: https://svnweb.freebsd.org/changeset/base/327991 Log: stand/fdt: don't send clobbered FDT to the kernel If fdt_overlay_apply fails at some stage to apply the overlay to the base, both the base and overlay may be in an inconsistent state (some fixups applied, some phandles adjusted, some symbols merged). These can be bad for a number of reasons, to include user frustration if some fixups applied and not others. Fail a little safer by making a clean copy of the base FDT for every overlay that we can simply discard if things go awry. This also allows us the luxury of simply discarding overlays if we hit some kind of memory limit or if they're malformed and extremely large for some reason. We'll now leave a nice error message indicating that some overlays could not be applied due to size restrictions and we apply what we can. I note that our overlay implementation has some flaws that might still leave your system in an unbootable state even if an overlay applies correctly; please exercise caution in using overlays until we can swap it out for libfdt's implementation. Tested on: BananaPi-M3 (armv7) Tested on: Pine64 (aarch64) Differential Revision: https://reviews.freebsd.org/D13709 Modified: head/stand/fdt/fdt_loader_cmd.c Modified: head/stand/fdt/fdt_loader_cmd.c ============================================================================== --- head/stand/fdt/fdt_loader_cmd.c Mon Jan 15 04:52:12 2018 (r327990) +++ head/stand/fdt/fdt_loader_cmd.c Mon Jan 15 05:00:26 2018 (r327991) @@ -340,60 +340,78 @@ void fdt_apply_overlays() { struct preloaded_file *fp; - size_t overlays_size, max_overlay_size, new_fdtp_size; + size_t max_overlay_size, next_fdtp_size; + size_t current_fdtp_size; + void *current_fdtp; void *new_fdtp; + void *next_fdtp; void *overlay; int rv; if ((fdtp == NULL) || (fdtp_size == 0)) return; - overlays_size = 0; + new_fdtp = NULL; max_overlay_size = 0; for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) { if (max_overlay_size < fp->f_size) max_overlay_size = fp->f_size; - overlays_size += fp->f_size; } /* Nothing to apply */ - if (overlays_size == 0) + if (max_overlay_size == 0) return; - /* It's actually more than enough */ - new_fdtp_size = fdtp_size + overlays_size; - new_fdtp = malloc(new_fdtp_size); - if (new_fdtp == NULL) { - printf("failed to allocate memory for DTB blob with overlays\n"); - return; - } - overlay = malloc(max_overlay_size); if (overlay == NULL) { printf("failed to allocate memory for DTB blob with overlays\n"); - free(new_fdtp); return; } - - rv = fdt_open_into(fdtp, new_fdtp, new_fdtp_size); - if (rv != 0) { - printf("failed to open DTB blob for applying overlays\n"); - free(new_fdtp); - free(overlay); - return; - } - + current_fdtp = fdtp; + current_fdtp_size = fdtp_size; for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) { printf("applying DTB overlay '%s'\n", fp->f_name); + next_fdtp_size = current_fdtp_size + fp->f_size; + next_fdtp = malloc(next_fdtp_size); + if (next_fdtp == NULL) { + /* + * Output warning, then move on to applying other + * overlays in case this one is simply too large. + */ + printf("failed to allocate memory for overlay base\n"); + continue; + } + rv = fdt_open_into(current_fdtp, next_fdtp, next_fdtp_size); + if (rv != 0) { + 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 */ - fdt_overlay_apply(new_fdtp, overlay); + rv = fdt_overlay_apply(next_fdtp, overlay); + if (rv == 0) { + /* Rotate next -> current */ + if (current_fdtp != fdtp) + free(current_fdtp); + current_fdtp = next_fdtp; + current_fdtp_size = next_fdtp_size; + } else { + /* + * Assume here that the base we tried to apply on is + * either trashed or in an inconsistent state. Trying to + * load it might work, but it's better to discard it and + * play it safe. */ + free(next_fdtp); + printf("failed to apply overlay: %s\n", + fdt_strerror(rv)); + } } - - free(fdtp); - fdtp = new_fdtp; - fdtp_size = new_fdtp_size; - + /* We could have failed to apply all overlays; then we do nothing */ + if (current_fdtp != fdtp) { + free(fdtp); + fdtp = current_fdtp; + fdtp_size = current_fdtp_size; + } free(overlay); }