From patchwork Mon Dec 17 19:06:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014697 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="LkA4e18M"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JVyv6DFmz9s3q for ; Tue, 18 Dec 2018 06:07:35 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 7A702C2214A; Mon, 17 Dec 2018 19:07:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9404AC2213B; Mon, 17 Dec 2018 19:06:50 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 2E549C21FCA; Mon, 17 Dec 2018 19:06:49 +0000 (UTC) Received: from mail-wm1-f66.google.com (mail-wm1-f66.google.com [209.85.128.66]) by lists.denx.de (Postfix) with ESMTPS id 92D03C21E35 for ; Mon, 17 Dec 2018 19:06:48 +0000 (UTC) Received: by mail-wm1-f66.google.com with SMTP id m22so324123wml.3 for ; Mon, 17 Dec 2018 11:06:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+eQ/rW2n1PFCPfN/4E21c6DJP6ucTyG97SeLTYYFVOU=; b=LkA4e18MaJkG1o+M2nd56/E/DhBDukvmgRvQkP1Fq47gfXMmTSnbQlv+aajo9qd9nY WOZRP96tEVwo55aRsl8/TRkjypqKL2IyaS9ptioX7MDGOvEvV2Ddml3lio51yLoFF0BQ 72DCOX8eI8Mx/oJqUYFWByHICXk8ScjruAVQO/KyOcIAffcK1xQkBlBBByR/pGNlHI3E CKVZrSqhER4WLG0Xr5JBjKol4KfBLUSxZAPT0jorL4Dnkfv6Afo0mUWSP+zFuxF224yc WlkescOtA51rOtQGVQdrXqeGWw27g9+WCfBF65vroLceP3MObFOU42ATHGzoG4fzHlJj hQAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+eQ/rW2n1PFCPfN/4E21c6DJP6ucTyG97SeLTYYFVOU=; b=nHbn3zmzcM2CTk5Fy+iHq3ukWHo8obicFPR2tcnZSpBfdzJmsDVCKwOwwvbnoJNE0r CeTsopnKbX5pjRDR85kpGNFEg9jnamxC1NSG9H+ZUAYqw9ZnRoVC+WMhW5CWf89BSZpV Vr+tOIAf3ogsvCSrDwOWHQFX6GXcUCKphufEIcsNuDhL9gvYfDbwknWxbOCyfqefEnhj kdDVUnAkF0qMgv76Ezh7+Uk0dEcEWFLhrr+1UJlCSruRxfAOSDuhSI9injRB96wH5vpz YEGbiBJpAjSokntueOeUXGwDYrU4b6+iz3UM6nK8RZ3XhpdHXxc0Td152E/aSiKOt8V+ 1qAg== X-Gm-Message-State: AA+aEWZBlMXLJDUCGaftuT8/KP789eG6d9OCNwVSthCipfyZcCHxClFb +jQOKJl1sN5xwSwTktFl4Ww= X-Google-Smtp-Source: AFSGD/XVMQyKIL9GCxMeVPokpnwPWjNt/fLPvx+USxJs2bquFJsebS+Za7TaMDQ24tG4bUKSe9mGBQ== X-Received: by 2002:a1c:1d4f:: with SMTP id d76mr308824wmd.98.1545073608000; Mon, 17 Dec 2018 11:06:48 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:46 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:30 +0100 Message-Id: <20181217190638.21672-2-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v7 1/9] test: add test for lib/lmb.c X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add basic tests for the lmb memory allocation code used to reserve and allocate memory during boot. Signed-off-by: Simon Goldschmidt --- Changes in v7: None Changes in v6: None Changes in v5: - this patch is new in v5 Changes in v4: None Changes in v2: None test/lib/Makefile | 1 + test/lib/lmb.c | 297 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+) create mode 100644 test/lib/lmb.c diff --git a/test/lib/Makefile b/test/lib/Makefile index ea68fae566..5a636aac74 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -3,3 +3,4 @@ # (C) Copyright 2018 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc obj-y += hexdump.o +obj-y += lmb.o diff --git a/test/lib/lmb.c b/test/lib/lmb.c new file mode 100644 index 0000000000..dd7ba14b34 --- /dev/null +++ b/test/lib/lmb.c @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 Simon Goldschmidt + */ + +#include +#include +#include +#include + +static int check_lmb(struct unit_test_state *uts, struct lmb *lmb, + phys_addr_t ram_base, phys_size_t ram_size, + unsigned long num_reserved, + phys_addr_t base1, phys_size_t size1, + phys_addr_t base2, phys_size_t size2, + phys_addr_t base3, phys_size_t size3) +{ + ut_asserteq(lmb->memory.cnt, 1); + ut_asserteq(lmb->memory.region[0].base, ram_base); + ut_asserteq(lmb->memory.region[0].size, ram_size); + + ut_asserteq(lmb->reserved.cnt, num_reserved); + if (num_reserved > 0) { + ut_asserteq(lmb->reserved.region[0].base, base1); + ut_asserteq(lmb->reserved.region[0].size, size1); + } + if (num_reserved > 1) { + ut_asserteq(lmb->reserved.region[1].base, base2); + ut_asserteq(lmb->reserved.region[1].size, size2); + } + if (num_reserved > 2) { + ut_asserteq(lmb->reserved.region[2].base, base3); + ut_asserteq(lmb->reserved.region[2].size, size3); + } + return 0; +} + +#define ASSERT_LMB(lmb, ram_base, ram_size, num_reserved, base1, size1, \ + base2, size2, base3, size3) \ + ut_assert(!check_lmb(uts, lmb, ram_base, ram_size, \ + num_reserved, base1, size1, base2, size2, base3, \ + size3)) + +/* + * Test helper function that reserves 64 KiB somewhere in the simulated RAM and + * then does some alloc + free tests. + */ +static int test_multi_alloc(struct unit_test_state *uts, + const phys_addr_t ram, const phys_size_t ram_size, + const phys_addr_t alloc_64k_addr) +{ + const phys_addr_t ram_end = ram + ram_size; + const phys_addr_t alloc_64k_end = alloc_64k_addr + 0x10000; + + struct lmb lmb; + long ret; + phys_addr_t a, a2, b, b2, c, d; + + /* check for overflow */ + ut_assert(ram_end == 0 || ram_end > ram); + ut_assert(alloc_64k_end > alloc_64k_addr); + /* check input addresses + size */ + ut_assert(alloc_64k_addr >= ram + 8); + ut_assert(alloc_64k_end <= ram_end - 8); + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + /* reserve 64KiB somewhere */ + ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000, + 0, 0, 0, 0); + + /* allocate somewhere, should be at the end of RAM */ + a = lmb_alloc(&lmb, 4, 1); + ut_asserteq(a, ram_end - 4); + ASSERT_LMB(&lmb, ram, ram_size, 2, alloc_64k_addr, 0x10000, + ram_end - 4, 4, 0, 0); + /* alloc below end of reserved region -> below reserved region */ + b = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end); + ut_asserteq(b, alloc_64k_addr - 4); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 4, 0x10000 + 4, ram_end - 4, 4, 0, 0); + + /* 2nd time */ + c = lmb_alloc(&lmb, 4, 1); + ut_asserteq(c, ram_end - 8); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 4, 0x10000 + 4, ram_end - 8, 8, 0, 0); + d = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end); + ut_asserteq(d, alloc_64k_addr - 8); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0); + + ret = lmb_free(&lmb, a, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0); + /* allocate again to ensure we get the same address */ + a2 = lmb_alloc(&lmb, 4, 1); + ut_asserteq(a, a2); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 8, 0, 0); + ret = lmb_free(&lmb, a2, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0); + + ret = lmb_free(&lmb, b, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 3, + alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000, + ram_end - 8, 4); + /* allocate again to ensure we get the same address */ + b2 = lmb_alloc_base(&lmb, 4, 1, alloc_64k_end); + ut_asserteq(b, b2); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 8, 0x10000 + 8, ram_end - 8, 4, 0, 0); + ret = lmb_free(&lmb, b2, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 3, + alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000, + ram_end - 8, 4); + + ret = lmb_free(&lmb, c, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 2, + alloc_64k_addr - 8, 4, alloc_64k_addr, 0x10000, 0, 0); + ret = lmb_free(&lmb, d, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000, + 0, 0, 0, 0); + + return 0; +} + +static int test_multi_alloc_512mb(struct unit_test_state *uts, + const phys_addr_t ram) +{ + return test_multi_alloc(uts, ram, 0x20000000, ram + 0x10000000); +} + +/* Create a memory region with one reserved region and allocate */ +static int lib_test_lmb_simple(struct unit_test_state *uts) +{ + /* simulate 512 MiB RAM beginning at 1GiB */ + return test_multi_alloc_512mb(uts, 0x40000000); +} + +DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */ +static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram) +{ + const phys_size_t ram_size = 0x20000000; + const phys_size_t big_block_size = 0x10000000; + const phys_addr_t ram_end = ram + ram_size; + const phys_addr_t alloc_64k_addr = ram + 0x10000000; + struct lmb lmb; + long ret; + phys_addr_t a, b; + + /* check for overflow */ + ut_assert(ram_end == 0 || ram_end > ram); + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + /* reserve 64KiB in the middle of RAM */ + ret = lmb_reserve(&lmb, alloc_64k_addr, 0x10000); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000, + 0, 0, 0, 0); + + /* allocate a big block, should be below reserved */ + a = lmb_alloc(&lmb, big_block_size, 1); + ut_asserteq(a, ram); + ASSERT_LMB(&lmb, ram, ram_size, 1, a, + big_block_size + 0x10000, 0, 0, 0, 0); + /* allocate 2nd big block */ + /* This should fail, printing an error */ + b = lmb_alloc(&lmb, big_block_size, 1); + ut_asserteq(b, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, a, + big_block_size + 0x10000, 0, 0, 0, 0); + + ret = lmb_free(&lmb, a, big_block_size); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000, + 0, 0, 0, 0); + + /* allocate too big block */ + /* This should fail, printing an error */ + a = lmb_alloc(&lmb, ram_size, 1); + ut_asserteq(a, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, alloc_64k_addr, 0x10000, + 0, 0, 0, 0); + + return 0; +} + +static int lib_test_lmb_big(struct unit_test_state *uts) +{ + return test_bigblock(uts, 0x40000000); +} + +DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Simulate 512 MiB RAM, allocate a block without previous reservation */ +static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram) +{ + const phys_size_t ram_size = 0x20000000; + const phys_addr_t ram_end = ram + ram_size; + struct lmb lmb; + long ret; + phys_addr_t a, b; + + /* check for overflow */ + ut_assert(ram_end == 0 || ram_end > ram); + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + /* allocate a block */ + a = lmb_alloc(&lmb, 4, 1); + ut_assert(a != 0); + /* and free it */ + ret = lmb_free(&lmb, a, 4); + ut_asserteq(ret, 0); + + /* allocate a block with base*/ + b = lmb_alloc_base(&lmb, 4, 1, ram_end); + ut_assert(a == b); + /* and free it */ + ret = lmb_free(&lmb, b, 4); + ut_asserteq(ret, 0); + + return 0; +} + +static int lib_test_lmb_noreserved(struct unit_test_state *uts) +{ + return test_noreserved(uts, 0x40000000); +} + +DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* + * Simulate a RAM that starts at 0 and allocate down to address 0, which must + * fail as '0' means failure for the lmb_alloc functions. + */ +static int lib_test_lmb_at_0(struct unit_test_state *uts) +{ + const phys_addr_t ram = 0; + const phys_size_t ram_size = 0x20000000; + struct lmb lmb; + long ret; + phys_addr_t a, b; + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + /* allocate nearly everything */ + a = lmb_alloc(&lmb, ram_size - 4, 1); + ut_asserteq(a, ram + 4); + ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4, + 0, 0, 0, 0); + /* allocate the rest */ + /* This should fail as the allocated address would be 0 */ + b = lmb_alloc(&lmb, 4, 1); + ut_asserteq(b, 0); + /* check that this was an error by checking lmb */ + ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4, + 0, 0, 0, 0); + /* check that this was an error by freeing b */ + ret = lmb_free(&lmb, b, 4); + ut_asserteq(ret, -1); + ASSERT_LMB(&lmb, ram, ram_size, 1, a, ram_size - 4, + 0, 0, 0, 0); + + ret = lmb_free(&lmb, a, ram_size - 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0); + + return 0; +} + +DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From patchwork Mon Dec 17 19:06:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014700 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="J1NL4unA"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW134ywKz9s2P for ; Tue, 18 Dec 2018 06:09:27 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 22A58C21FE1; Mon, 17 Dec 2018 19:08:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id EF655C2218C; Mon, 17 Dec 2018 19:07:02 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 862EAC22169; Mon, 17 Dec 2018 19:06:54 +0000 (UTC) Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by lists.denx.de (Postfix) with ESMTPS id C0ACEC2215B for ; Mon, 17 Dec 2018 19:06:50 +0000 (UTC) Received: by mail-wr1-f66.google.com with SMTP id c14so13463839wrr.0 for ; Mon, 17 Dec 2018 11:06:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7y/kzm7CGjbqDDA3eR04sRYqKAsbf0pbkP7Aj9BbQYs=; b=J1NL4unA1JrbM45x7quecne1COXdoBDv8fMf/iniK+TJXN8YjT1rgIft3vjX0KRyfe Z+i/9BmPQXnD4DMa55lSaWky9RXeegp9nZ8IHrgUq3h3J9tIWjBpgblL8zofUPEviS0i VyQcjgVbEtSYMD/M2OVrbkVClK/uu++CD6j9ZVi/29IwoWUVfU8GKxJrQ60PjZGcp9Gv 2Wm8se9EZ+NkALyOWUoynDRGEJl0CFXJgUdXEMxvT3TdD85NjKTECcSuw6vefi24mkfr Yj+uzYSLqKMVlKWjlk9C//wXMR+r+Mm+igSyodLLYr6Nxtvu2SEh3CsvqvtcAeYoSQUm ppXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7y/kzm7CGjbqDDA3eR04sRYqKAsbf0pbkP7Aj9BbQYs=; b=BD8lI9mZYS7IrrpOjt/M2HFfvsqGbhTPBaiOO+SCLfcW75EhP1RfJcxNhlD77gsRAO xbAKNLijE5H02VGy6sZy1pt3MC2ruG9FQoEN21hzSKSSkfjaJ2TiHe9m4QyEYOiisHQt w0vyRBoH/0YXLH5z1nXbNSL0VYYPRNwXHDP1YD8EWqyfihCMbA3CnkApQJL+m6j7qOjO pvAA3OD52u8khQ4fY8wqscXcBAIduzn7v8UgzDmIyXkrvH8AxsdHMf8jk9jARwaI+tvb ut0go0wTYDyrgTK2rRGlhd0dVd0ZKS3X+yrnD9bNXdp0axhkODNOf984Kca9QCtjSE+k QOiw== X-Gm-Message-State: AA+aEWbfCNLc7wBhq7jGa7JCZE3bUGtsPoNh2xZmrWZJZJ9Z2wFRBwxs c9jZHtt4sQdYOpFDQ/J8pbSId5cXSec= X-Google-Smtp-Source: AFSGD/XhUbATEKvU+420CWo49aYNqKU9bRP0VlNSch4wao300cO+0rWz9kBn2jVuR/wdCCcw3ZQvlg== X-Received: by 2002:adf:dbcb:: with SMTP id e11mr12313369wrj.58.1545073610436; Mon, 17 Dec 2018 11:06:50 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:48 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:31 +0100 Message-Id: <20181217190638.21672-3-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v7 2/9] lmb: fix allocation at end of address range X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The lmb code fails if base + size of RAM overflows to zero. Fix this by calculating end as 'base + size - 1' instead of 'base + size' where appropriate. Added tests to assert this is fixed. Signed-off-by: Simon Goldschmidt --- Changes in v7: None Changes in v6: None Changes in v5: - this patch is new in v5 Changes in v4: None Changes in v2: None lib/lmb.c | 29 ++++++++++++----------------- test/lib/lmb.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/lib/lmb.c b/lib/lmb.c index 1705417348..6d3dcf4e09 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -43,7 +43,10 @@ void lmb_dump_all(struct lmb *lmb) static long lmb_addrs_overlap(phys_addr_t base1, phys_size_t size1, phys_addr_t base2, phys_size_t size2) { - return ((base1 < (base2+size2)) && (base2 < (base1+size1))); + const phys_addr_t base1_end = base1 + size1 - 1; + const phys_addr_t base2_end = base2 + size2 - 1; + + return ((base1 <= base2_end) && (base2 <= base1_end)); } static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1, @@ -89,18 +92,9 @@ static void lmb_coalesce_regions(struct lmb_region *rgn, void lmb_init(struct lmb *lmb) { - /* Create a dummy zero size LMB which will get coalesced away later. - * This simplifies the lmb_add() code below... - */ - lmb->memory.region[0].base = 0; - lmb->memory.region[0].size = 0; - lmb->memory.cnt = 1; + lmb->memory.cnt = 0; lmb->memory.size = 0; - - /* Ditto. */ - lmb->reserved.region[0].base = 0; - lmb->reserved.region[0].size = 0; - lmb->reserved.cnt = 1; + lmb->reserved.cnt = 0; lmb->reserved.size = 0; } @@ -110,9 +104,10 @@ static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t unsigned long coalesced = 0; long adjacent, i; - if ((rgn->cnt == 1) && (rgn->region[0].size == 0)) { + if (rgn->cnt == 0) { rgn->region[0].base = base; rgn->region[0].size = size; + rgn->cnt = 1; return 0; } @@ -183,7 +178,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size) { struct lmb_region *rgn = &(lmb->reserved); phys_addr_t rgnbegin, rgnend; - phys_addr_t end = base + size; + phys_addr_t end = base + size - 1; int i; rgnbegin = rgnend = 0; /* supress gcc warnings */ @@ -191,7 +186,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size) /* Find the region where (base, size) belongs to */ for (i=0; i < rgn->cnt; i++) { rgnbegin = rgn->region[i].base; - rgnend = rgnbegin + rgn->region[i].size; + rgnend = rgnbegin + rgn->region[i].size - 1; if ((rgnbegin <= base) && (end <= rgnend)) break; @@ -209,7 +204,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size) /* Check to see if region is matching at the front */ if (rgnbegin == base) { - rgn->region[i].base = end; + rgn->region[i].base = end + 1; rgn->region[i].size -= size; return 0; } @@ -225,7 +220,7 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size) * beginging of the hole and add the region after hole. */ rgn->region[i].size = base - rgn->region[i].base; - return lmb_add_region(rgn, end, rgnend - end); + return lmb_add_region(rgn, end + 1, rgnend - end); } long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size) diff --git a/test/lib/lmb.c b/test/lib/lmb.c index dd7ba14b34..fb7ca45ef1 100644 --- a/test/lib/lmb.c +++ b/test/lib/lmb.c @@ -146,8 +146,15 @@ static int test_multi_alloc_512mb(struct unit_test_state *uts, /* Create a memory region with one reserved region and allocate */ static int lib_test_lmb_simple(struct unit_test_state *uts) { + int ret; + /* simulate 512 MiB RAM beginning at 1GiB */ - return test_multi_alloc_512mb(uts, 0x40000000); + ret = test_multi_alloc_512mb(uts, 0x40000000); + if (ret) + return ret; + + /* simulate 512 MiB RAM beginning at 1.5GiB */ + return test_multi_alloc_512mb(uts, 0xE0000000); } DM_TEST(lib_test_lmb_simple, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); @@ -206,7 +213,15 @@ static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram) static int lib_test_lmb_big(struct unit_test_state *uts) { - return test_bigblock(uts, 0x40000000); + int ret; + + /* simulate 512 MiB RAM beginning at 1GiB */ + ret = test_bigblock(uts, 0x40000000); + if (ret) + return ret; + + /* simulate 512 MiB RAM beginning at 1.5GiB */ + return test_bigblock(uts, 0xE0000000); } DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); @@ -247,7 +262,15 @@ static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram) static int lib_test_lmb_noreserved(struct unit_test_state *uts) { - return test_noreserved(uts, 0x40000000); + int ret; + + /* simulate 512 MiB RAM beginning at 1GiB */ + ret = test_noreserved(uts, 0x40000000); + if (ret) + return ret; + + /* simulate 512 MiB RAM beginning at 1.5GiB */ + return test_noreserved(uts, 0xE0000000); } DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From patchwork Mon Dec 17 19:06:32 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014698 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RrXRzJM9"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JVzx67Hfz9s3q for ; Tue, 18 Dec 2018 06:08:29 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 8ED83C21FD2; Mon, 17 Dec 2018 19:07:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 1B84DC221AA; Mon, 17 Dec 2018 19:07:00 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 5A552C21F51; Mon, 17 Dec 2018 19:06:56 +0000 (UTC) Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by lists.denx.de (Postfix) with ESMTPS id 3B559C22178 for ; Mon, 17 Dec 2018 19:06:52 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id z5so13421449wrt.11 for ; Mon, 17 Dec 2018 11:06:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=pvUs8SEamT6jDIQd/bAwUtpDPh/4cJNCDhdYrw5MnS0=; b=RrXRzJM98sNaLR62V0Fg+YGxMqzsgRG7p/WUX3kvja9jLEToUpoB0vR05LItVK3J3J 2q7LR0Ql1GIdxsTOtXk69+GUrRxJCSRPSer80pZ1UvnqtXYDXxNMS7imS79ZmGx/zJTP zXCp/GQYsPYkH08LlIpyHBFXeldySmy5T/tF/WISw0+++WNsNwe9BLI0ZbkK1E+ErzyM Ax2Bx9z8WnQwNkwjEnwZTgAynWRlFnc2yzNgFyoBPBuwhykU3m65b0Sm8tbmBK7rmCRw v75kDO8Db9HbuJ0TSk+jZRXN4fRfs+vIR6dAxh6mSPEKrqlOMF3hQl5gKIW9B6VQdMzD SdCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=pvUs8SEamT6jDIQd/bAwUtpDPh/4cJNCDhdYrw5MnS0=; b=C9iS6kR8jCwVQdBfe10yFDIfKrqC15OSs46bzLP+XxPcmNp4dcHC6I0BtmU2/20py0 9fwPIKIsvQMUtpXR/KBpb157nxJ6md8HFR+o39VbbikJtu6ZM2Ke841QNt/BLWbvzIsf iOkU+GA3Ym0/f4HqN2JENLiVhUZ3YKLH+aa77Xg+1WjmgKKCSnw44X3Hrao0X7lCjNWB C/FwptLbtfyNtl1tNLRm0o1MBDdrhwLKXk0ebwn5nl+iGAJ/3qVVmomwe1a3t5CLUD4f OP9R+325KEH4JaHf6JnAGIdOqrLQiOczbVpMqpTcVQZXfZA3tvYfvx3T26DIMS9wMh0d U2/A== X-Gm-Message-State: AA+aEWbtF/ZK9NHcrHUKFBhSgFebkYJpLerDZatLXglsCna0scSP5vcM NuXvO3pIPCVMjqFTJy8QyAY= X-Google-Smtp-Source: AFSGD/Xac4lA/dt8TW7xWXSUckz7ZyH+XS5lbFAevzAXHWIGPIkZSMouvpyUjVkKo61/xwUwdd/Uuw== X-Received: by 2002:adf:fe11:: with SMTP id n17mr11490535wrr.329.1545073611684; Mon, 17 Dec 2018 11:06:51 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:50 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:32 +0100 Message-Id: <20181217190638.21672-4-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v7 3/9] lib: lmb: reserving overlapping regions should fail X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" lmb_add_region handles overlapping regions wrong: instead of merging or rejecting to add a new reserved region that overlaps an existing one, it just adds the new region. Since internally the same function is used for lmb_alloc, change lmb_add_region to reject overlapping regions. Also, to keep reserved memory correct after 'free', reserved entries created by allocating memory must not set their size to a multiple of alignment but to the original size. This ensures the reserved region is completely removed when the caller calls 'lmb_free', as this one takes the same size as passed to 'lmb_alloc' etc. Add test to assert this. Signed-off-by: Simon Goldschmidt --- Changes in v7: - add braces around if/else with macros accross more than one line Changes in v6: - fix size of allocated regions that need alignment padding Changes in v5: - added a test for this bug Changes in v4: None Changes in v2: None lib/lmb.c | 11 +++--- test/lib/lmb.c | 95 +++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/lib/lmb.c b/lib/lmb.c index 6d3dcf4e09..cd297f8202 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -131,6 +131,9 @@ static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t rgn->region[i].size += size; coalesced++; break; + } else if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) { + /* regions overlap */ + return -1; } } @@ -269,11 +272,6 @@ static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size) return addr & ~(size - 1); } -static phys_addr_t lmb_align_up(phys_addr_t addr, ulong size) -{ - return (addr + (size - 1)) & ~(size - 1); -} - phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr) { long i, j; @@ -302,8 +300,7 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy if (j < 0) { /* This area isn't reserved, take it */ if (lmb_add_region(&lmb->reserved, base, - lmb_align_up(size, - align)) < 0) + size) < 0) return 0; return base; } diff --git a/test/lib/lmb.c b/test/lib/lmb.c index fb7ca45ef1..e6acb70e76 100644 --- a/test/lib/lmb.c +++ b/test/lib/lmb.c @@ -227,13 +227,16 @@ static int lib_test_lmb_big(struct unit_test_state *uts) DM_TEST(lib_test_lmb_big, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); /* Simulate 512 MiB RAM, allocate a block without previous reservation */ -static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram) +static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram, + const phys_addr_t alloc_size, const ulong align) { const phys_size_t ram_size = 0x20000000; const phys_addr_t ram_end = ram + ram_size; struct lmb lmb; long ret; phys_addr_t a, b; + const phys_addr_t alloc_size_aligned = (alloc_size + align - 1) & + ~(align - 1); /* check for overflow */ ut_assert(ram_end == 0 || ram_end > ram); @@ -242,20 +245,43 @@ static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram) ret = lmb_add(&lmb, ram, ram_size); ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0); /* allocate a block */ - a = lmb_alloc(&lmb, 4, 1); + a = lmb_alloc(&lmb, alloc_size, align); ut_assert(a != 0); - /* and free it */ - ret = lmb_free(&lmb, a, 4); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned, + alloc_size, 0, 0, 0, 0); + /* allocate another block */ + b = lmb_alloc(&lmb, alloc_size, align); + ut_assert(b != 0); + if (alloc_size == alloc_size_aligned) { + ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - + (alloc_size_aligned * 2), alloc_size * 2, 0, 0, 0, + 0); + } else { + ASSERT_LMB(&lmb, ram, ram_size, 2, ram + ram_size - + (alloc_size_aligned * 2), alloc_size, ram + ram_size + - alloc_size_aligned, alloc_size, 0, 0); + } + /* and free them */ + ret = lmb_free(&lmb, b, alloc_size); ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned, + alloc_size, 0, 0, 0, 0); + ret = lmb_free(&lmb, a, alloc_size); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0); /* allocate a block with base*/ - b = lmb_alloc_base(&lmb, 4, 1, ram_end); + b = lmb_alloc_base(&lmb, alloc_size, align, ram_end); ut_assert(a == b); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram + ram_size - alloc_size_aligned, + alloc_size, 0, 0, 0, 0); /* and free it */ - ret = lmb_free(&lmb, b, 4); + ret = lmb_free(&lmb, b, alloc_size); ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 0, 0, 0, 0, 0, 0, 0); return 0; } @@ -265,16 +291,30 @@ static int lib_test_lmb_noreserved(struct unit_test_state *uts) int ret; /* simulate 512 MiB RAM beginning at 1GiB */ - ret = test_noreserved(uts, 0x40000000); + ret = test_noreserved(uts, 0x40000000, 4, 1); if (ret) return ret; /* simulate 512 MiB RAM beginning at 1.5GiB */ - return test_noreserved(uts, 0xE0000000); + return test_noreserved(uts, 0xE0000000, 4, 1); } DM_TEST(lib_test_lmb_noreserved, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); +static int lib_test_lmb_unaligned_size(struct unit_test_state *uts) +{ + int ret; + + /* simulate 512 MiB RAM beginning at 1GiB */ + ret = test_noreserved(uts, 0x40000000, 5, 8); + if (ret) + return ret; + + /* simulate 512 MiB RAM beginning at 1.5GiB */ + return test_noreserved(uts, 0xE0000000, 5, 8); +} + +DM_TEST(lib_test_lmb_unaligned_size, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); /* * Simulate a RAM that starts at 0 and allocate down to address 0, which must * fail as '0' means failure for the lmb_alloc functions. @@ -318,3 +358,42 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts) } DM_TEST(lib_test_lmb_at_0, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Check that calling lmb_reserve with overlapping regions fails. */ +static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts) +{ + const phys_addr_t ram = 0x40000000; + const phys_size_t ram_size = 0x20000000; + struct lmb lmb; + long ret; + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + ret = lmb_reserve(&lmb, 0x40010000, 0x10000); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000, + 0, 0, 0, 0); + /* allocate overlapping region should fail */ + ret = lmb_reserve(&lmb, 0x40011000, 0x10000); + ut_asserteq(ret, -1); + ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x10000, + 0, 0, 0, 0); + /* allocate 3nd region */ + ret = lmb_reserve(&lmb, 0x40030000, 0x10000); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 2, 0x40010000, 0x10000, + 0x40030000, 0x10000, 0, 0); + /* allocate 2nd region */ + ret = lmb_reserve(&lmb, 0x40020000, 0x10000); + ut_assert(ret >= 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x30000, + 0, 0, 0, 0); + + return 0; +} + +DM_TEST(lib_test_lmb_overlapping_reserve, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From patchwork Mon Dec 17 19:06:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014702 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="UwMf+gYE"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW2p6DT3z9s3q for ; Tue, 18 Dec 2018 06:10:58 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 25E91C21EFF; Mon, 17 Dec 2018 19:09:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 7B7BEC221B5; Mon, 17 Dec 2018 19:07:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D4695C22193; Mon, 17 Dec 2018 19:06:57 +0000 (UTC) Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by lists.denx.de (Postfix) with ESMTPS id F2308C22195 for ; Mon, 17 Dec 2018 19:06:53 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id u4so12467449wrp.3 for ; Mon, 17 Dec 2018 11:06:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5M61YIGG8qeLicc+KMq2dcwunwJsbunaLy54/JIw5RY=; b=UwMf+gYEHc18DumQUn8T0xBbdd4ShOjmGilqJ4uJE3TVVdLTU+9flL9haR/OugJRlF TqmP1Cf0MOp6gDMQfjvQ6hbrRe6dwJcrS9JDX9B52x423g1yRB3UHIpjl8B8mf1GMgVU 2ZI2n5tZS5pB7waM7UGknjQXUwEKKgWiy6oOTrrUkdXmgCg0uZk5Q9jkQj2wo7DQnTeH xznrgB0J2rC2jzpikylgRAdHw6MGjl44yiXjm/NLMkiMpHWzVdiUa6gOXi86i1VyBbap +zWEqEShVRllhKGe8fqrxzr/pwn5h1BiwzVWwRj7rr7714A6YM0wZHz2IfSVvXVF0kfS UNLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5M61YIGG8qeLicc+KMq2dcwunwJsbunaLy54/JIw5RY=; b=kqEFZZu2vn02aqcevWJ2WhtlnnJCzlAyGqQTjXLx6zyxtKDx6i8A4ZKlbxEci7u6Kh DOSb+LxIsfleT0TQ4jR8NM2ZwESlvBpndKLlIDyqarXTNjv1Y8IwnKQyYg1BiHRC1WM/ M960UjgIyFS6YrUzkvoFjxUkwyf0fp9VfNdVKD2KwOM7xQRYKlrtZQhDXxD9j7PwLgBl gO/P3Fj9pHnVlOJBkcUDXsO80871upJ48l5qv+5jC7y291eoPLPWx6f118bI6AJoqcMk +fAQaZWOywBFBYOzChOJtehe4ls+vDew1tQQqoDXK6zhrYNUo89eNDPr7UZ0+nx5IvhD 4wRQ== X-Gm-Message-State: AA+aEWY2zCgzgey2xkExuS/8+ygtrKUDq+Lu4ZNcMLw+dUzmcb6WapwX zxQ10GQ0pRx8pj4Fo3BJVgk= X-Google-Smtp-Source: AFSGD/WXYj775NkDviSNZLNlaiV9ziFK1B2rWYjLbpQljF0+h47EatsykwHF82L4K4GOGdAlev2YbA== X-Received: by 2002:adf:f28d:: with SMTP id k13mr12410642wro.78.1545073613677; Mon, 17 Dec 2018 11:06:53 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:52 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:33 +0100 Message-Id: <20181217190638.21672-5-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Alexey Brodkin , Heinrich Schuchardt , Alexander Graf , Miquel Raynal , Andrea Barisani Subject: [U-Boot] [PATCH v7 4/9] fdt: parse "reserved-memory" for memory reservation X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" boot_fdt_add_mem_rsv_regions() adds reserved memory sections to an lmb struct. Currently, it only parses regions described by /memreserve/ entries. Extend this to the more commonly used scheme of the "reserved-memory" node. Signed-off-by: Simon Goldschmidt --- Changes in v7: - fix compiling without CONFIG_FIT Changes in v6: - fix compiling without OF_CONTROL Changes in v5: None Changes in v4: - fixed invalid 'if' statement without braces in boot_fdt_reserve_region Changes in v2: - this patch is new in v2 common/image-fdt.c | 53 +++++++++++++++++++++++++++++++++++++++------- lib/Makefile | 1 + 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/common/image-fdt.c b/common/image-fdt.c index 95748f0ae1..5c0d6db3fe 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -67,30 +68,66 @@ static const image_header_t *image_get_fdt(ulong fdt_addr) } #endif +static void boot_fdt_reserve_region(struct lmb *lmb, uint64_t addr, + uint64_t size) +{ + int ret; + + ret = lmb_reserve(lmb, addr, size); + if (!ret) { + debug(" reserving fdt memory region: addr=%llx size=%llx\n", + (unsigned long long)addr, (unsigned long long)size); + } else { + puts("ERROR: reserving fdt memory region failed "); + printf("(addr=%llx size=%llx)\n", + (unsigned long long)addr, (unsigned long long)size); + } +} + /** - * boot_fdt_add_mem_rsv_regions - Mark the memreserve sections as unusable + * boot_fdt_add_mem_rsv_regions - Mark the memreserve and reserved-memory + * sections as unusable * @lmb: pointer to lmb handle, will be used for memory mgmt * @fdt_blob: pointer to fdt blob base address * - * Adds the memreserve regions in the dtb to the lmb block. Adding the - * memreserve regions prevents u-boot from using them to store the initrd - * or the fdt blob. + * Adds the and reserved-memorymemreserve regions in the dtb to the lmb block. + * Adding the memreserve regions prevents u-boot from using them to store the + * initrd or the fdt blob. */ void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob) { uint64_t addr, size; - int i, total; + int i, total, ret; + int nodeoffset, subnode; + struct fdt_resource res; if (fdt_check_header(fdt_blob) != 0) return; + /* process memreserve sections */ total = fdt_num_mem_rsv(fdt_blob); for (i = 0; i < total; i++) { if (fdt_get_mem_rsv(fdt_blob, i, &addr, &size) != 0) continue; - printf(" reserving fdt memory region: addr=%llx size=%llx\n", - (unsigned long long)addr, (unsigned long long)size); - lmb_reserve(lmb, addr, size); + boot_fdt_reserve_region(lmb, addr, size); + } + + /* process reserved-memory */ + nodeoffset = fdt_subnode_offset(fdt_blob, 0, "reserved-memory"); + if (nodeoffset >= 0) { + subnode = fdt_first_subnode(fdt_blob, nodeoffset); + while (subnode >= 0) { + /* check if this subnode has a reg property */ + ret = fdt_get_resource(fdt_blob, subnode, "reg", 0, + &res); + if (!ret) { + addr = res.start; + size = res.end - res.start + 1; + boot_fdt_reserve_region(lmb, addr, size); + } + + subnode = fdt_next_subnode(fdt_blob, subnode); + } } } diff --git a/lib/Makefile b/lib/Makefile index a6dd928a92..358789ff12 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -30,6 +30,7 @@ obj-y += crc7.o obj-y += crc8.o obj-y += crc16.o obj-$(CONFIG_ERRNO_STR) += errno_str.o +obj-$(CONFIG_OF_LIBFDT) += fdtdec.o obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o From patchwork Mon Dec 17 19:06:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014705 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="o7FiKeW5"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW3k6b84z9s3q for ; Tue, 18 Dec 2018 06:11:46 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 92374C221B1; Mon, 17 Dec 2018 19:08:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 8B367C220F8; Mon, 17 Dec 2018 19:07:14 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 85B6EC21FD2; Mon, 17 Dec 2018 19:06:59 +0000 (UTC) Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by lists.denx.de (Postfix) with ESMTPS id C6C56C221A4 for ; Mon, 17 Dec 2018 19:06:55 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id q18so13423746wrx.9 for ; Mon, 17 Dec 2018 11:06:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=UAjYtqU2Q50mqUybS7wa2UAkCxcQRR0kPA919dwJfVc=; b=o7FiKeW5i6iqOQETJpzqSlCns0lTJQl4/YTo9B2sTxToXLYM1FV63Lglv+HOPfvKiU lKYVmoMWJOHR05T52zyRm7zIXYwFKGqooUBAT6sJlQqWnA0zYJncsOizS+Fd8HfIGwS/ un9pIxTdHvKxfklcMf21vSUsmCrPHePQqc6Ok8wBZRle14HWjLAqtagcxgiJyZhJufd0 Elgmd8lGpNEElrJPvH+7UrS7IGUCgdJ3BMyWpJXAfmbnTzC9CP2OdlUeMZZvRnUxVHR9 /iH6TKAhoEcETh73+yE9XZX3aOqMV44zbtb7Y2qa3M47KBffI/z4FuuUEWO8kKQ0+hwq h/Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=UAjYtqU2Q50mqUybS7wa2UAkCxcQRR0kPA919dwJfVc=; b=SYjZ3PQHseg7gm7HMCubAXpGN2vCmovDzifVH8NEAHdRhXQh8AiDijRPqlVaFEQ+6b eBqZvAYGb3x0xejSMFdZDaD/QEIS4L/5kYK3VsTpybrh08poTnv4J+lgFq314sNXdXMd M0BKHoMfsCcdT4wE0PtyAxTWZDy1at9D8l1BNRYFLIlIpS37azOPfaQfe1dYJznIIUIG zx4KBmgl1LnXDLRywDZ51SpKgtWQxkroQXS/k9wOLU2Szud8cSN5QGovTmVdaFfyRgk4 cnlMUnc4XXNFx2C16nxva9tgkpX6si+hBf8U5kMR61dOlQt9UIP/d6Oc+/7wL3ie+OK1 ZiVw== X-Gm-Message-State: AA+aEWbDawd47/QyM4b1OUKZ8VlOQ0B/bi3zCvi/e1kOUx3piE1/GSqL WPlJeHwKU9JBKyDuR6Spxy4= X-Google-Smtp-Source: AFSGD/XjGw29amBEotsnPPgcEKopui2VBncQy6443lWnaxWa5jI3aFats+GU8RI9SjYkEnsmfq3scQ== X-Received: by 2002:adf:e3d0:: with SMTP id k16mr12430676wrm.223.1545073615323; Mon, 17 Dec 2018 11:06:55 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:54 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:34 +0100 Message-Id: <20181217190638.21672-6-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v7 5/9] lib: lmb: extend lmb for checks at load time X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This adds two new functions, lmb_alloc_addr and lmb_get_unreserved_size. lmb_alloc_addr behaves like lmb_alloc, but it tries to allocate a pre-specified address range. Unlike lmb_reserve, this address range must be inside one of the memory ranges that has been set up with lmb_add. lmb_get_unreserved_size returns the number of bytes that can be used up to the next reserved region or the end of valid ram. This can be 0 if the address passed is reserved. Added test for these new functions. Signed-off-by: Simon Goldschmidt --- Changes in v7: None Changes in v6: None Changes in v5: - fixed lmb_alloc_addr when resulting reserved ranges get combined - added test for these new functions Changes in v4: None Changes in v2: - added lmb_get_unreserved_size() for tftp include/lmb.h | 3 + lib/lmb.c | 53 +++++++++++++ test/lib/lmb.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 258 insertions(+) diff --git a/include/lmb.h b/include/lmb.h index f04d058093..7d7e2a78dc 100644 --- a/include/lmb.h +++ b/include/lmb.h @@ -38,6 +38,9 @@ extern phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align phys_addr_t max_addr); extern phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr); +extern phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, + phys_size_t size); +extern phys_size_t lmb_get_unreserved_size(struct lmb *lmb, phys_addr_t addr); extern int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr); extern long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size); diff --git a/lib/lmb.c b/lib/lmb.c index cd297f8202..e380a0a722 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -313,6 +313,59 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy return 0; } +/* + * Try to allocate a specific address range: must be in defined memory but not + * reserved + */ +phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size) +{ + long j; + + /* Check if the requested address is in one of the memory regions */ + j = lmb_overlaps_region(&lmb->memory, base, size); + if (j >= 0) { + /* + * Check if the requested end address is in the same memory + * region we found. + */ + if (lmb_addrs_overlap(lmb->memory.region[j].base, + lmb->memory.region[j].size, base + size - + 1, 1)) { + /* ok, reserve the memory */ + if (lmb_reserve(lmb, base, size) >= 0) + return base; + } + } + return 0; +} + +/* Return number of bytes from a given address that are free */ +phys_size_t lmb_get_unreserved_size(struct lmb *lmb, phys_addr_t addr) +{ + int i; + long j; + + /* check if the requested address is in the memory regions */ + j = lmb_overlaps_region(&lmb->memory, addr, 1); + if (j >= 0) { + for (i = 0; i < lmb->reserved.cnt; i++) { + if (addr < lmb->reserved.region[i].base) { + /* first reserved range > requested address */ + return lmb->reserved.region[i].base - addr; + } + if (lmb->reserved.region[i].base + + lmb->reserved.region[i].size > addr) { + /* requested addr is in this reserved range */ + return 0; + } + } + /* if we come here: no reserved ranges above requested addr */ + return lmb->memory.region[lmb->memory.cnt - 1].base + + lmb->memory.region[lmb->memory.cnt - 1].size - addr; + } + return 0; +} + int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr) { int i; diff --git a/test/lib/lmb.c b/test/lib/lmb.c index e6acb70e76..058d3c332b 100644 --- a/test/lib/lmb.c +++ b/test/lib/lmb.c @@ -397,3 +397,205 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts) DM_TEST(lib_test_lmb_overlapping_reserve, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* + * Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between. + * Expect addresses outside the memory range to fail. + */ +static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram) +{ + const phys_size_t ram_size = 0x20000000; + const phys_addr_t ram_end = ram + ram_size; + const phys_size_t alloc_addr_a = ram + 0x8000000; + const phys_size_t alloc_addr_b = ram + 0x8000000 * 2; + const phys_size_t alloc_addr_c = ram + 0x8000000 * 3; + struct lmb lmb; + long ret; + phys_addr_t a, b, c, d, e; + + /* check for overflow */ + ut_assert(ram_end == 0 || ram_end > ram); + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + /* reserve 3 blocks */ + ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000); + ut_asserteq(ret, 0); + ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000); + ut_asserteq(ret, 0); + ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000, + alloc_addr_b, 0x10000, alloc_addr_c, 0x10000); + + /* allocate blocks */ + a = lmb_alloc_addr(&lmb, ram, alloc_addr_a - ram); + ut_asserteq(a, ram); + ASSERT_LMB(&lmb, ram, ram_size, 3, ram, 0x8010000, + alloc_addr_b, 0x10000, alloc_addr_c, 0x10000); + b = lmb_alloc_addr(&lmb, alloc_addr_a + 0x10000, + alloc_addr_b - alloc_addr_a - 0x10000); + ut_asserteq(b, alloc_addr_a + 0x10000); + ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x10010000, + alloc_addr_c, 0x10000, 0, 0); + c = lmb_alloc_addr(&lmb, alloc_addr_b + 0x10000, + alloc_addr_c - alloc_addr_b - 0x10000); + ut_asserteq(c, alloc_addr_b + 0x10000); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000, + 0, 0, 0, 0); + d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, + ram_end - alloc_addr_c - 0x10000); + ut_asserteq(d, alloc_addr_c + 0x10000); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size, + 0, 0, 0, 0); + + /* allocating anything else should fail */ + e = lmb_alloc(&lmb, 1, 1); + ut_asserteq(e, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, ram_size, + 0, 0, 0, 0); + + ret = lmb_free(&lmb, d, ram_end - alloc_addr_c - 0x10000); + ut_asserteq(ret, 0); + + /* allocate at 3 points in free range */ + + d = lmb_alloc_addr(&lmb, ram_end - 4, 4); + ut_asserteq(d, ram_end - 4); + ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000, + d, 4, 0, 0); + ret = lmb_free(&lmb, d, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000, + 0, 0, 0, 0); + + d = lmb_alloc_addr(&lmb, ram_end - 128, 4); + ut_asserteq(d, ram_end - 128); + ASSERT_LMB(&lmb, ram, ram_size, 2, ram, 0x18010000, + d, 4, 0, 0); + ret = lmb_free(&lmb, d, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000, + 0, 0, 0, 0); + + d = lmb_alloc_addr(&lmb, alloc_addr_c + 0x10000, 4); + ut_asserteq(d, alloc_addr_c + 0x10000); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010004, + 0, 0, 0, 0); + ret = lmb_free(&lmb, d, 4); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram, 0x18010000, + 0, 0, 0, 0); + + /* allocate at the bottom */ + ret = lmb_free(&lmb, a, alloc_addr_a - ram); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 1, ram + 0x8000000, 0x10010000, + 0, 0, 0, 0); + d = lmb_alloc_addr(&lmb, ram, 4); + ut_asserteq(d, ram); + ASSERT_LMB(&lmb, ram, ram_size, 2, d, 4, + ram + 0x8000000, 0x10010000, 0, 0); + + /* check that allocating outside memory fails */ + if (ram_end != 0) { + ret = lmb_alloc_addr(&lmb, ram_end, 1); + ut_asserteq(ret, 0); + } + if (ram != 0) { + ret = lmb_alloc_addr(&lmb, ram - 1, 1); + ut_asserteq(ret, 0); + } + + return 0; +} + +static int lib_test_lmb_alloc_addr(struct unit_test_state *uts) +{ + int ret; + + /* simulate 512 MiB RAM beginning at 1GiB */ + ret = test_alloc_addr(uts, 0x40000000); + if (ret) + return ret; + + /* simulate 512 MiB RAM beginning at 1.5GiB */ + return test_alloc_addr(uts, 0xE0000000); +} + +DM_TEST(lib_test_lmb_alloc_addr, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Simulate 512 MiB RAM, reserve 3 blocks, check addresses in between */ +static int test_get_unreserved_size(struct unit_test_state *uts, + const phys_addr_t ram) +{ + const phys_size_t ram_size = 0x20000000; + const phys_addr_t ram_end = ram + ram_size; + const phys_size_t alloc_addr_a = ram + 0x8000000; + const phys_size_t alloc_addr_b = ram + 0x8000000 * 2; + const phys_size_t alloc_addr_c = ram + 0x8000000 * 3; + struct lmb lmb; + long ret; + phys_size_t s; + + /* check for overflow */ + ut_assert(ram_end == 0 || ram_end > ram); + + lmb_init(&lmb); + + ret = lmb_add(&lmb, ram, ram_size); + ut_asserteq(ret, 0); + + /* reserve 3 blocks */ + ret = lmb_reserve(&lmb, alloc_addr_a, 0x10000); + ut_asserteq(ret, 0); + ret = lmb_reserve(&lmb, alloc_addr_b, 0x10000); + ut_asserteq(ret, 0); + ret = lmb_reserve(&lmb, alloc_addr_c, 0x10000); + ut_asserteq(ret, 0); + ASSERT_LMB(&lmb, ram, ram_size, 3, alloc_addr_a, 0x10000, + alloc_addr_b, 0x10000, alloc_addr_c, 0x10000); + + /* check addresses in between blocks */ + s = lmb_get_unreserved_size(&lmb, ram); + ut_asserteq(s, alloc_addr_a - ram); + s = lmb_get_unreserved_size(&lmb, ram + 0x10000); + ut_asserteq(s, alloc_addr_a - ram - 0x10000); + s = lmb_get_unreserved_size(&lmb, alloc_addr_a - 4); + ut_asserteq(s, 4); + + s = lmb_get_unreserved_size(&lmb, alloc_addr_a + 0x10000); + ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x10000); + s = lmb_get_unreserved_size(&lmb, alloc_addr_a + 0x20000); + ut_asserteq(s, alloc_addr_b - alloc_addr_a - 0x20000); + s = lmb_get_unreserved_size(&lmb, alloc_addr_b - 4); + ut_asserteq(s, 4); + + s = lmb_get_unreserved_size(&lmb, alloc_addr_c + 0x10000); + ut_asserteq(s, ram_end - alloc_addr_c - 0x10000); + s = lmb_get_unreserved_size(&lmb, alloc_addr_c + 0x20000); + ut_asserteq(s, ram_end - alloc_addr_c - 0x20000); + s = lmb_get_unreserved_size(&lmb, ram_end - 4); + ut_asserteq(s, 4); + + return 0; +} + +static int lib_test_lmb_get_unreserved_size(struct unit_test_state *uts) +{ + int ret; + + /* simulate 512 MiB RAM beginning at 1GiB */ + ret = test_get_unreserved_size(uts, 0x40000000); + if (ret) + return ret; + + /* simulate 512 MiB RAM beginning at 1.5GiB */ + return test_get_unreserved_size(uts, 0xE0000000); +} + +DM_TEST(lib_test_lmb_get_unreserved_size, + DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From patchwork Mon Dec 17 19:06:35 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014699 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="GIXhPbC9"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW0z121yz9s2P for ; Tue, 18 Dec 2018 06:09:23 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id A6DF1C22162; Mon, 17 Dec 2018 19:08:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id A57B8C2219F; Mon, 17 Dec 2018 19:07:07 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D7525C221C2; Mon, 17 Dec 2018 19:07:01 +0000 (UTC) Received: from mail-wm1-f66.google.com (mail-wm1-f66.google.com [209.85.128.66]) by lists.denx.de (Postfix) with ESMTPS id EDB72C22169 for ; Mon, 17 Dec 2018 19:06:57 +0000 (UTC) Received: by mail-wm1-f66.google.com with SMTP id y185so5428459wmd.1 for ; Mon, 17 Dec 2018 11:06:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=3AAfZ/pKLdMgJ/DPBNm4l0PjDdN2Lu3G5hsLcd4DswI=; b=GIXhPbC9ildRusdCpC0org8lgdqu/PlIqbr1wjROk5l9ptptanA3YEVyAfjuVxryYv 5KA3qOaqmKEZPQzqwPSRYk4bdrRpsUelIZP0xoZk2BdwNUh8FNdp5Q9yr8y8JLB1Ri6c 11q/0hPqhLdUiWZ7nEIECTteek5t3LY7Z6Ft1oqF3khnIVcGqCIfIXq61hYgTp24u5yZ P12Puw0k9cr0aCJlrrYAnqYS2QP5MC2V84U/VyV9ckXgWDdHDW3+f6RVe/AfalX8fYtg 2yWtbPyTiN7sZhqPsIApjrqGDQv2ByIZ5U9PLC8NEWZgUCNSp+/Qaryuc43oICK3UG5r t0Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3AAfZ/pKLdMgJ/DPBNm4l0PjDdN2Lu3G5hsLcd4DswI=; b=rGvxeKoPS49TlV/6lA92G3awvdPlupEc8a3B/tr5VwkBho0XQbArH5XZKzfG1sKdzu /aWe5v3puZYzr4ng3KDR4b1/N5ee3miQuta2LFprnkWjP9g+6fcPLygLpSSCPYmi4WHU tWdmpAMEIaHFrSyoqoL2Z4wS/0l1GOaImsEgL0AZ41IWf2ImDWr1zig4cUehZXMd8+XI TerKaoLHD2wWt7fdayfxMc3aYegg6wfdwcY7NLNHdk33QyZVGoBsprzOS/4fknxyYPaU bsrkzto61vIHdHmDGMwHnN1zqyY+aN0iXAgAaIrzo3/u63I6eSW+nZEdOocleCisENCc ZCYg== X-Gm-Message-State: AA+aEWat3TP8kDFBXy+9fcspByy49BTqVuoRQNuT7P8VrHX6rvManqvf zsaudGF7IVZIiDexoqqCW9Q= X-Google-Smtp-Source: AFSGD/Xt0OSTLqhb8rWK33MIycEMWakGMNfTmK5rs7MV/w/UM+r1n8CbdO/Wg3Ee4Ci8PFzESg1mnA== X-Received: by 2002:a1c:68d7:: with SMTP id d206mr286255wmc.43.1545073617513; Mon, 17 Dec 2018 11:06:57 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:56 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:35 +0100 Message-Id: <20181217190638.21672-7-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Alexander Graf , Andrea Barisani Subject: [U-Boot] [PATCH v7 6/9] fs: prevent overwriting reserved memory X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This fixes CVE-2018-18440 ("insufficient boundary checks in filesystem image load") by using lmb to check the load size of a file against reserved memory addresses. Signed-off-by: Simon Goldschmidt --- Changes in v7: None Changes in v6: - fixed NULL pointer access in 'fdt_blob' passed to 'boot_fdt_add_mem_rsv_regions' Changes in v5: None Changes in v4: None Changes in v2: None fs/fs.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++--- include/lmb.h | 2 ++ lib/lmb.c | 13 ++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index cb265174e2..400aa921a7 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -429,13 +429,57 @@ int fs_size(const char *filename, loff_t *size) return ret; } -int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, - loff_t *actread) +#ifdef CONFIG_LMB +/* Check if a file may be read to the given address */ +static int fs_read_lmb_check(const char *filename, ulong addr, loff_t offset, + loff_t len, struct fstype_info *info) +{ + struct lmb lmb; + int ret; + loff_t size; + loff_t read_len; + + /* get the actual size of the file */ + ret = info->size(filename, &size); + if (ret) + return ret; + if (offset >= size) { + /* offset >= EOF, no bytes will be written */ + return 0; + } + read_len = size - offset; + + /* limit to 'len' if it is smaller */ + if (len && len < read_len) + read_len = len; + + lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start, + gd->bd->bi_dram[0].size, (void *)gd->fdt_blob); + lmb_dump_all(&lmb); + + if (lmb_alloc_addr(&lmb, addr, read_len) == addr) + return 0; + + printf("** Reading file would overwrite reserved memory **\n"); + return -1; +} +#endif + +static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, + int do_lmb_check, loff_t *actread) { struct fstype_info *info = fs_get_info(fs_type); void *buf; int ret; +#ifdef CONFIG_LMB + if (do_lmb_check) { + ret = fs_read_lmb_check(filename, addr, offset, len, info); + if (ret) + return ret; + } +#endif + /* * We don't actually know how many bytes are being read, since len==0 * means read the whole file. @@ -452,6 +496,12 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, return ret; } +int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actread) +{ + return _fs_read(filename, addr, offset, len, 0, actread); +} + int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, loff_t *actwrite) { @@ -622,7 +672,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], pos = 0; time = get_timer(0); - ret = fs_read(filename, addr, pos, bytes, &len_read); + ret = _fs_read(filename, addr, pos, bytes, 1, &len_read); time = get_timer(time); if (ret < 0) return 1; diff --git a/include/lmb.h b/include/lmb.h index 7d7e2a78dc..62da85e716 100644 --- a/include/lmb.h +++ b/include/lmb.h @@ -31,6 +31,8 @@ struct lmb { extern struct lmb lmb; extern void lmb_init(struct lmb *lmb); +extern void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base, + phys_size_t size, void *fdt_blob); extern long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size); extern long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size); extern phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align); diff --git a/lib/lmb.c b/lib/lmb.c index e380a0a722..3407705fa7 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -98,6 +98,19 @@ void lmb_init(struct lmb *lmb) lmb->reserved.size = 0; } +/* Initialize the struct, add memory and call arch/board reserve functions */ +void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size, + void *fdt_blob) +{ + lmb_init(lmb); + lmb_add(lmb, base, size); + arch_lmb_reserve(lmb); + board_lmb_reserve(lmb); + + if (IMAGE_ENABLE_OF_LIBFDT && fdt_blob) + boot_fdt_add_mem_rsv_regions(lmb, fdt_blob); +} + /* This routine called with relocation disabled. */ static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, phys_size_t size) { From patchwork Mon Dec 17 19:06:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014703 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="GNI5FlA1"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW2w5CCwz9s3q for ; Tue, 18 Dec 2018 06:11:04 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 51F2AC22171; Mon, 17 Dec 2018 19:08:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 8F0DFC221C3; Mon, 17 Dec 2018 19:07:08 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id B1382C221C2; Mon, 17 Dec 2018 19:07:02 +0000 (UTC) Received: from mail-wr1-f68.google.com (mail-wr1-f68.google.com [209.85.221.68]) by lists.denx.de (Postfix) with ESMTPS id 275B4C22195 for ; Mon, 17 Dec 2018 19:06:59 +0000 (UTC) Received: by mail-wr1-f68.google.com with SMTP id t6so13256642wrr.12 for ; Mon, 17 Dec 2018 11:06:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GxPaWWhJSJfWHSDkuPLJ7m053sHaDRQnLyVdZ4U+4f0=; b=GNI5FlA1rpvv0OMoEbJ4wZfuyQ4LRv0T+75gEinzo89C2gg7DJd2WjiDmZs9VDSLKt uq0RWMuQxHwX1cPhCZz4voJrXl4+OLBHXDBtNOsvhWhBMX/9vK0qgmzSoLWmVhdvfXXz UKW8FPctp/XCOCayPRKBUzb+krdTYwPo3WXjNDO10rZUwl6KapfoWktKF34WeW/LeFS0 oe0RpU7Xc6IcSFhioaMtQ6Sk1xCHUu8iSUkJht0hym5KJgQSJFdQiI0tWB/1BP3Pu+Yv CGwXlyEJY6tY2YA7pCgq5d2F6OKUmhd5CgJFARCWKCJ8p21X9yg3HvuAm1EdEZxEQN2x FSVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GxPaWWhJSJfWHSDkuPLJ7m053sHaDRQnLyVdZ4U+4f0=; b=pKyqjqimk6QM32zYDwdLrvnGkLgJ5bk5p6EflOPjxNbFyUdFkihEwQr5wz+pX0n0Wx hUBWPx4vnlmlEQg6MG9ouktN+Y+PYFJkfvlpDRPR2qAK2Xkh+SoxC79CmZ15ex581znq /3jQ9Xn2zqHBv9UNhTZwwttsst2g6zECwz/u0Fabfw0z3liaCZ6M6Y4pugARREsC5Rwi immykFTiUexjTLjVfziESEBTMhbLOc05BD4ydQ/HovyGtVmyo/RTITpF4dtj28HRDOS7 6PtrXmAP5vLjykXgUnnCWEN7pP0lENoNw4gOAUhabXvdnMyW7VJOQT0xrwU+5SJkTA3h bTfQ== X-Gm-Message-State: AA+aEWZOxHatP3g+DEQIjvMEettbk3rGWwNf0q7mj7PKN8QDqXh/3rCP L0Cq6dlF8c2kQ3UJPEtHdag= X-Google-Smtp-Source: AFSGD/V3K6DdhbCeyhmHf+PRzMme+frUd8UCoLvgcFXPfM+gPFeB+U5YMeutcQ0a7oQuh6JOAUYBgQ== X-Received: by 2002:adf:9422:: with SMTP id 31mr12678694wrq.106.1545073618890; Mon, 17 Dec 2018 11:06:58 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:58 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:36 +0100 Message-Id: <20181217190638.21672-8-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Alexander Graf , Andrea Barisani Subject: [U-Boot] [PATCH v7 7/9] bootm: use new common function lmb_init_and_reserve X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This reduces duplicate code only. Signed-off-by: Simon Goldschmidt --- Changes in v7: None Changes in v6: None Changes in v5: None Changes in v4: None Changes in v2: None common/bootm.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/common/bootm.c b/common/bootm.c index 8bf84ebcb7..31e4f0f794 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -56,15 +56,11 @@ static void boot_start_lmb(bootm_headers_t *images) ulong mem_start; phys_size_t mem_size; - lmb_init(&images->lmb); - mem_start = env_get_bootm_low(); mem_size = env_get_bootm_size(); - lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size); - - arch_lmb_reserve(&images->lmb); - board_lmb_reserve(&images->lmb); + lmb_init_and_reserve(&images->lmb, (phys_addr_t)mem_start, mem_size, + NULL); } #else #define lmb_reserve(lmb, base, size) From patchwork Mon Dec 17 19:06:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014706 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jPTd1MQ6"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW411w27z9s6w for ; Tue, 18 Dec 2018 06:12:01 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id E9355C22132; Mon, 17 Dec 2018 19:09:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 13125C221B2; Mon, 17 Dec 2018 19:07:49 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D64FFC22167; Mon, 17 Dec 2018 19:07:03 +0000 (UTC) Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by lists.denx.de (Postfix) with ESMTPS id 9056DC22162 for ; Mon, 17 Dec 2018 19:07:00 +0000 (UTC) Received: by mail-wr1-f66.google.com with SMTP id t6so13256698wrr.12 for ; Mon, 17 Dec 2018 11:07:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=sjKqf5KISCeLGf/mLciVJx8I19LiLGD4Kq30noa/Rtw=; b=jPTd1MQ6p1ZCv/ng7DDqt6Ox/HsO+0R0xS82sH4l7UoJHehJZFAL8X7fTNz3amj9k0 fC34+OOdOGRQtphIv/HvyI1d6j3MSGHF3Oj96ZbIPC/zfCqyCyFCCKaq/ALPf5+U6udt e5eUahVs+wVaKYlt9io/aOWBaCur7V6ZJ1Zg4Mjg/iNgLiy6iBTJG/QazUl+OLQQ8GwL ry23iUdQqH8BDNadBdvAxD9NUxKDb3K856pRYhGyU56xD8qq27mH5wQfvjC036fST5gY CBE5BJ084Kt5FD4Kl6y5j3vdqUd+EluYzN6FKNZOds6LvsgyKTOwvIs6KRNcfjZnMTN4 YJ5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=sjKqf5KISCeLGf/mLciVJx8I19LiLGD4Kq30noa/Rtw=; b=Cd9VUPt3gQhQEquKsEDLUA9cNDffbHVAUdXEvwZeRstyhLdVNoVumTAMD3b13WLWMy yTbEEgMu5tslskIB1JmbvfXyn5N2Owr+0B+rKTp1lqhz5F9rtFq9Qvwk8B+vHxuxPI1G iVz8kgbO7yLeAB63qMBcz8SqJi4uKvx3EhI2Prbp1EclxobSCnblFD94FahgKZbXJU5j ifxc0PE2idceLWjkLZtYkZlAkoegbZhZ8e2sllRyR11ut+ksgnfHBe/iAhepA0mIUmdx Oful+M62XSbIwsRvpn2CPCrM7L3PcY4xod85+D4L7yLno7DtuxlpKHSKaMN4vvVwpa5J Yj2w== X-Gm-Message-State: AA+aEWZUpdU/HyCa97Z7mPKm781DS1fAHpKzuMLNTuHWQ8qA5tm/qQCS T+VQExki12mOyM6f4i6xaVM= X-Google-Smtp-Source: AFSGD/UKEpkuYXEnwfJleYvXRPkBYzF5iVmjL4b972p6Xko+vmOOjHqZqJTwJxMa7ELo6p8npBW5VA== X-Received: by 2002:a5d:480d:: with SMTP id l13mr12620324wrq.175.1545073620273; Mon, 17 Dec 2018 11:07:00 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.06.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:06:59 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:37 +0100 Message-Id: <20181217190638.21672-9-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v7 8/9] lmb: remove unused extern declaration X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" lmb.h includes an extern declaration of "struct lmb lmb;" which is not used anywhere, so remove it. Signed-off-by: Simon Goldschmidt --- Changes in v7: None Changes in v6: None Changes in v5: None Changes in v4: None Changes in v2: - this patch is new in v2 include/lmb.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/lmb.h b/include/lmb.h index 62da85e716..1bb003e35e 100644 --- a/include/lmb.h +++ b/include/lmb.h @@ -28,8 +28,6 @@ struct lmb { struct lmb_region reserved; }; -extern struct lmb lmb; - extern void lmb_init(struct lmb *lmb); extern void lmb_init_and_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size, void *fdt_blob); From patchwork Mon Dec 17 19:06:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Goldschmidt X-Patchwork-Id: 1014704 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="RrUpBwWI"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43JW3B2SrSz9s3q for ; Tue, 18 Dec 2018 06:11:18 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id F3156C21EFF; Mon, 17 Dec 2018 19:09:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 44C9CC221C0; Mon, 17 Dec 2018 19:07:42 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 38AAAC21EFF; Mon, 17 Dec 2018 19:07:09 +0000 (UTC) Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by lists.denx.de (Postfix) with ESMTPS id D86C3C22104 for ; Mon, 17 Dec 2018 19:07:01 +0000 (UTC) Received: by mail-wm1-f68.google.com with SMTP id q26so310093wmf.5 for ; Mon, 17 Dec 2018 11:07:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=bSuK/v1z1Y7YSAbhhLpVgJv7jIaJsJVOkFJk/ROFMiQ=; b=RrUpBwWIUExKvnKy90MqQSE37SkedRXEY2TTp8MyFNQ9w0MGbqn4DYtfAA3ah+K/Ha 498HyqKq0wUSe0IS7V4Ot4ByCz4hy4PFVJQ4zj45E6nAvsdioTuLtgEgZ4UrUx6L34Li Udh4aunHyVM5CYnDMHL9h4NHpcJCZbCXde2v5ZsQX9fG/K9OK76DInnP8jZfnT7zS1Oc /yW3XI6kKWrJ288uDuXuq5ZSCF5CFFSb1aW829Pg97mziTfcYTIjDbCJjWaTk0l0KYKb rUeYumVUgcIX+8jMQDGSKefrFfCtBLeWqEj1fnuIrZbTMv491fbI9zxNwqniREZb7UK0 x0kQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=bSuK/v1z1Y7YSAbhhLpVgJv7jIaJsJVOkFJk/ROFMiQ=; b=bmEZ36HmIhoyCyhUYgQBqFMPqRdKuYGgdvlte+Mr2dBsFYi4AqUprDoLWaqpqW1rho T5g7zCQK1cEWgKLPNi8DdmxvV89jwjLvqTUwMka+05MmyBQ4NddjiPgBsPy8rfWvOPeu WfSP8gbqeCoO3Yi/9hZs/NHQhYI4Z4FxxiPvuC0gfBXccxUZVxAgIavoukU5JXJ4eWyG EoX+TkytmS7xUtn2OaNsNPv5Gy3uIiWSd/kcOgtZh7O5jN6FDfouUn1L+IN8Et+RzYEs CVkYOe694AbWvU6D4wMwzTMLQ9hhBj5xOaaSh+CsqhjWMa/za5aNCxY9B32H2xHhkEjR GQig== X-Gm-Message-State: AA+aEWapdtudzql2AE2yj4P6nqNQKRrGdQpK5awYSUWwB/mcv9NKKtII Q7mkT9yCrAUzt6Nr1w5Cbxc= X-Google-Smtp-Source: AFSGD/VP416Wj+Gtiw4baro4GdWdBj1Osmi2Pjx0mgi2sOUV6rcrgAW20XUayQVS04SHfFvZKZcSRA== X-Received: by 2002:a1c:4d12:: with SMTP id o18mr332831wmh.92.1545073621578; Mon, 17 Dec 2018 11:07:01 -0800 (PST) Received: from ubuntu.home ([2a02:8071:6a3:700:80b1:ba3d:111a:23c5]) by smtp.gmail.com with ESMTPSA id c13sm1287634wrb.38.2018.12.17.11.07.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 11:07:00 -0800 (PST) From: Simon Goldschmidt To: Tom Rini , u-boot@lists.denx.de, Joe Hershberger Date: Mon, 17 Dec 2018 20:06:38 +0100 Message-Id: <20181217190638.21672-10-simon.k.r.goldschmidt@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> References: <20181217190638.21672-1-simon.k.r.goldschmidt@gmail.com> Cc: Heinrich Schuchardt , Andrea Barisani Subject: [U-Boot] [PATCH v7 9/9] tftp: prevent overwriting reserved memory X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This fixes CVE-2018-18439 ("insufficient boundary checks in network image boot") by using lmb to check for a valid range to store received blocks. Signed-off-by: Simon Goldschmidt --- Changes in v7: - fix compiling without CONFIG_LMB Changes in v6: None Changes in v5: None Changes in v4: - this was patch 8, is now patch 7 - lines changed because v3 patch 7 got removed and MCAST_TFTP still exists Changes in v2: - this patch is new in v2 net/tftp.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/net/tftp.c b/net/tftp.c index 68ffd81414..a9335b1b7e 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -17,6 +17,8 @@ #include #endif +DECLARE_GLOBAL_DATA_PTR; + /* Well known TFTP port # */ #define WELL_KNOWN_PORT 69 /* Millisecs to timeout for lost pkt */ @@ -81,6 +83,10 @@ static ulong tftp_block_wrap; /* memory offset due to wrapping */ static ulong tftp_block_wrap_offset; static int tftp_state; +static ulong tftp_load_addr; +#ifdef CONFIG_LMB +static ulong tftp_load_size; +#endif #ifdef CONFIG_TFTP_TSIZE /* The file size reported by the server */ static int tftp_tsize; @@ -164,10 +170,11 @@ static void mcast_cleanup(void) #endif /* CONFIG_MCAST_TFTP */ -static inline void store_block(int block, uchar *src, unsigned len) +static inline int store_block(int block, uchar *src, unsigned int len) { ulong offset = block * tftp_block_size + tftp_block_wrap_offset; ulong newsize = offset + len; + ulong store_addr = tftp_load_addr + offset; #ifdef CONFIG_SYS_DIRECT_FLASH_TFTP int i, rc = 0; @@ -175,24 +182,32 @@ static inline void store_block(int block, uchar *src, unsigned len) /* start address in flash? */ if (flash_info[i].flash_id == FLASH_UNKNOWN) continue; - if (load_addr + offset >= flash_info[i].start[0]) { + if (store_addr >= flash_info[i].start[0]) { rc = 1; break; } } if (rc) { /* Flash is destination for this packet */ - rc = flash_write((char *)src, (ulong)(load_addr+offset), len); + rc = flash_write((char *)src, store_addr, len); if (rc) { flash_perror(rc); - net_set_state(NETLOOP_FAIL); - return; + return rc; } } else #endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */ { - void *ptr = map_sysmem(load_addr + offset, len); - + void *ptr; + +#ifdef CONFIG_LMB + if (store_addr < tftp_load_addr || + store_addr + len > tftp_load_addr + tftp_load_size) { + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return -1; + } +#endif + ptr = map_sysmem(store_addr, len); memcpy(ptr, src, len); unmap_sysmem(ptr); } @@ -203,6 +218,8 @@ static inline void store_block(int block, uchar *src, unsigned len) if (net_boot_file_size < newsize) net_boot_file_size = newsize; + + return 0; } /* Clear our state ready for a new transfer */ @@ -606,7 +623,11 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, timeout_count_max = tftp_timeout_count_max; net_set_timeout_handler(timeout_ms, tftp_timeout_handler); - store_block(tftp_cur_block - 1, pkt + 2, len); + if (store_block(tftp_cur_block - 1, pkt + 2, len)) { + eth_halt(); + net_set_state(NETLOOP_FAIL); + break; + } /* * Acknowledge the block just received, which will prompt @@ -695,6 +716,25 @@ static void tftp_timeout_handler(void) } } +/* Initialize tftp_load_addr and tftp_load_size from load_addr and lmb */ +static int tftp_init_load_addr(void) +{ +#ifdef CONFIG_LMB + struct lmb lmb; + phys_size_t max_size; + + lmb_init_and_reserve(&lmb, gd->bd->bi_dram[0].start, + gd->bd->bi_dram[0].size, (void *)gd->fdt_blob); + + max_size = lmb_get_unreserved_size(&lmb, load_addr); + if (!max_size) + return -1; + + tftp_load_size = max_size; +#endif + tftp_load_addr = load_addr; + return 0; +} void tftp_start(enum proto_t protocol) { @@ -791,7 +831,14 @@ void tftp_start(enum proto_t protocol) } else #endif { - printf("Load address: 0x%lx\n", load_addr); + if (tftp_init_load_addr()) { + eth_halt(); + net_set_state(NETLOOP_FAIL); + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return; + } + printf("Load address: 0x%lx\n", tftp_load_addr); puts("Loading: *\b"); tftp_state = STATE_SEND_RRQ; #ifdef CONFIG_CMD_BOOTEFI @@ -842,9 +889,15 @@ void tftp_start_server(void) { tftp_filename[0] = 0; + if (tftp_init_load_addr()) { + eth_halt(); + net_set_state(NETLOOP_FAIL); + puts("\nTFTP error: trying to overwrite reserved memory...\n"); + return; + } printf("Using %s device\n", eth_get_name()); printf("Listening for TFTP transfer on %pI4\n", &net_ip); - printf("Load address: 0x%lx\n", load_addr); + printf("Load address: 0x%lx\n", tftp_load_addr); puts("Loading: *\b");