From patchwork Wed Jan 19 01:42:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581593 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=K27kjEhG; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpMh0pwDz9sPC for ; Wed, 19 Jan 2022 12:44:00 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1A112837CF; Wed, 19 Jan 2022 02:43:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="K27kjEhG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4847483281; Wed, 19 Jan 2022 02:43:45 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd31.google.com (mail-io1-xd31.google.com [IPv6:2607:f8b0:4864:20::d31]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 25B4680636 for ; Wed, 19 Jan 2022 02:43:41 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd31.google.com with SMTP id z19so991923ioj.1 for ; Tue, 18 Jan 2022 17:43:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Cbt3ztpO4zBUyrBJv8jnvHuBCFj2weHycqvphThlv8c=; b=K27kjEhGRSBaxZlrKa2cjxJTUc3bimJOQD5sW65YHeAPflFvPqGVMp01oZkhrAfGa7 mJlpDB1twhqpvBZLphlBqqtRmpChrJXvk9Dx5y9uViB9H9U/lMVY/OnYqbPe6sC6D0M6 Vb+qe4jpCbMc9aejITgNvxhQQBiLhibLqZQ0A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Cbt3ztpO4zBUyrBJv8jnvHuBCFj2weHycqvphThlv8c=; b=fmP+s1kRb0Fi420V7BXf39Cffl85UpPqRFhuSonSU18pMhj36GEUtzbC8IOeRKy4Vd use79CY89aq4io4F9rQDNtR7isPnPRnwukPK5XbuYQ/BdcZ+Vd3Ay+7pPsFDARdNAfRe WgnVY6uQcBKnABITWiC/LgNZ+6+2s9FSuS32A5kRQhmNDfRmaV24wrKjz3iy6ks0Q8Xv /22uW+mYwVwnpMJbMhGTzJWYk0qsKPdTrtEC3NU/6oLCLGcVCSt1MBpX8HdWCBmc+J3V xYtGQZvhGPEqUVr787liCuSswjYpJy2qt50rTSy1TKB11fMHiR2/P3Jvikecg2VckbUe EF2A== X-Gm-Message-State: AOAM532LJ2maJuqzrO1j3pkGFYCDtPeSQkIPS3Nqb6JmRCCyjL90mL3w FVYwpzLbCFptnFhbz+9xq1YlBneH6uTQ8A== X-Google-Smtp-Source: ABdhPJx9cZJ6rkRAgdGVcyFIRd9/OwW9+e8wu6n0bybD7fblQIEXboROkF1jNE/gFbHzIzSfcTan9A== X-Received: by 2002:a05:6638:3c4:: with SMTP id r4mr13499560jaq.45.1642556619796; Tue, 18 Jan 2022 17:43:39 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:39 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 01/31] str: Move string tests to the string module Date: Tue, 18 Jan 2022 18:42:45 -0700 Message-Id: <20220119014315.1938157-2-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean A few string tests were added to the print module by mistake. Move them. Signed-off-by: Simon Glass --- (no changes since v1) test/print_ut.c | 40 ---------------------------------------- test/str_ut.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/test/print_ut.c b/test/print_ut.c index 7b2e7bb152c..b52fdf7ae05 100644 --- a/test/print_ut.c +++ b/test/print_ut.c @@ -333,26 +333,6 @@ static int print_do_hex_dump(struct unit_test_state *uts) } PRINT_TEST(print_do_hex_dump, UT_TESTF_CONSOLE_REC); -static int print_itoa(struct unit_test_state *uts) -{ - ut_asserteq_str("123", simple_itoa(123)); - ut_asserteq_str("0", simple_itoa(0)); - ut_asserteq_str("2147483647", simple_itoa(0x7fffffff)); - ut_asserteq_str("4294967295", simple_itoa(0xffffffff)); - - /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ -#ifdef CONFIG_PHYS_64BIT - if (sizeof(ulong) == 8) { - ut_asserteq_str("9223372036854775807", - simple_itoa((1UL << 63) - 1)); - ut_asserteq_str("18446744073709551615", simple_itoa(-1)); - } -#endif /* CONFIG_PHYS_64BIT */ - - return 0; -} -PRINT_TEST(print_itoa, 0); - static int snprint(struct unit_test_state *uts) { char buf[10] = "xxxxxxxxx"; @@ -367,26 +347,6 @@ static int snprint(struct unit_test_state *uts) } PRINT_TEST(snprint, 0); -static int print_xtoa(struct unit_test_state *uts) -{ - ut_asserteq_str("7f", simple_xtoa(127)); - ut_asserteq_str("00", simple_xtoa(0)); - ut_asserteq_str("7fffffff", simple_xtoa(0x7fffffff)); - ut_asserteq_str("ffffffff", simple_xtoa(0xffffffff)); - - /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ -#ifdef CONFIG_PHYS_64BIT - if (sizeof(ulong) == 8) { - ut_asserteq_str("7fffffffffffffff", - simple_xtoa((1UL << 63) - 1)); - ut_asserteq_str("ffffffffffffffff", simple_xtoa(-1)); - } -#endif /* CONFIG_PHYS_64BIT */ - - return 0; -} -PRINT_TEST(print_xtoa, 0); - int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(print_test); diff --git a/test/str_ut.c b/test/str_ut.c index d2840d51524..6c817f6f72f 100644 --- a/test/str_ut.c +++ b/test/str_ut.c @@ -202,6 +202,46 @@ static int str_dectoul(struct unit_test_state *uts) } STR_TEST(str_dectoul, 0); +static int str_itoa(struct unit_test_state *uts) +{ + ut_asserteq_str("123", simple_itoa(123)); + ut_asserteq_str("0", simple_itoa(0)); + ut_asserteq_str("2147483647", simple_itoa(0x7fffffff)); + ut_asserteq_str("4294967295", simple_itoa(0xffffffff)); + + /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ +#ifdef CONFIG_PHYS_64BIT + if (sizeof(ulong) == 8) { + ut_asserteq_str("9223372036854775807", + simple_itoa((1UL << 63) - 1)); + ut_asserteq_str("18446744073709551615", simple_itoa(-1)); + } +#endif /* CONFIG_PHYS_64BIT */ + + return 0; +} +STR_TEST(str_itoa, 0); + +static int str_xtoa(struct unit_test_state *uts) +{ + ut_asserteq_str("7f", simple_xtoa(127)); + ut_asserteq_str("00", simple_xtoa(0)); + ut_asserteq_str("7fffffff", simple_xtoa(0x7fffffff)); + ut_asserteq_str("ffffffff", simple_xtoa(0xffffffff)); + + /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ +#ifdef CONFIG_PHYS_64BIT + if (sizeof(ulong) == 8) { + ut_asserteq_str("7fffffffffffffff", + simple_xtoa((1UL << 63) - 1)); + ut_asserteq_str("ffffffffffffffff", simple_xtoa(-1)); + } +#endif /* CONFIG_PHYS_64BIT */ + + return 0; +} +STR_TEST(str_xtoa, 0); + int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(str_test); From patchwork Wed Jan 19 01:42:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581594 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=GZCvTF0h; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpMr2zRyz9sPC for ; Wed, 19 Jan 2022 12:44:08 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 17A29837CC; Wed, 19 Jan 2022 02:43:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="GZCvTF0h"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id EBCDB835CA; Wed, 19 Jan 2022 02:43:45 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2f.google.com (mail-io1-xd2f.google.com [IPv6:2607:f8b0:4864:20::d2f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E0F29801EA for ; Wed, 19 Jan 2022 02:43:41 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2f.google.com with SMTP id a12so943235iod.9 for ; Tue, 18 Jan 2022 17:43:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vg4HZSYzyDvZUu2a/b6tj0njgGw25RIkFnHNyc7BUwQ=; b=GZCvTF0hcI+mQvBcMGIArKgAKW85VYC2Ckmpq7IPJ/yI93UrivhYXysIQLlgubjJbC y5gYRaWVl5NxdzninTfjgzLNLaTD689uGZrr6X4/rmjcr8J0PKvtVcZ3G3e3Hjo9ss7h 1lSdc4NNy6gKK4jZIHEG4BzD19NTpooOfSnlw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vg4HZSYzyDvZUu2a/b6tj0njgGw25RIkFnHNyc7BUwQ=; b=vF7HIIte+lD5BMfGksU/4SuusO8y0+GIizeRoL2nJJGRi1GMfV4vLLA8aEgxt2DwUS 4V+cWWB20bZ+fT6Y1W0JLFsCvozcnqMczl8E7f3DhvMPrl7vwwR1JW5V03DqpG4o1WHc e6lH41QJqTgv5jIqswuFBKnol7jaNlJk/EByN4lsCho0tNayJWLYlAk/JMFCn1UKx3tM SOgc76Zi1zKXXIUu7KReDwpx0kNMGQkGK/0UrjsnJrgfPYRxSef7/uZSUKkoTKFqg58E FS7ojb/fIM/2QcS4AKN3Y4JRkZJ8+0FPdoGKH/OM6A8N7/rcTgGa8EfamsEQZkscZAfU H8bw== X-Gm-Message-State: AOAM530CUpBQ7eOQTbtrhdRHGSuGypaYz6a/YB238R7o3K4cJOrNEQ96 AdSLOpaFzrrJ+tBU0PDI7Ch2Zz5bNotWHA== X-Google-Smtp-Source: ABdhPJxeq5C3+rMpchuxkUUNq03QjlHrCr23ivjVFtDTOPLSI2+f/w4N56W7203RnWHEwS9whadx/g== X-Received: by 2002:a6b:740b:: with SMTP id s11mr14165525iog.120.1642556620568; Tue, 18 Jan 2022 17:43:40 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:40 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 02/31] test: Add tests for trailing_strtol() Date: Tue, 18 Jan 2022 18:42:46 -0700 Message-Id: <20220119014315.1938157-3-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean This function currently has no tests. Add some. Signed-off-by: Simon Glass --- (no changes since v1) include/vsprintf.h | 4 ++-- test/str_ut.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/vsprintf.h b/include/vsprintf.h index 8bfafa0d33f..01d2248e04d 100644 --- a/include/vsprintf.h +++ b/include/vsprintf.h @@ -99,7 +99,7 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base); * For example, "abc123" would return 123. * * @str: String to exxamine - * @return training number if found, else -1 + * @return trailing number if found, else -1 */ long trailing_strtol(const char *str); @@ -114,7 +114,7 @@ long trailing_strtol(const char *str); * @str: String to exxamine * @end: Pointer to end of string to examine, or NULL to use the * whole string - * @return training number if found, else -1 + * @return trailing number if found, else -1 */ long trailing_strtoln(const char *str, const char *end); diff --git a/test/str_ut.c b/test/str_ut.c index 6c817f6f72f..9674a59f2a6 100644 --- a/test/str_ut.c +++ b/test/str_ut.c @@ -242,6 +242,25 @@ static int str_xtoa(struct unit_test_state *uts) } STR_TEST(str_xtoa, 0); +static int str_trailing(struct unit_test_state *uts) +{ + char str1[] = "abc123def"; + + ut_asserteq(-1, trailing_strtol("")); + ut_asserteq(-1, trailing_strtol("123")); + ut_asserteq(123, trailing_strtol("abc123")); + ut_asserteq(4, trailing_strtol("12c4")); + ut_asserteq(-1, trailing_strtol("abd")); + ut_asserteq(-1, trailing_strtol("abc123def")); + + ut_asserteq(-1, trailing_strtoln(str1, NULL)); + ut_asserteq(123, trailing_strtoln(str1, str1 + 6)); + ut_asserteq(-1, trailing_strtoln(str1, str1 + 9)); + + return 0; +} +STR_TEST(str_trailing, 0); + int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(str_test); From patchwork Wed Jan 19 01:42:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581595 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Ea0gy88W; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpN315fbz9sPC for ; Wed, 19 Jan 2022 12:44:19 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9A782837E9; Wed, 19 Jan 2022 02:43:59 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Ea0gy88W"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id EC6E7837CF; Wed, 19 Jan 2022 02:43:48 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd29.google.com (mail-io1-xd29.google.com [IPv6:2607:f8b0:4864:20::d29]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id CC3F08303A for ; Wed, 19 Jan 2022 02:43:42 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd29.google.com with SMTP id z19so991999ioj.1 for ; Tue, 18 Jan 2022 17:43:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DVK862rKaHR+OZMTXDfBWXtgOHjZyxARtD3NzJpld4U=; b=Ea0gy88WalEmxtE4j3pwt66g4hAMvKw9FFP9CBFFGwgxpzLXLHZ6DwDql8jSp/MFn3 I32L2tfWzHwXB3wXz6oDcOdLJSSvRzJH4FDd1M8xn02sN3fqSm1KXSZJd8lbHwywRf0y l9iwVIXXGReZJbQNlwSKefyFUhC/H4Vg91udk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DVK862rKaHR+OZMTXDfBWXtgOHjZyxARtD3NzJpld4U=; b=57QMx1RGUExBfh0hOyygk8iOG/m+38vmGHz2ykhW7zsxUXP8asS2bGz5QpzWhZlJCC 1aKx2OVqavP3hLBGV2tnFepDPsk6XevcszXkfKdlUCsWGaURMONwuFtYLE+CIxx3XVpL cafvo3/cKlZ5te5Pxbgwe9RWjpkMHJn4hAY3VPgHxQtVk3ZgJb7w3RfUfypElGz0mvSX fbBbgKbd0n9wDnzwvAAPFOKoQKE5GcmDflgLjqbaVTzbISuzc/Qo9YJKJ0B3LF7wYSly b6xxklT97B67ZMgN2gwD/hq1xD9lHDNu0L9/0QdzazE4XHdtbIK2oKoFZdgu6AK+EMVj mfjg== X-Gm-Message-State: AOAM531T0t/x3RCc1G3zOyfIgAcLHr0fYX7S8O9WCMLytWPdSvWo/Y3i fjw+SNfb/h/8CQD7mBybIM+uuakQ/sqf1A== X-Google-Smtp-Source: ABdhPJy/3FQBWFUFx/IzoWwJcP38qfTHghWFFVs5j6JvzZrqwFs7vcFKYOEQiXDEXPcT3007eZJ8LQ== X-Received: by 2002:a5e:df4b:: with SMTP id g11mr6766362ioq.146.1642556621464; Tue, 18 Jan 2022 17:43:41 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:41 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 03/31] str: Fix a few bugs in trailing_strtoln() Date: Tue, 18 Jan 2022 18:42:47 -0700 Message-Id: <20220119014315.1938157-4-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean At present this has a minor bug in that it reads the byte before the start of the string. Also it doesn't handle a non-numeric prefix which is only one character long. Fix these bugs with a reworked implementation. Add a test for the second case. The first one is hard to test. Signed-off-by: Simon Glass --- (no changes since v1) lib/strto.c | 11 ++++++----- test/str_ut.c | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/strto.c b/lib/strto.c index 7bba1e3e549..58fc10ecaea 100644 --- a/lib/strto.c +++ b/lib/strto.c @@ -189,11 +189,12 @@ long trailing_strtoln(const char *str, const char *end) if (!end) end = str + strlen(str); - if (isdigit(end[-1])) { - for (p = end - 1; p > str; p--) { - if (!isdigit(*p)) - return dectoul(p + 1, NULL); - } + p = end - 1; + if (p > str && isdigit(*p)) { + do { + if (!isdigit(p[-1])) + return dectoul(p, NULL); + } while (--p > str); } return -1; diff --git a/test/str_ut.c b/test/str_ut.c index 9674a59f2a6..058b3594379 100644 --- a/test/str_ut.c +++ b/test/str_ut.c @@ -257,6 +257,8 @@ static int str_trailing(struct unit_test_state *uts) ut_asserteq(123, trailing_strtoln(str1, str1 + 6)); ut_asserteq(-1, trailing_strtoln(str1, str1 + 9)); + ut_asserteq(3, trailing_strtol("a3")); + return 0; } STR_TEST(str_trailing, 0); From patchwork Wed Jan 19 01:42:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581597 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=C3HwnzLG; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpNS2fQqz9sPC for ; Wed, 19 Jan 2022 12:44:40 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 923CB837E4; Wed, 19 Jan 2022 02:44:13 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="C3HwnzLG"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 04B6A801EA; Wed, 19 Jan 2022 02:43:52 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd33.google.com (mail-io1-xd33.google.com [IPv6:2607:f8b0:4864:20::d33]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DCE7783214 for ; Wed, 19 Jan 2022 02:43:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd33.google.com with SMTP id p7so989206iod.2 for ; Tue, 18 Jan 2022 17:43:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=i6Nxn1lykz2X9TaqlZ2K+L0UmKn0sM1AJ2U1ITNRCxQ=; b=C3HwnzLGrHRacXaM0tgR7ZFaNp63W6ShYJFOVMbgl7pPHsFk8oO7kar0KeDCSAJIVn HwiIclOMXML0mvZgMYKRDUzszBXEJs/IWSBuy0HLjRXlHxxrWU2KrKMR+iTSwasdGKlP +fhDjVllHvYK7k6b5Hj0qX/fnGi8QZQFxcUkU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=i6Nxn1lykz2X9TaqlZ2K+L0UmKn0sM1AJ2U1ITNRCxQ=; b=EKFd67acfJJoOi0qDX10FOyb3F6in7dLr3DdCegng6YnmCBypka1hTAMvQhJ1foovN 6J0PHqQApdnoCmPs1xGvkl3rr4OKxX8Mwd0tg4cqYlxT6f26XNnPpj5hDInspHuJ8qFf TVjMTTZh7l4IxHAsNIHyjGZ+t/2EskVuwLnb9kgpjoR5qWPOzLiGPnLg4GrOL+RXjaj8 hzRfIOTAVVby4d6sPApdpBQZdSYqB1D04j30cxJqmd3uSQXGV+hNA5V3oWoajrpGL0yo YA6RYqd7egGvCUOOn8DveZwtOQhPScmm/E4xt9qToS4FjvSWFPrd/U9+gMKpRtZtmbRz HU5A== X-Gm-Message-State: AOAM531BwODuqQu/p79TquTgAp5Mnr3tHyxuSlkD3zZ4fpNW3jKSCyjV fJctGa9kYA3uTrcOwwg7tZfP5wa+vxNNVw== X-Google-Smtp-Source: ABdhPJwuIozf0mML9ot2jDJqCLwuygSE9TR42DteM3dh01PX659klTXv8MJ8EA30tU0Um/p36Lmf8Q== X-Received: by 2002:a5d:9f01:: with SMTP id q1mr14100523iot.144.1642556622539; Tue, 18 Jan 2022 17:43:42 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:42 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 04/31] lib: Add a way to find the postiion of a trailing number Date: Tue, 18 Jan 2022 18:42:48 -0700 Message-Id: <20220119014315.1938157-5-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean At present it is not possible to find out which part of the string is the number part and which is before it. Add a new variant which provides this feature, so we can separate the two in the caller. Signed-off-by: Simon Glass --- Changes in v3: - Change the function to return a pointer to the first digit - Add some tests, including one for 'abc123def456' include/vsprintf.h | 18 ++++++++++++++++++ lib/strto.c | 14 ++++++++++++-- test/str_ut.c | 13 ++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/include/vsprintf.h b/include/vsprintf.h index 01d2248e04d..ce7a7aaa1cc 100644 --- a/include/vsprintf.h +++ b/include/vsprintf.h @@ -118,6 +118,24 @@ long trailing_strtol(const char *str); */ long trailing_strtoln(const char *str, const char *end); +/** + * trailing_strtoln_end() - extract trailing integer from a fixed-length string + * + * Given a fixed-length string this finds a trailing number on the string + * and returns it. For example, "abc123" would return 123. Only the + * characters between @str and @end - 1 are examined. If @end is NULL, it is + * set to str + strlen(str). + * + * @str: String to exxamine + * @end: Pointer to end of string to examine, or NULL to use the + * whole string + * @endp: If non-NULL, this is set to point to the character where the + * number starts, e.g. for "mmc0" this would be point to the '0'; if no + * trailing number is found, it is set to the end of the string + * @return training number if found, else -1 + */ +long trailing_strtoln_end(const char *str, const char *end, char const **endp); + /** * panic() - Print a message and reset/hang * diff --git a/lib/strto.c b/lib/strto.c index 58fc10ecaea..72cfef660fc 100644 --- a/lib/strto.c +++ b/lib/strto.c @@ -183,7 +183,7 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base) return simple_strtoull(cp, endp, base); } -long trailing_strtoln(const char *str, const char *end) +long trailing_strtoln_end(const char *str, const char *end, char const **endp) { const char *p; @@ -192,14 +192,24 @@ long trailing_strtoln(const char *str, const char *end) p = end - 1; if (p > str && isdigit(*p)) { do { - if (!isdigit(p[-1])) + if (!isdigit(p[-1])) { + if (endp) + *endp = p; return dectoul(p, NULL); + } } while (--p > str); } + if (endp) + *endp = end; return -1; } +long trailing_strtoln(const char *str, const char *end) +{ + return trailing_strtoln_end(str, end, NULL); +} + long trailing_strtol(const char *str) { return trailing_strtoln(str, NULL); diff --git a/test/str_ut.c b/test/str_ut.c index 058b3594379..5a844347c2b 100644 --- a/test/str_ut.c +++ b/test/str_ut.c @@ -244,7 +244,9 @@ STR_TEST(str_xtoa, 0); static int str_trailing(struct unit_test_state *uts) { - char str1[] = "abc123def"; + const char str1[] = "abc123def"; + const char str2[] = "abc123def456"; + const char *end; ut_asserteq(-1, trailing_strtol("")); ut_asserteq(-1, trailing_strtol("123")); @@ -259,6 +261,15 @@ static int str_trailing(struct unit_test_state *uts) ut_asserteq(3, trailing_strtol("a3")); + ut_asserteq(123, trailing_strtoln_end(str1, str1 + 6, &end)); + ut_asserteq(3, end - str1); + + ut_asserteq(-1, trailing_strtoln_end(str1, str1 + 7, &end)); + ut_asserteq(7, end - str1); + + ut_asserteq(456, trailing_strtoln_end(str2, NULL, &end)); + ut_asserteq(9, end - str2); + return 0; } STR_TEST(str_trailing, 0); From patchwork Wed Jan 19 01:42:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581596 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=kXQKvhda; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpNG1YPCz9sPC for ; Wed, 19 Jan 2022 12:44:30 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D103982F5E; Wed, 19 Jan 2022 02:44:04 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="kXQKvhda"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B2F09801EA; Wed, 19 Jan 2022 02:43:50 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-io1-xd30.google.com (mail-io1-xd30.google.com [IPv6:2607:f8b0:4864:20::d30]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C2ED183563 for ; Wed, 19 Jan 2022 02:43:44 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd30.google.com with SMTP id y22so957770iof.7 for ; Tue, 18 Jan 2022 17:43:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=tPETFA/JjlffbQl9ut23/SDQrwhirkUj8rK6m21fi/A=; b=kXQKvhdaFnPw806kmKHjzfNzt5sk1WpdoEeoU4mzwugsc9IOEDBSdGhTRCg9hOXO/+ bGPha5Qv5OaEcxyV59YcOeNWIUQ9yIzM/wzvQ9G12/2w7+Tfg6iqE+JKdaOO8ShvVYtZ LqvJKDWQIfahjX+bGh7oPk8LOgwiAFsgGbPlY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=tPETFA/JjlffbQl9ut23/SDQrwhirkUj8rK6m21fi/A=; b=DF4K/UWDPLjABeK7J1i6lTICwn6mb8tCP/LoGB+q5bGwFlmlvh05k/3lvmz7hrGzqC lsToYi07XqGCxB0zRgUEm6oa4gimyGceIElWzCvFq/0DmnmsGUhEn6Clg7S5TbaNfWpW xJNUGl0BG+2IbMxAlZzIkjuKaMTxQFlQo+caEUXdltJP9Gi7VYywijfR5fv8At+necCu kUVaqz39ZcZGkPNe5RpVL8vxP621/iuzl+BADBFfbdPSamcRAT/JMbFrOW1RQ4N4q0eZ PxZ098dx81ave17RGXk7b8HlMuloCdo8d5AyE28xJgzxUGeFDOZA3Ef1r92e5KeKEDD7 KbTg== X-Gm-Message-State: AOAM532Ce3kx6Hls32yPGtXYXpf4HvKVb/IQhiW/zF6x1uPi7ZxBsqVU u29ET7rAWmwK5nJgz8SlcbOAV8IstqXNTA== X-Google-Smtp-Source: ABdhPJzFeCDFbwi0maIDvYp2joJH05lGE+q3W8b1z2tM/ECymH7rM4QD/pox7LUsUWhFmsppCIWPYQ== X-Received: by 2002:a05:6602:200b:: with SMTP id y11mr14104858iod.121.1642556623367; Tue, 18 Jan 2022 17:43:43 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:43 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass , Marek Vasut , Pavel Herrmann Subject: [PATCH v3 05/31] dm: core: Rename uclass_get_by_name_len() Date: Tue, 18 Jan 2022 18:42:49 -0700 Message-Id: <20220119014315.1938157-6-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean It seems that namelen is more common in U-Boot. Rename this function to fit in better. Signed-off-by: Simon Glass --- Changes in v3: - Add new patch to rename uclass_get_by_name_len() drivers/core/uclass.c | 7 ++++--- include/dm/uclass.h | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 336ea8d243d..563ff9b2856 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -180,14 +180,15 @@ void uclass_set_priv(struct uclass *uc, void *priv) uc->priv_ = priv; } -enum uclass_id uclass_get_by_name_len(const char *name, int len) +enum uclass_id uclass_get_by_namelen(const char *name, int len) { int i; for (i = 0; i < UCLASS_COUNT; i++) { struct uclass_driver *uc_drv = lists_uclass_lookup(i); - if (uc_drv && !strncmp(uc_drv->name, name, len)) + if (uc_drv && !strncmp(uc_drv->name, name, len) && + strlen(uc_drv->name) == len) return i; } @@ -196,7 +197,7 @@ enum uclass_id uclass_get_by_name_len(const char *name, int len) enum uclass_id uclass_get_by_name(const char *name) { - return uclass_get_by_name_len(name, strlen(name)); + return uclass_get_by_namelen(name, strlen(name)); } int dev_get_uclass_index(struct udevice *dev, struct uclass **ucp) diff --git a/include/dm/uclass.h b/include/dm/uclass.h index 7f33c34214e..7876e9175e7 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -173,13 +173,13 @@ int uclass_get(enum uclass_id key, struct uclass **ucp); const char *uclass_get_name(enum uclass_id id); /** - * uclass_get_by_name_len() - Look up a uclass by its partial driver name + * uclass_get_by_namelen() - Look up a uclass by its driver name * * @name: Name to look up - * @len: Length of the partial name - * Return: the associated uclass ID, or UCLASS_INVALID if not found + * @len: Length of @name (the uclass driver name must have the same length) + * @returns the associated uclass ID, or UCLASS_INVALID if not found */ -enum uclass_id uclass_get_by_name_len(const char *name, int len); +enum uclass_id uclass_get_by_namelen(const char *name, int len); /** * uclass_get_by_name() - Look up a uclass by its driver name From patchwork Wed Jan 19 01:42:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581599 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=EEYlXOPH; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpNs0lj5z9sPC for ; Wed, 19 Jan 2022 12:45:01 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C49AA834A0; Wed, 19 Jan 2022 02:44:21 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="EEYlXOPH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3DC4683281; Wed, 19 Jan 2022 02:43:54 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-io1-xd32.google.com (mail-io1-xd32.google.com [IPv6:2607:f8b0:4864:20::d32]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id D3026836D8 for ; Wed, 19 Jan 2022 02:43:45 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd32.google.com with SMTP id y22so957814iof.7 for ; Tue, 18 Jan 2022 17:43:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vpWxnkJksBEvJvRtz4b8OxOPdsYHs6x70ZWl6eLP7rA=; b=EEYlXOPHA2iN3NULnHILLe7y1oPxZ3uOphVCLRKuicX6vw61N2MbI7WvF2ERZfoybS zRmdX9XwELIVLL+tw3JkJOkud0akyLOMBHwFmvj3jcrt6OgXYkLy5Lc6XZagTMrJLJ/V rHIKGIifNogLNPusOTVUwqhtxCChpSrgtykHY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vpWxnkJksBEvJvRtz4b8OxOPdsYHs6x70ZWl6eLP7rA=; b=XwgrlXGOOvKBXTzxI36ym6g025WRqdKU4wAodj9KpRSNIa7wTCkjFmovFo/OdGxExS MmZPWqgEdQsv2JtP+tUi7XpARkJKi2+FjZkmJj0jXA9pD0e3ftFLWMt7k8s7sirO+C0y uNHS4TfSB3lF6lH+qykr/SlaAa9zaSrYvFTatgk57n4DP/Eaqq7Kxo4Pt7hlnAkTL+I1 7SRk35wShTUMh1wtXdP8WOlzj3e8Uh2Fpkq19hCM3iDvoM8NZmFZ+7/UTJQQdodqHBDY 0TCJUZktMma0+dKqiWG5vjcH2mdUayd0wCuhvG3Kh3VEXzU5c6ZPqdK/vlgUN0OmJslj yabQ== X-Gm-Message-State: AOAM533kXmQGb2KWmbcDv9ioQLJ4yB87ObFJRbIf89aFhqAKkuZ/hMY3 6JquOoQvidIqbvsbhQHNtlcAjQ/xLwEg5A== X-Google-Smtp-Source: ABdhPJySBUVm9srJmJwpvQjBHTDRvFZZM4PJvJGhG9b8v4EplUUqNDeU3O8MrPRTn+cIy0WnCPksyw== X-Received: by 2002:a6b:b7d4:: with SMTP id h203mr9366818iof.193.1642556624262; Tue, 18 Jan 2022 17:43:44 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:44 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass , Marek Vasut , Pavel Herrmann Subject: [PATCH v3 06/31] dm: core: Allow finding a uclass device by partial name Date: Tue, 18 Jan 2022 18:42:50 -0700 Message-Id: <20220119014315.1938157-7-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean In some cases two devices are related and the only way to tell is to check that the names partially patch. Add a way to check this without needing to create a new string for the comparison. Fix the comment for device_find_child_by_namelen() while we are here. Signed-off-by: Simon Glass --- Changes in v3: - Add new patch to support finding a uclass device by partial name drivers/core/uclass.c | 13 ++++++++++--- include/dm/device.h | 2 +- include/dm/uclass-internal.h | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 563ff9b2856..a0d3840802b 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -274,8 +274,8 @@ int uclass_find_next_device(struct udevice **devp) return 0; } -int uclass_find_device_by_name(enum uclass_id id, const char *name, - struct udevice **devp) +int uclass_find_device_by_namelen(enum uclass_id id, const char *name, int len, + struct udevice **devp) { struct uclass *uc; struct udevice *dev; @@ -289,7 +289,8 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name, return ret; uclass_foreach_dev(dev, uc) { - if (!strcmp(dev->name, name)) { + if (!strncmp(dev->name, name, len) && + strlen(dev->name) == len) { *devp = dev; return 0; } @@ -298,6 +299,12 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name, return -ENODEV; } +int uclass_find_device_by_name(enum uclass_id id, const char *name, + struct udevice **devp) +{ + return uclass_find_device_by_namelen(id, name, strlen(name), devp); +} + int uclass_find_next_free_seq(struct uclass *uc) { struct udevice *dev; diff --git a/include/dm/device.h b/include/dm/device.h index 435a1114f1c..30703af96e4 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -791,7 +791,7 @@ int device_find_first_child_by_uclass(const struct udevice *parent, struct udevice **devp); /** - * device_find_child_by_name() - Find a child by device name + * device_find_child_by_namelen() - Find a child by device name * * @parent: Parent device to search * @name: Name to look for diff --git a/include/dm/uclass-internal.h b/include/dm/uclass-internal.h index fb0edcc2969..1118f64bdfd 100644 --- a/include/dm/uclass-internal.h +++ b/include/dm/uclass-internal.h @@ -154,6 +154,22 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp); */ int uclass_find_next_device(struct udevice **devp); +/** + * uclass_find_device_by_namelen() - Find uclass device based on ID and name + * + * This searches for a device with the exactly given name. + * + * The device is NOT probed, it is merely returned. + * + * @id: ID to look up + * @name: name of a device to find + * @len: Length of @name (the uclass driver name must have the same length) + * @devp: Returns pointer to device (the first one with the name) + * @return 0 if OK, -ve on error + */ +int uclass_find_device_by_namelen(enum uclass_id id, const char *name, int len, + struct udevice **devp); + /** * uclass_find_device_by_name() - Find uclass device based on ID and name * From patchwork Wed Jan 19 01:42:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581598 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=E2qk6+VI; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpNf6D53z9sPC for ; Wed, 19 Jan 2022 12:44:50 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id B4C6A836E6; Wed, 19 Jan 2022 02:44:17 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="E2qk6+VI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 41BCB801EA; Wed, 19 Jan 2022 02:43:53 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2b.google.com (mail-io1-xd2b.google.com [IPv6:2607:f8b0:4864:20::d2b]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 95C5283281 for ; Wed, 19 Jan 2022 02:43:46 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2b.google.com with SMTP id a12so943445iod.9 for ; Tue, 18 Jan 2022 17:43:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EVjUHwY2iY87zs7vKphngWY6xkzZYwQbqw9YMse8+mQ=; b=E2qk6+VI0PD4Mnmp0W2dP3rQxmO88vG/pGaSOEPXtMv5TOFxdHL2h4CZ2e6Fs8IRnQ 58PWUh0sNykiu1dJvjWf2tqbaUpcFoAyZ8Hb8O0uSGXPfF6Jmj2nGneYOClYZoeqoCVd kWmYvfYYFAePegztjaZeSF77peIiQIljsnXOk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EVjUHwY2iY87zs7vKphngWY6xkzZYwQbqw9YMse8+mQ=; b=MIB8UvxrKZZYBijjTLH0dpgpQd8E8pjFbbNQT0KUrYf98bi7cV3GZ+FX6suPtA3vDk NVIWhUNXlBVJsvHWLfZlWFCg3NnwrYq4jWNx8RW5WEkR1FzBachBjrxWiEWK/ZTpvdlJ Vdw6l5+3j4wQ4/L+LuI4A6vYXXw9NwYTbZ0W8ZnBPiXxYKbSC7+7U+Jmd99thFKiNvUd bb3D4isckg9gyJ4gHfDQYEtwHi8XOGXLh4BLp6qdIDJAk/u48vj4JUVpZbifyTs2HGlF /zJCp/Hp3HvlaDpIUU7Cvl/4XFoz6o5aeRJ+HhZYig4P4NYXQh/lvkPgYljcWyiHaPe/ y/sQ== X-Gm-Message-State: AOAM530BIUClYc7paEg470k4pPvmUR5uRGsxrzzwojRcT5AQVDxD5lHG IUcw618zWJOWbVlJBeiJHBpfI10EgUmPjA== X-Google-Smtp-Source: ABdhPJyEjbHZtzy3ZuiXCeu2QlolnQ+PeXHb2GZUTc5h+l0e/QUrVvMn5/5vdHwdRZTFC8sMVtHUFQ== X-Received: by 2002:a02:962d:: with SMTP id c42mr5329911jai.118.1642556625136; Tue, 18 Jan 2022 17:43:45 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:44 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 07/31] test: fastboot: Avoid using mmc1 Date: Tue, 18 Jan 2022 18:42:51 -0700 Message-Id: <20220119014315.1938157-8-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean The bootflow tests need to use an MMC with an associated backing file containing a filesystem. Update the fastboot tests to cope with this. Signed-off-by: Simon Glass --- (no changes since v1) test/dm/fastboot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/dm/fastboot.c b/test/dm/fastboot.c index e7f8c362b85..758538d0e85 100644 --- a/test/dm/fastboot.c +++ b/test/dm/fastboot.c @@ -81,9 +81,9 @@ static int dm_test_fastboot_mmc_part(struct unit_test_state *uts) &part_info, response)); ut_asserteq(0, fastboot_mmc_get_part_info("0.0:0", &fb_dev_desc, &part_info, response)); - ut_asserteq(0, fastboot_mmc_get_part_info("1", &fb_dev_desc, + ut_asserteq(0, fastboot_mmc_get_part_info("2", &fb_dev_desc, &part_info, response)); - ut_asserteq(0, fastboot_mmc_get_part_info("1.0", &fb_dev_desc, + ut_asserteq(0, fastboot_mmc_get_part_info("2.0", &fb_dev_desc, &part_info, response)); ut_asserteq(1, fastboot_mmc_get_part_info(":1", &fb_dev_desc, &part_info, response)); From patchwork Wed Jan 19 01:42:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581601 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=cF/Igf3c; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpPD6KvKz9sPC for ; Wed, 19 Jan 2022 12:45:20 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 75BFD837B6; Wed, 19 Jan 2022 02:44:27 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="cF/Igf3c"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 249A7836CF; Wed, 19 Jan 2022 02:43:57 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-io1-xd29.google.com (mail-io1-xd29.google.com [IPv6:2607:f8b0:4864:20::d29]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 66B46836E6 for ; Wed, 19 Jan 2022 02:43:47 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd29.google.com with SMTP id w7so967533ioj.5 for ; Tue, 18 Jan 2022 17:43:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Ru3Yz7/9Izcohxdw0moOhYO92yJXEWW7vNDjwBQdrJQ=; b=cF/Igf3cRNqFmjzpauxQbJjVPMBZ/Gmz0IPAifY5ayFndLn0t7GTi9jBXFTEQSbC2b keZd3soAAkdv0W66qW8aUaEe+oDp/4Ig2p8GAWtCOIs83TW6xYuZi01Mzq1OcK1magoF t7+S2eZh4UfKXetK+pmT+e71Gi2KmJbFs9YeM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Ru3Yz7/9Izcohxdw0moOhYO92yJXEWW7vNDjwBQdrJQ=; b=HbJc69xuNRaohD1i6wy4TXyIteOwTJsB7j9ABvtJDkfNDZ8zyqFk4NRfwd6oe2Q39t yKj7ptUHzQSEKN2NHPi18fdfoADowcKkUharZoCsxmavc5N9+YcV33cNpeJFtjBnXR8k nEDIphd95fJc4hl3j2I/HA96NfIWfn6uqudbkW4nCsSKSoMakqPabVqeBL7JmonQGqrZ /9lfawttVwQweF4gYrgX716RcbpPVclOa9R5XNW2C1kgunkdTJ8ygok1AzQOB4RoURvC p1slUrewfjsWuSFOdeVks+foPsBNLVnAYrb+WrDMCUAdLppDRvtxCThp/ndEkmvdqIua w44g== X-Gm-Message-State: AOAM531iw/tjlxblbhMYXJwHXdXfJfP21sALZL1ez0keJE2U0OM4A/q2 NZKEaP+hSppsALW2N8homUNE3mIfiDZEgg== X-Google-Smtp-Source: ABdhPJztbKSSVkixyNCJGARCpDUBA7vf8jEqGxqGVb1rB/tpMWAWNAC+qBSNLOrMKFIKkElixGPZjQ== X-Received: by 2002:a05:6638:11ce:: with SMTP id g14mr1909161jas.188.1642556626074; Tue, 18 Jan 2022 17:43:46 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:45 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass , Marek Vasut , Pavel Herrmann Subject: [PATCH v3 08/31] test: dm: Restart USB before assuming it is stopped Date: Tue, 18 Jan 2022 18:42:52 -0700 Message-Id: <20220119014315.1938157-9-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Update the blk test to stop USB first, in case another test has started it. Signed-off-by: Simon Glass --- (no changes since v1) test/dm/blk.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/dm/blk.c b/test/dm/blk.c index deccf05289b..b5957a20fb0 100644 --- a/test/dm/blk.c +++ b/test/dm/blk.c @@ -15,6 +15,9 @@ DECLARE_GLOBAL_DATA_PTR; +/* Allow resetting the USB-started flag */ +extern char usb_started; + /* Test that block devices can be created */ static int dm_test_blk_base(struct unit_test_state *uts) { @@ -66,8 +69,11 @@ static int dm_test_blk_usb(struct unit_test_state *uts) struct udevice *usb_dev, *dev; struct blk_desc *dev_desc; + usb_started = false; + /* Get a flash device */ state_set_skip_delays(true); + ut_assertok(usb_stop()); ut_assertok(usb_init()); ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev)); ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); From patchwork Wed Jan 19 01:42:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581600 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=DxrHKaOd; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpP35VfLz9sPC for ; Wed, 19 Jan 2022 12:45:11 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 32D2E8380F; Wed, 19 Jan 2022 02:44:25 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="DxrHKaOd"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D41D3837E1; Wed, 19 Jan 2022 02:43:56 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-io1-xd32.google.com (mail-io1-xd32.google.com [IPv6:2607:f8b0:4864:20::d32]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B9F34837CC for ; Wed, 19 Jan 2022 02:43:48 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd32.google.com with SMTP id f24so1033769ioc.0 for ; Tue, 18 Jan 2022 17:43:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=CeQ4TznH5ulNgatYTr4CgoePHEto85uHOBv7OxAtLGg=; b=DxrHKaOd0uDsGRNs1+Ln+j9BpEpgmc+lYhE6x0ZaHt05o0k16v19LDyVmdUoJn5Qu5 fm8YLnzzS47i7/4bfdXFb21x7XM3usmlx6JvlCaayVo0vvDus7YEj4lUsuZBHkvoiFye lmQjucx+FQIkw/nqlM/lQ1RkCd4+X+Jxi6fAA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=CeQ4TznH5ulNgatYTr4CgoePHEto85uHOBv7OxAtLGg=; b=7b7/PGqjwryzyBp+iwu+LXS/o6tZiGySMXeMQcPhgwrvw7X1F5PNOYlipipGrQnTr3 Ly7aYAFpl5MXcqi2ib2q+EXdUa0QlPxn46TlIGSUu3Eu8unQwAOwZ5mhfYNRQoZuswaU wYEfxal+3If5vb/DDWlM/1jCTl0rrs9TubuMZwkl+Ral+FMXGx26vhFfgfxK6T6BMufk 5AZWDvioNaqcxzEY2fnayYBt0WKK8Nh9m/A4N7TE9dEFffrlddtOo4G5ERYhIdTybare cqFVisv84ZkBVubvc33ulNjhQzVXgj7l1ruYac6n3j/7Ybj1AV3lxju8tcN2XF9W377E Z0Tw== X-Gm-Message-State: AOAM532teZS5W9dxB9qgS/XNU+cG83KlhK65TQiP0Litq+iAesIH4jyi nB69jiyPiLc7wtmmgXhn9/4AV/p9tWw5UQ== X-Google-Smtp-Source: ABdhPJxzxuK3xfpXUdx0CYBrZOl8y+i7F+1tRu7S6/hxtiJ6fPPiKAt0008LtwUoD44IZxj4/rcDAA== X-Received: by 2002:a05:6638:2a7:: with SMTP id d7mr12865916jaq.93.1642556627352; Tue, 18 Jan 2022 17:43:47 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:47 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass , Marek Vasut , Pavel Herrmann Subject: [PATCH v3 09/31] dm: blk: Add a function to return the device type Date: Tue, 18 Jan 2022 18:42:53 -0700 Message-Id: <20220118184259.v3.9.I6a05dc4317e457af31d5f1dc9df5848a521a2374@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Use the uclass name to get the device type for a block device. Signed-off-by: Simon Glass --- (no changes since v1) drivers/block/blk-uclass.c | 8 ++++++++ include/blk.h | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index a055387570a..cfc34417a27 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -509,6 +509,14 @@ int blk_get_from_parent(struct udevice *parent, struct udevice **devp) return 0; } +const char *blk_get_devtype(struct udevice *dev) +{ + struct udevice *parent = dev_get_parent(dev); + + return uclass_get_name(device_get_uclass_id(parent)); +}; + + int blk_find_max_devnum(enum if_type if_type) { struct udevice *dev; diff --git a/include/blk.h b/include/blk.h index 133204a82e1..e88948e4c32 100644 --- a/include/blk.h +++ b/include/blk.h @@ -433,6 +433,14 @@ int blk_select_hwpart(struct udevice *dev, int hwpart); */ int blk_get_from_parent(struct udevice *parent, struct udevice **devp); +/** + * blk_get_devtype() - Get the device type of a block device + * + * @dev: Block device to check + * @return device tree, i.e. the uclass name of its parent, e.g. "mmc" + */ +const char *blk_get_devtype(struct udevice *dev); + /** * blk_get_by_device() - Get the block device descriptor for the given device * @dev: Instance of a storage device From patchwork Wed Jan 19 01:42:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581603 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=lxdxOdtQ; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpPd51jrz9sPC for ; Wed, 19 Jan 2022 12:45:41 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id BA2F683826; Wed, 19 Jan 2022 02:44:34 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="lxdxOdtQ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 958188380A; Wed, 19 Jan 2022 02:44:02 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2d.google.com (mail-io1-xd2d.google.com [IPv6:2607:f8b0:4864:20::d2d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DE145837E2 for ; Wed, 19 Jan 2022 02:43:49 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2d.google.com with SMTP id p7so989441iod.2 for ; Tue, 18 Jan 2022 17:43:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MGGxoWM0kHmW1FyuIvnh2cjrGPP4TkwahquVDghjD68=; b=lxdxOdtQzf2JjudUgO8l5YPSlnfEL6ga0AnZL0Kzh7oK2QsF63RCpZPfhRlsVA8m9X 8ZE+1Jv40gZJPScawoyF98GWew1XCyYB1WGJy2xbi5d1D+cy7ahZL8aht9KaEXuVfYmi qfXVt5OZa/4jQKY5WDK8eToWgyAwodAN6SoYw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MGGxoWM0kHmW1FyuIvnh2cjrGPP4TkwahquVDghjD68=; b=slTGpfjK7Lq4tYElK/V1e9iKNo5cgU+tZv7jUguYdiRRS/ZrZFE2WWLzBv8jEcmMK+ 0qDWiCHetVin7op8xArEm1wG3GLo71ZVPOg4Asx4BYaJB6D0lSUTCm2ORWS+zq784/x7 X6uXdwOLY4SaKzv7ijrVL0wcchDVcixFZKkTPAQAKDOpG9EZTjWukekyUsiVHiZRb5+g XAX/nJnS3wuIgvk8vrjxFcPlNl36V8j+/ZOfDk6R6Dim/SjRkI1GOUb92KZwqXCVSbCT Ky/laICDbncupfynF2i32RJp7DPa+ZIi48YJK5CNRFdDt6ufx+zpQsxJTmZ2jPozIF3p EBOA== X-Gm-Message-State: AOAM532ozxKSw+m9RhS0fY4dQ3386pmkIxmfLJtFn8QTbBlsrMpsigzw pvA0QwEPDN20A2THd07ZhMc59BAFd4p54Q== X-Google-Smtp-Source: ABdhPJw0cfZRzWWoGMKZEQVn5tLLwLFDWlxD/gT6EoivypleCo1A5n7AgB1GLTdIx8t22AKVxoktsg== X-Received: by 2002:a5e:8717:: with SMTP id y23mr10418167ioj.79.1642556628464; Tue, 18 Jan 2022 17:43:48 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:48 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 10/31] bootstd: Add the concept of a bootflow Date: Tue, 18 Jan 2022 18:42:54 -0700 Message-Id: <20220119014315.1938157-10-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean A bootflow encapsulates the process used to boot an operating system. It typically has a control file (such as extlinux.conf) and information about which 'bootdev' it came from. Add the header file for this first, since it is needed by all other files. Signed-off-by: Simon Glass --- Changes in v3: - Mention bootflow_state[] in enum bootflow_state_t MAINTAINERS | 5 + include/bootflow.h | 256 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 include/bootflow.h diff --git a/MAINTAINERS b/MAINTAINERS index 38c68ee87d4..cfa0dfc77f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -660,6 +660,11 @@ M: Simon Glass S: Maintained F: tools/binman/ +BOOTDEVICE +M: Simon Glass +S: Maintained +F: include/bootflow.h + BTRFS M: Marek Behun R: Qu Wenruo diff --git a/include/bootflow.h b/include/bootflow.h new file mode 100644 index 00000000000..ef751179580 --- /dev/null +++ b/include/bootflow.h @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __bootflow_h +#define __bootflow_h + +#include + +/** + * enum bootflow_state_t - states that a particular bootflow can be in + * + * Only bootflows in state BOOTFLOWST_READY can be used to boot. + * + * See bootflow_state[] for the names for each of these + */ +enum bootflow_state_t { + BOOTFLOWST_BASE, /**< Nothing known yet */ + BOOTFLOWST_MEDIA, /**< Media exists */ + BOOTFLOWST_PART, /**< Partition exists */ + BOOTFLOWST_FS, /**< Filesystem exists */ + BOOTFLOWST_FILE, /**< Bootflow file exists */ + BOOTFLOWST_READY, /**< Bootflow file loaded */ + + BOOTFLOWST_COUNT +}; + +/** + * struct bootflow - information about a bootflow + * + * This is connected into two separate linked lists: + * + * bm_sibling - links all bootflows in the same bootdev + * glob_sibling - links all bootflows in all bootdevs + * + * @bm_node: Points to siblings in the same bootdev + * @glob_node: Points to siblings in the global list (all bootdev) + * @dev: Bootdevice device which produced this bootflow + * @blk: Block device which contains this bootflow, NULL if this is a network + * device + * @part: Partition number (0 for whole device) + * @method: Bootmethod device used to perform the boot and read files + * @name: Name of bootflow (allocated) + * @state: Current state (enum bootflow_state_t) + * @subdir: Subdirectory to fetch files from (with trailing /), or NULL if none + * @fname: Filename of bootflow file (allocated) + * @buf: Bootflow file contents (allocated) + * @size: Size of bootflow file in bytes + * @err: Error number received (0 if OK) + */ +struct bootflow { + struct list_head bm_node; + struct list_head glob_node; + struct udevice *dev; + struct udevice *blk; + int part; + struct udevice *method; + char *name; + enum bootflow_state_t state; + char *subdir; + char *fname; + char *buf; + int size; + int err; +}; + +/** + * enum bootflow_flags_t - flags for the bootflow iterator + * + * @BOOTFLOWF_FIXED: Only used fixed/internal media + * @BOOTFLOWF_SHOW: Show each bootdev before scanning it + * @BOOTFLOWF_ALL: Return bootflows with errors as well + * @BOOTFLOWF_SINGLE_DEV: Just scan one bootmeth + */ +enum bootflow_flags_t { + BOOTFLOWF_FIXED = 1 << 0, + BOOTFLOWF_SHOW = 1 << 1, + BOOTFLOWF_ALL = 1 << 2, + BOOTFLOWF_SINGLE_DEV = 1 << 3, +}; + +/** + * struct bootflow_iter - state for iterating through bootflows + * + * This starts at with the first bootdev/partition/bootmeth and can be used to + * iterate through all of them. + * + * Iteration starts with the bootdev. The first partition (0, i.e. whole device) + * is scanned first. For partition 0, it iterates through all the available + * bootmeths to see which one(s) can provide a bootflow. Then it moves to + * parition 1 (if there is one) and the process continues. Once all partitions + * are examined, it moves to the next bootdev. + * + * Initially @max_part is 0, meaning that only the whole device (@part=0) can be + * used. During scanning, if a partition table is found, then @max_part is + * updated to a larger value, no less than the number of available partitions. + * This ensures that iteration works through all partitions on the bootdev. + * + * @flags: Flags to use (see enum bootflow_flags_t) + * @dev: Current bootdev + * @part: Current partition number (0 for whole device) + * @method: Current bootmeth + * @max_part: Maximum hardware partition number in @dev, 0 if there is no + * partition table + * @err: Error obtained from checking the last iteration. This is used to skip + * forward (e.g. to skip the current partition because it is not valid) + * -ESHUTDOWN: try next bootdev + * @num_devs: Number of bootdevs in @dev_order + * @cur_dev: Current bootdev number, an index into @dev_order[] + * @dev_order: List of bootdevs to scan, in order of priority. The scan starts + * with the first one on the list + * @num_methods: Number of bootmeth devices in @method_order + * @cur_method: Current method number, an index into @method_order + * @method_order: List of bootmeth devices to use, in order + */ +struct bootflow_iter { + int flags; + struct udevice *dev; + int part; + struct udevice *method; + int max_part; + int err; + int num_devs; + int cur_dev; + struct udevice **dev_order; + int num_methods; + int cur_method; + struct udevice **method_order; +}; + +/** + * bootflow_iter_init() - Reset a bootflow iterator + * + * This sets everything to the starting point, ready for use. + * + * @iter: Place to store private info (inited by this call) + * @flags: Flags to use (see enum bootflow_flags_t) + */ +void bootflow_iter_init(struct bootflow_iter *iter, int flags); + +/** + * bootflow_iter_uninit() - Free memory used by an interator + * + * @iter: Iterator to free + */ +void bootflow_iter_uninit(struct bootflow_iter *iter); + +/** + * bootflow_scan_bootdev() - find the first bootflow in a bootdev + * + * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too + * + * @dev: Boot device to scan, NULL to work through all of them until it + * finds one that * can supply a bootflow + * @iter: Place to store private info (inited by this call) + * @flags: Flags for bootdev (enum bootflow_flags_t) + * @bflow: Place to put the bootflow if found + * @return 0 if found, -ENODEV if no device, other -ve on other error + * (iteration can continue) + */ +int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter, + int flags, struct bootflow *bflow); + +/** + * bootflow_scan_first() - find the first bootflow + * + * This works through the available bootdev devices until it finds one that + * can supply a bootflow. It then returns that + * + * If @flags includes BOOTFLOWF_ALL then bootflows with errors are returned too + * + * @iter: Place to store private info (inited by this call), with + * @flags: Flags for bootdev (enum bootflow_flags_t) + * @bflow: Place to put the bootflow if found + * @return 0 if found, -ENODEV if no device, other -ve on other error (iteration + * can continue) + */ +int bootflow_scan_first(struct bootflow_iter *iter, int flags, + struct bootflow *bflow); + +/** + * bootflow_scan_next() - find the next bootflow + * + * This works through the available bootdev devices until it finds one that + * can supply a bootflow. It then returns that bootflow + * + * @iter: Private info (as set up by bootflow_scan_first()) + * @bflow: Place to put the bootflow if found + * @return 0 if found, -ENODEV if no device, -ESHUTDOWN if no more bootflows, + * other -ve on other error (iteration can continue) + */ +int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow); + +/** + * bootflow_first_glob() - Get the first bootflow from the global list + * + * Returns the first bootflow in the global list, no matter what bootflow it is + * attached to + * + * @bflowp: Returns a pointer to the bootflow + * @return 0 if found, -ENOENT if there are no bootflows + */ +int bootflow_first_glob(struct bootflow **bflowp); + +/** + * bootflow_next_glob() - Get the next bootflow from the global list + * + * Returns the next bootflow in the global list, no matter what bootflow it is + * attached to + * + * @bflowp: On entry, the last bootflow returned , e.g. from + * bootflow_first_glob() + * @return 0 if found, -ENOENT if there are no more bootflows + */ +int bootflow_next_glob(struct bootflow **bflowp); + +/** + * bootflow_free() - Free memory used by a bootflow + * + * This frees fields within @bflow, but not the @bflow pointer itself + */ +void bootflow_free(struct bootflow *bflow); + +/** + * bootflow_boot() - boot a bootflow + * + * @bflow: Bootflow to boot + * @return -EPROTO if bootflow has not been loaded, -ENOSYS if the bootflow + * type is not supported, -EFAULT if the boot returned without an error + * when we are expecting it to boot, -ENOTSUPP if trying method resulted in + * finding out that is not actually supported for this boot and should not + * be tried again unless something changes + */ +int bootflow_boot(struct bootflow *bflow); + +/** + * bootflow_run_boot() - Try to boot a bootflow + * + * @iter: Current iteration (or NULL if none). Used to disable a bootmeth if the + * boot returns -ENOTSUPP + * @bflow: Bootflow to boot + * @return result of trying to boot + */ +int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow); + +/** + * bootflow_state_get_name() - Get the name of a bootflow state + * + * @state: State to check + * @return name, or "?" if invalid + */ +const char *bootflow_state_get_name(enum bootflow_state_t state); + +#endif From patchwork Wed Jan 19 01:42:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581602 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=mXQ8+ZZ0; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpPQ5LrHz9sPC for ; Wed, 19 Jan 2022 12:45:30 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 880C783824; Wed, 19 Jan 2022 02:44:30 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="mXQ8+ZZ0"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AA3D1837B5; Wed, 19 Jan 2022 02:44:04 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x132.google.com (mail-il1-x132.google.com [IPv6:2607:f8b0:4864:20::132]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E44D782F5E for ; Wed, 19 Jan 2022 02:43:50 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x132.google.com with SMTP id d3so836162ilr.10 for ; Tue, 18 Jan 2022 17:43:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pMWVVlEYIP628Crf16iKjccvMDSESjw9q3lhgJt5KjU=; b=mXQ8+ZZ061wln9VeVR8SXJ94rsbPgDKA1E/nD/pYoAYKTOcroEjF45Qf4QToF8AdhI NL2XZepy4Vhg4/Zx8jge2EtxEsghuPXtDDnBZ3QceKmXPx/68xt3BN//9B4Vbma4ceSW uLf5PNhasWXxO00EMJJxpCGsPeews5HuWY0xw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pMWVVlEYIP628Crf16iKjccvMDSESjw9q3lhgJt5KjU=; b=w8KKTkFCQwXbyk/rc2XcZqT78y59VnvzqNHJO9DItFraGaJXeOVcOp01SHFEi/pZeT RkWxQddGiLOsGMPGpgPLeX8C/c38qiEUcdNlqdmoBMuV0htX3PIEbBVU2X4qG5vzxZ// pVV6VgHLmNn2cruTHOc+r31ZjK15SW4OXKw0mNbImQRVqne8aU/O/CCsyoN+1t6xzrkx jq8Z5H0DynHKezuN9pT2iL4qtUANF0JxjmhF57kFLDl38mQVIs1fB1h0eEnE/h7wFPfZ VyzEv/piz8ZtG+uIC0LcZPJ6hFa+Nk0YD9mlQENRJ80ccdolLmEY9KOmJiJsaqhG1DQx S+9Q== X-Gm-Message-State: AOAM531YtsRUnRlNKIf3DMEDOVm3sJUUYN9j/qYhW1/2n5RQC8rEZjrQ heXh3yozpgJGx7eFhdbgnmYFZBNugVwlcg== X-Google-Smtp-Source: ABdhPJxPCzyQn74vFhj/Sp8FMX1t57N0Yk3EarXO/v6FX+R9mqQvnKwRSYAD5ZQqY7lRZqE+k4hQuA== X-Received: by 2002:a05:6e02:1a4b:: with SMTP id u11mr95023ilv.156.1642556629279; Tue, 18 Jan 2022 17:43:49 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:49 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 11/31] bootstd: Add the bootstd uclass and core implementation Date: Tue, 18 Jan 2022 18:42:55 -0700 Message-Id: <20220118184259.v3.11.I3b5bc09d034cd72b2a9c604a0907c10abc05956a@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean The 'bootstd' device provides the central information about U-Boot standard boot. Add a uclass for bootstd and the various helpers needed to make it work. Also add a binding file. Signed-off-by: Simon Glass --- Changes in v3: - Add CONFIG_BOOTSTD_FULL to enable the full feature set - Support bootdev-order and filename-prefixes only with CONFIG_BOOTSTD_FULL MAINTAINERS | 2 + boot/Kconfig | 34 ++++++ boot/Makefile | 3 + boot/bootstd-uclass.c | 152 +++++++++++++++++++++++++++ doc/device-tree-bindings/bootstd.txt | 28 +++++ include/bootstd.h | 80 ++++++++++++++ include/dm/uclass-id.h | 1 + 7 files changed, 300 insertions(+) create mode 100644 boot/bootstd-uclass.c create mode 100644 doc/device-tree-bindings/bootstd.txt create mode 100644 include/bootstd.h diff --git a/MAINTAINERS b/MAINTAINERS index cfa0dfc77f0..ef0cd0b8103 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -663,6 +663,8 @@ F: tools/binman/ BOOTDEVICE M: Simon Glass S: Maintained +F: boot/bootstd.c +F: include/bootstd.h F: include/bootflow.h BTRFS diff --git a/boot/Kconfig b/boot/Kconfig index f1ce576ab2f..032f0b93c68 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -281,6 +281,40 @@ endif # SPL endif # FIT +config BOOTSTD + bool "Standard boot support" + default y + depends on DM && OF_CONTROL && BLK + help + U-Boot supports a standard way of locating something to boot, + typically an Operating System such as Linux, provided by a distro such + as Arch Linux or Debian. Enable this to support iterating through + available bootdevs and using bootmeths to find bootflows suitable for + booting. + + Standard boot is not a standard way of booting, just a framework + within U-Boot for supporting all the different ways that exist. + + Terminology: + + - bootdev - a device which can hold a distro (e.g. MMC) + - bootmeth - a method to scan a bootdev to find bootflows (owned by + U-Boot) + - bootflow - a description of how to boot (owned by the distro) + +config BOOTSTD_FULL + bool "Enhanced features for standard boot" + default y if SANDBOX + help + This enables various useful features for standard boot, which are not + essential for operation: + + - bootdev, bootmeth commands + - extra features in the bootflow command + - support for selecting the ordering of bootmeths ("bootmeth order") + - support for selecting the ordering of bootdevs using the devicetree + as well as the "boot_targets" environment variable + config LEGACY_IMAGE_FORMAT bool "Enable support for the legacy image format" default y if !FIT_SIGNATURE diff --git a/boot/Makefile b/boot/Makefile index 2938c3f1458..48031d1c2b0 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -22,6 +22,9 @@ endif obj-y += image.o image-board.o obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o + +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o + obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c new file mode 100644 index 00000000000..687d29d8073 --- /dev/null +++ b/boot/bootstd-uclass.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Uclass implemenation for standard boot + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* These are used if filename-prefixes is not present */ +const char *const default_prefixes[] = {"/", "/boot/"}; + +static int bootstd_of_to_plat(struct udevice *dev) +{ + struct bootstd_priv *priv = dev_get_priv(dev); + int ret; + + if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) { + /* Don't check errors since livetree and flattree are different */ + ret = dev_read_string_list(dev, "filename-prefixes", + &priv->prefixes); + dev_read_string_list(dev, "bootdev-order", + &priv->bootdev_order); + } + + return 0; +} + +static void bootstd_clear_glob_(struct bootstd_priv *priv) +{ + while (!list_empty(&priv->glob_head)) { + struct bootflow *bflow; + + bflow = list_first_entry(&priv->glob_head, struct bootflow, + glob_node); + /* add later bootflow_remove(bflow); */ + } +} + +void bootstd_clear_glob(void) +{ + struct bootstd_priv *std; + + if (bootstd_get_priv(&std)) + return; + + bootstd_clear_glob_(std); +} + +static int bootstd_remove(struct udevice *dev) +{ + struct bootstd_priv *priv = dev_get_priv(dev); + + free(priv->prefixes); + free(priv->bootdev_order); + bootstd_clear_glob_(priv); + + return 0; +} + +const char *const *const bootstd_get_bootdev_order(struct udevice *dev) +{ + struct bootstd_priv *std = dev_get_priv(dev); + + return std->bootdev_order; +} + +const char *const *const bootstd_get_prefixes(struct udevice *dev) +{ + struct bootstd_priv *std = dev_get_priv(dev); + + return std->prefixes ? std->prefixes : default_prefixes; +} + +int bootstd_get_priv(struct bootstd_priv **stdp) +{ + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_BOOTSTD, &dev); + if (ret) + return ret; + *stdp = dev_get_priv(dev); + + return 0; +} + +static int bootstd_probe(struct udevice *dev) +{ + struct bootstd_priv *std = dev_get_priv(dev); + + INIT_LIST_HEAD(&std->glob_head); + + return 0; +} + +/* For now, bind the boormethod device if none are found in the devicetree */ +int dm_scan_other(bool pre_reloc_only) +{ + struct udevice *bootstd; + int ret; + + /* These are not needed before relocation */ + if (!(gd->flags & GD_FLG_RELOC)) + return 0; + + /* Create a bootstd device if needed */ + uclass_find_first_device(UCLASS_BOOTSTD, &bootstd); + if (!bootstd) { + ret = device_bind_driver(gd->dm_root, "bootstd_drv", "bootstd", + &bootstd); + if (ret) + return log_msg_ret("bootstd", ret); + } + + return 0; +} + +static const struct udevice_id bootstd_ids[] = { + { .compatible = "u-boot,boot-std" }, + { } +}; + +U_BOOT_DRIVER(bootstd_drv) = { + .id = UCLASS_BOOTSTD, + .name = "bootstd_drv", + .of_to_plat = bootstd_of_to_plat, + .probe = bootstd_probe, + .remove = bootstd_remove, + .of_match = bootstd_ids, + .priv_auto = sizeof(struct bootstd_priv), +}; + +UCLASS_DRIVER(bootstd) = { + .id = UCLASS_BOOTSTD, + .name = "bootstd", +#if CONFIG_IS_ENABLED(OF_REAL) + .post_bind = dm_scan_fdt_dev, +#endif +}; diff --git a/doc/device-tree-bindings/bootstd.txt b/doc/device-tree-bindings/bootstd.txt new file mode 100644 index 00000000000..f048b9dd327 --- /dev/null +++ b/doc/device-tree-bindings/bootstd.txt @@ -0,0 +1,28 @@ +U-Boot standard boot device (bootstd) +===================================== + +This is the controlling device for U-Boot standard boot, providing a way to +boot operating systems in a way that can be controlled by distros. + +Required properties: + +compatible: "u-boot,boot-std" + +Optional properties: + +filename-prefixes: + List of strings, each a directory to search for bootflow files + +bootdev-order: + List of bootdevs to check for bootflows, each a bootdev label (the media + uclass followed by the numeric sequence number of the media device) + + +Example: + + bootstd { + compatible = "u-boot,boot-std"; + + filename-prefixes = "/", "/boot/"; + bootdev-order = "mmc2", "mmc1"; + }; diff --git a/include/bootstd.h b/include/bootstd.h new file mode 100644 index 00000000000..95b6e5e1a3c --- /dev/null +++ b/include/bootstd.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Standard U-Boot boot framework + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __bootstd_h +#define __bootstd_h + +struct udevice; + +/** + * struct bootstd_priv - priv data for the bootstd driver + * + * This is attached to the (only) bootstd device, so there is only one instance + * of this struct. It provides overall information about bootdevs and bootflows. + * + * @prefixes: NULL-terminated list of prefixes to use for bootflow filenames, + * e.g. "/", "/boot/"; NULL if none + * @bootdev_order: Order to use for bootdevs (or NULL if none), with each item + * being a bootdev label, e.g. "mmc2", "mmc1"; + * @cur_bootdev: Currently selected bootdev (for commands) + * @cur_bootflow: Currently selected bootflow (for commands) + * @glob_head: Head for the global list of all bootflows across all bootdevs + * @bootmeth_count: Number of bootmeth devices in @bootmeth_order + * @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated + */ +struct bootstd_priv { + const char **prefixes; + const char **bootdev_order; + struct udevice *cur_bootdev; + struct bootflow *cur_bootflow; + struct list_head glob_head; + int bootmeth_count; + struct udevice **bootmeth_order; +}; + +/** + * bootstd_get_bootdev_order() - Get the boot-order list + * + * This reads the boot order, e.g. {"mmc0", "mmc2", NULL} + * + * The list is alloced by the bootstd driver so should not be freed. That is the + * reason for all the const stuff in the function signature + * + * @return list of string points, terminated by NULL; or NULL if no boot order + */ +const char *const *const bootstd_get_bootdev_order(struct udevice *dev); + +/** + * bootstd_get_prefixes() - Get the filename-prefixes list + * + * This reads the prefixes, e.g. {"/", "/bpot", NULL} + * + * The list is alloced by the bootstd driver so should not be freed. That is the + * reason for all the const stuff in the function signature + * + * @return list of string points, terminated by NULL; or NULL if no boot order + */ +const char *const *const bootstd_get_prefixes(struct udevice *dev); + +/** + * bootstd_get_priv() - Get the (single) state for the bootstd system + * + * The state holds a global list of all bootflows that have been found. + * + * @return 0 if OK, -ve if the uclass does not exist + */ +int bootstd_get_priv(struct bootstd_priv **stdp); + +/** + * bootstd_clear_glob() - Clear the global list of bootflows + * + * This removes all bootflows globally and across all bootdevs. + */ +void bootstd_clear_glob(void); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 0e26e1d1382..cece0626a11 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -38,6 +38,7 @@ enum uclass_id { UCLASS_AXI, /* AXI bus */ UCLASS_BLK, /* Block device */ UCLASS_BOOTCOUNT, /* Bootcount backing store */ + UCLASS_BOOTSTD, /* Standard boot driver */ UCLASS_BUTTON, /* Button */ UCLASS_CACHE, /* Cache controller */ UCLASS_CLK, /* Clock source, e.g. used by peripherals */ From patchwork Wed Jan 19 01:42:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581608 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=B2Zh3G/7; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpQg4Rkcz9sPC for ; Wed, 19 Jan 2022 12:46:35 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 68C1083858; Wed, 19 Jan 2022 02:44:58 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="B2Zh3G/7"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5775183830; Wed, 19 Jan 2022 02:44:12 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd30.google.com (mail-io1-xd30.google.com [IPv6:2607:f8b0:4864:20::d30]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 96AC083214 for ; Wed, 19 Jan 2022 02:43:52 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd30.google.com with SMTP id o9so985534iob.3 for ; Tue, 18 Jan 2022 17:43:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=GM5OsMP+0ymtsDZFQrEZKb4EXBrxda0ZnRFn3HHUsEo=; b=B2Zh3G/7cQ/DkaWqlcV3fYEmoU5X+YHqtxJjkSMSM8f+aIjXlJOICvdyNgQO28fzE1 /QoDFHj72TxG9hcYSGZkelr+46zRPanc1GIx3YYFLp2yHmUb1CCwqpTt551CbXH4EY8h K67loEXfB5M9tMZ7OenILfjsUM+XW14jVtOX8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=GM5OsMP+0ymtsDZFQrEZKb4EXBrxda0ZnRFn3HHUsEo=; b=R4KJBFKL3uE2ju5qJuqTm3YR5cEIE5lOB9mFMXz99yUe8zjtAFb8vlIsxp6pNGXSJv izPuEObFSKMXjOPlsv+4o8yz9YGoMRA2gxsnARUAm3X2n7a3vwwI5w1UNZfYOJdEZeU/ L2MH7N9e2pV54H6VISFfBE8ublmclLlrmJjZXj6KByD3c94KPxwpyr1qGVhjpb+BQZ54 dXbQzjKrYrg8MyD8aKjSQJ0ADfyZ1gste6UizVjgyJxA48U0+i6JKJWwxc7E7XDqHwMu IkEthVTUTUIfMGinXHHGl1J1Mkv75GzIKDjosrTuEb8y8WkGzS4AIxE+We47ZPzX9FMY gh+w== X-Gm-Message-State: AOAM533tO26HXU4jLJikIwwWME78KQS1XJPD0GWqNcZSjCXTNXEG3/Wj PchGm3Z2a/99hdOigWxYJ8+GBx0c537wsg== X-Google-Smtp-Source: ABdhPJzFz4xkBIAw37869FG2bqmaRAN62zxvvqWg1TzQPcTxITuVln3SXLx/mOhzXS2DcC8nLVwFUw== X-Received: by 2002:a05:6602:587:: with SMTP id v7mr14058643iox.105.1642556630705; Tue, 18 Jan 2022 17:43:50 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:49 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 12/31] bootstd: Add the bootdev uclass Date: Tue, 18 Jan 2022 18:42:56 -0700 Message-Id: <20220118184259.v3.12.I3b5bc09d034cd72b2a9c604a0907c10abc05956a@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean A 'bootdev' is a device which can be used to boot an operating system. It is a child of the media device (e.g. MMC) which handles reading files from that device, such as a bootflow file. Add a uclass for bootdev and the various helpers needed to make it work. Also add a binding file, empty for now. Signed-off-by: Simon Glass --- Changes in v3: - Update for the new trailing_strtoln_end() - Add bootdev_get_from_blk() function - Use blk_find_device() to find the block device for a media device - Move bootdev ordering into the uclass MAINTAINERS | 4 +- boot/Makefile | 1 + boot/bootdev-uclass.c | 640 +++++++++++++++++++++++++++ doc/device-tree-bindings/bootdev.txt | 8 + include/bootdev.h | 275 ++++++++++++ include/dm/uclass-id.h | 1 + 6 files changed, 928 insertions(+), 1 deletion(-) create mode 100644 boot/bootdev-uclass.c create mode 100644 doc/device-tree-bindings/bootdev.txt create mode 100644 include/bootdev.h diff --git a/MAINTAINERS b/MAINTAINERS index ef0cd0b8103..5b11d80f32b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -663,9 +663,11 @@ F: tools/binman/ BOOTDEVICE M: Simon Glass S: Maintained +F: boot/bootdev*.c F: boot/bootstd.c -F: include/bootstd.h +F: include/bootdev*.h F: include/bootflow.h +F: include/bootstd.h BTRFS M: Marek Behun diff --git a/boot/Makefile b/boot/Makefile index 48031d1c2b0..35abfd37654 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -23,6 +23,7 @@ obj-y += image.o image-board.o obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c new file mode 100644 index 00000000000..93781b89af5 --- /dev/null +++ b/boot/bootdev-uclass.c @@ -0,0 +1,640 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + /* + * Set some sort of limit on the number of partitions a bootdev can + * have. Note that for disks this limits the partitions numbers that + * are scanned to 1..MAX_BOOTFLOWS_PER_BOOTDEV + */ + MAX_PART_PER_BOOTDEV = 30, + + /* Maximum supported length of the "boot_targets" env string */ + BOOT_TARGETS_MAX_LEN = 100, +}; + +int bootdev_add_bootflow(struct bootflow *bflow) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(bflow->dev); + struct bootstd_priv *std; + struct bootflow *new; + int ret; + + assert(bflow->dev); + ret = bootstd_get_priv(&std); + if (ret) + return ret; + + new = malloc(sizeof(*bflow)); + if (!new) + return log_msg_ret("bflow", -ENOMEM); + memcpy(new, bflow, sizeof(*bflow)); + + list_add_tail(&new->glob_node, &std->glob_head); + list_add_tail(&new->bm_node, &ucp->bootflow_head); + + return 0; +} + +int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + if (list_empty(&ucp->bootflow_head)) + return -ENOENT; + + *bflowp = list_first_entry(&ucp->bootflow_head, struct bootflow, + bm_node); + + return 0; +} + +int bootdev_next_bootflow(struct bootflow **bflowp) +{ + struct bootflow *bflow = *bflowp; + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(bflow->dev); + + *bflowp = NULL; + + if (list_is_last(&bflow->bm_node, &ucp->bootflow_head)) + return -ENOENT; + + *bflowp = list_entry(bflow->bm_node.next, struct bootflow, bm_node); + + return 0; +} + +int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name, + struct udevice **devp) +{ + struct udevice *dev; + char dev_name[30]; + char *str; + int ret; + + snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); + str = strdup(dev_name); + if (!str) + return -ENOMEM; + ret = device_bind_driver(parent, drv_name, str, &dev); + if (ret) + return ret; + device_set_name_alloced(dev); + *devp = dev; + + return 0; +} + +int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, + struct bootflow_iter *iter, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(blk); + struct disk_partition info; + char partstr[20]; + char name[60]; + int ret; + + /* Sanity check */ + if (iter->part >= MAX_PART_PER_BOOTDEV) + return log_msg_ret("max", -ESHUTDOWN); + + bflow->blk = blk; + if (iter->part) + snprintf(partstr, sizeof(partstr), "part_%x", iter->part); + else + strcpy(partstr, "whole"); + snprintf(name, sizeof(name), "%s.%s", dev->name, partstr); + bflow->name = strdup(name); + if (!bflow->name) + return log_msg_ret("name", -ENOMEM); + + bflow->part = iter->part; + + /* + * partition numbers start at 0 so this cannot succeed, but it can tell + * us whether there is valid media there + */ + ret = part_get_info(desc, iter->part, &info); + if (!iter->part && ret == -ENOENT) + ret = 0; + + /* + * This error indicates the media is not present. Otherwise we just + * blindly scan the next partition. We could be more intelligent here + * and check which partition numbers actually exist. + */ + if (ret == -EOPNOTSUPP) + ret = -ESHUTDOWN; + else + bflow->state = BOOTFLOWST_MEDIA; + if (ret) + return log_msg_ret("part", ret); + + /* + * Currently we don't get the number of partitions, so just + * assume a large number + */ + iter->max_part = MAX_PART_PER_BOOTDEV; + + if (iter->part) { + ret = fs_set_blk_dev_with_part(desc, bflow->part); + bflow->state = BOOTFLOWST_PART; + + /* Use an #ifdef due to info.sys_ind */ +#ifdef CONFIG_DOS_PARTITION + log_debug("%s: Found partition %x type %x fstype %d\n", + blk->name, bflow->part, info.sys_ind, + ret ? -1 : fs_get_type()); +#endif + if (ret) + return log_msg_ret("fs", ret); + bflow->state = BOOTFLOWST_FS; + } + + return 0; +} + +void bootdev_list(bool probe) +{ + struct udevice *dev; + int ret; + int i; + + printf("Seq Probed Status Uclass Name\n"); + printf("--- ------ ------ -------- ------------------\n"); + if (probe) + ret = uclass_first_device_err(UCLASS_BOOTDEV, &dev); + else + ret = uclass_find_first_device(UCLASS_BOOTDEV, &dev); + for (i = 0; dev; i++) { + printf("%3x [ %c ] %6s %-9.9s %s\n", dev_seq(dev), + device_active(dev) ? '+' : ' ', + ret ? simple_itoa(ret) : "OK", + dev_get_uclass_name(dev_get_parent(dev)), dev->name); + if (probe) + ret = uclass_next_device_err(&dev); + else + ret = uclass_find_next_device(&dev); + } + printf("--- ------ ------ -------- ------------------\n"); + printf("(%d bootdev%s)\n", i, i != 1 ? "s" : ""); +} + +int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name) +{ + struct udevice *bdev; + int ret; + + ret = device_find_first_child_by_uclass(parent, UCLASS_BOOTDEV, + &bdev); + if (ret) { + if (ret != -ENODEV) { + log_debug("Cannot access bootdev device\n"); + return ret; + } + + ret = bootdev_bind(parent, drv_name, "bootdev", &bdev); + if (ret) { + log_debug("Cannot create bootdev device\n"); + return ret; + } + } + + return 0; +} + +int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name) +{ + struct udevice *parent, *dev; + char dev_name[50]; + int ret; + + snprintf(dev_name, sizeof(dev_name), "%s.%s", blk->name, "bootdev"); + + parent = dev_get_parent(blk); + ret = device_find_child_by_name(parent, dev_name, &dev); + if (ret) { + char *str; + + if (ret != -ENODEV) { + log_debug("Cannot access bootdev device\n"); + return ret; + } + str = strdup(dev_name); + if (!str) + return -ENOMEM; + + ret = device_bind_driver(parent, drv_name, str, &dev); + if (ret) { + log_debug("Cannot create bootdev device\n"); + return ret; + } + device_set_name_alloced(dev); + } + + return 0; +} + +int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp) +{ + struct udevice *parent = dev_get_parent(dev); + struct udevice *blk; + int ret, len; + char *p; + + if (device_get_uclass_id(dev) != UCLASS_BOOTDEV) + return -EINVAL; + + /* This should always work if bootdev_setup_sibling_blk() was used */ + p = strstr(dev->name, ".bootdev"); + if (!p) + return log_msg_ret("str", -EINVAL); + + len = p - dev->name; + ret = device_find_child_by_namelen(parent, dev->name, len, &blk); + if (ret) + return log_msg_ret("find", ret); + *blkp = blk; + + return 0; +} + +static int bootdev_get_from_blk(struct udevice *blk, struct udevice **bootdevp) +{ + struct udevice *parent = dev_get_parent(blk); + struct udevice *bootdev; + char dev_name[50]; + int ret; + + if (device_get_uclass_id(blk) != UCLASS_BLK) + return -EINVAL; + + /* This should always work if bootdev_setup_sibling_blk() was used */ + snprintf(dev_name, sizeof(dev_name), "%s.%s", blk->name, "bootdev"); + ret = device_find_child_by_name(parent, dev_name, &bootdev); + if (ret) + return log_msg_ret("find", ret); + *bootdevp = bootdev; + + return 0; +} + +int bootdev_unbind_dev(struct udevice *parent) +{ + struct udevice *dev; + int ret; + + ret = device_find_first_child_by_uclass(parent, UCLASS_BOOTDEV, &dev); + if (!ret) { + ret = device_remove(dev, DM_REMOVE_NORMAL); + if (ret) + return log_msg_ret("rem", ret); + ret = device_unbind(dev); + if (ret) + return log_msg_ret("unb", ret); + } + + return 0; +} + +/** + * bootdev_find_by_label() - Convert a label string to a bootdev device + * + * Looks up a label name to find the associated bootdev. For example, if the + * label name is "mmc2", this will find a bootdev for an mmc device whose + * sequence number is 2. + * + * @label: Label string to convert, e.g. "mmc2" + * @devp: Returns bootdev device corresponding to that boot label + * @return 0 if OK, -EINVAL if the label name (e.g. "mmc") does not refer to a + * uclass, -ENOENT if no bootdev for that media has the sequence number + * (e.g. 2) + */ +int bootdev_find_by_label(const char *label, struct udevice **devp) +{ + struct udevice *media; + struct uclass *uc; + enum uclass_id id; + const char *end; + int seq; + + seq = trailing_strtoln_end(label, NULL, &end); + id = uclass_get_by_namelen(label, end - label); + log_debug("find %s: seq=%d, id=%d/%s\n", label, seq, id, + uclass_get_name(id)); + if (id == UCLASS_INVALID) { + log_warning("Unknown uclass '%s' in label\n", label); + return -EINVAL; + } + if (id == UCLASS_USB) + id = UCLASS_MASS_STORAGE; + + /* Iterate through devices in the media uclass (e.g. UCLASS_MMC) */ + uclass_id_foreach_dev(id, media, uc) { + struct udevice *bdev, *blk; + int ret; + + /* if there is no seq, match anything */ + if (seq != -1 && dev_seq(media) != seq) { + log_debug("- skip, media seq=%d\n", dev_seq(media)); + continue; + } + + ret = device_find_first_child_by_uclass(media, UCLASS_BOOTDEV, + &bdev); + if (ret) { + log_debug("- looking via blk, seq=%d, id=%d\n", seq, + id); + ret = blk_find_device(id, seq, &blk); + if (!ret) { + log_debug("- get from blk %s\n", blk->name); + ret = bootdev_get_from_blk(blk, &bdev); + } + } + if (!ret) { + log_debug("- found %s\n", bdev->name); + *devp = bdev; + return 0; + } + log_debug("- no device in %s\n", media->name); + } + log_warning("Unknown seq %d for label '%s'\n", seq, label); + + return -ENOENT; +} + +int bootdev_find_by_any(const char *name, struct udevice **devp) +{ + struct udevice *dev; + int ret, seq; + char *endp; + + seq = simple_strtol(name, &endp, 16); + + /* Select by name, label or number */ + if (*endp) { + ret = uclass_get_device_by_name(UCLASS_BOOTDEV, name, &dev); + if (ret == -ENODEV) { + ret = bootdev_find_by_label(name, &dev); + if (ret) { + printf("Cannot find bootdev '%s' (err=%d)\n", + name, ret); + return ret; + } + ret = device_probe(dev); + } + if (ret) { + printf("Cannot probe bootdev '%s' (err=%d)\n", name, + ret); + return ret; + } + } else { + ret = uclass_get_device_by_seq(UCLASS_BOOTDEV, seq, &dev); + } + if (ret) { + printf("Cannot find '%s' (err=%d)\n", name, ret); + return ret; + } + + *devp = dev; + + return 0; +} + +int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + const struct bootdev_ops *ops = bootdev_get_ops(dev); + + if (!ops->get_bootflow) + return -ENOSYS; + memset(bflow, '\0', sizeof(*bflow)); + bflow->dev = dev; + bflow->method = iter->method; + bflow->state = BOOTFLOWST_BASE; + + return ops->get_bootflow(dev, iter, bflow); +} + +void bootdev_clear_bootflows(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + while (!list_empty(&ucp->bootflow_head)) { + struct bootflow *bflow; + + bflow = list_first_entry(&ucp->bootflow_head, struct bootflow, + bm_node); + /* later bootflow_remove(bflow); */ + } +} + +/** + * h_cmp_bootdev() - Compare two bootdevs to find out which should go first + * + * @v1: struct udevice * of first bootdev device + * @v2: struct udevice * of second bootdev device + * @return sort order (<0 if dev1 < dev2, ==0 if equal, >0 if dev1 > dev2) + */ +static int h_cmp_bootdev(const void *v1, const void *v2) +{ + const struct udevice *dev1 = *(struct udevice **)v1; + const struct udevice *dev2 = *(struct udevice **)v2; + const struct bootdev_uc_plat *ucp1 = dev_get_uclass_plat(dev1); + const struct bootdev_uc_plat *ucp2 = dev_get_uclass_plat(dev2); + int diff; + + /* Use priority first */ + diff = ucp1->prio - ucp2->prio; + if (diff) + return diff; + + /* Fall back to seq for devices of the same priority */ + diff = dev_seq(dev1) - dev_seq(dev2); + + return diff; +} + +/** + * build_order() - Build the ordered list of bootdevs to use + * + * This builds an ordered list of devices by one of three methods: + * - using the boot_targets environment variable, if non-empty + * - using the bootdev-order devicetree property, if present + * - sorted by priority and sequence number + * + * @bootstd: BOOTSTD device to use + * @order: Bootdevs listed in in default order + * @max_count: Number of entries in @order + * @return number of bootdevs found in the ordering, or -E2BIG if the + * boot_targets string is too long, or -EXDEV if the ordering produced 0 results + */ +static int build_order(struct udevice *bootstd, struct udevice **order, + int max_count) +{ + const char *overflow_target = NULL; + const char *const *labels; + struct udevice *dev; + const char *targets; + int i, ret, count; + + targets = env_get("boot_targets"); + labels = IS_ENABLED(CONFIG_BOOTSTD_FULL) ? + bootstd_get_bootdev_order(bootstd) : NULL; + if (targets) { + char str[BOOT_TARGETS_MAX_LEN]; + char *target; + + if (strlen(targets) >= BOOT_TARGETS_MAX_LEN) + return log_msg_ret("len", -E2BIG); + + /* make a copy of the string, since strok() will change it */ + strcpy(str, targets); + for (i = 0, target = strtok(str, " "); target; + target = strtok(NULL, " ")) { + ret = bootdev_find_by_label(target, &dev); + if (!ret) { + if (i == max_count) { + overflow_target = target; + break; + } + order[i++] = dev; + } + } + count = i; + } else if (labels) { + int upto; + + upto = 0; + for (i = 0; labels[i]; i++) { + ret = bootdev_find_by_label(labels[i], &dev); + if (!ret) { + if (upto == max_count) { + overflow_target = labels[i]; + break; + } + order[upto++] = dev; + } + } + count = upto; + } else { + /* sort them into priorty order */ + count = max_count; + qsort(order, count, sizeof(struct udevice *), h_cmp_bootdev); + } + + if (overflow_target) { + log_warning("Expected at most %d bootdevs, but overflowed with boot_target '%s'\n", + max_count, overflow_target); + } + + if (!count) + return log_msg_ret("targ", -EXDEV); + + return count; +} + +int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp) +{ + struct udevice *bootstd, *dev = *devp, **order; + int upto, i; + int count; + int ret; + + ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd); + if (ret) { + log_err("Missing bootstd device\n"); + return log_msg_ret("std", ret); + } + + /* Handle scanning a single device */ + if (dev) { + iter->flags |= BOOTFLOWF_SINGLE_DEV; + return 0; + } + + count = uclass_id_count(UCLASS_BOOTDEV); + if (!count) + return log_msg_ret("count", -ENOENT); + + order = calloc(count, sizeof(struct udevice *)); + if (!order) + return log_msg_ret("order", -ENOMEM); + + /* + * Get a list of bootdevs, in seq order (i.e. using aliases). There may + * be gaps so try to count up high enough to find them all. + */ + for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) { + ret = uclass_find_device_by_seq(UCLASS_BOOTDEV, i, &dev); + if (!ret) + order[upto++] = dev; + } + log_debug("Found %d bootdevs\n", count); + if (upto != count) + log_debug("Expected %d bootdevs, found %d using aliases\n", + count, upto); + + count = build_order(bootstd, order, upto); + if (count < 0) { + free(order); + return log_msg_ret("build", count); + } + + iter->dev_order = order; + iter->num_devs = count; + iter->cur_dev = 0; + + dev = *order; + ret = device_probe(dev); + if (ret) + return log_msg_ret("probe", ret); + *devp = dev; + + return 0; +} + +static int bootdev_post_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + INIT_LIST_HEAD(&ucp->bootflow_head); + + return 0; +} + +static int bootdev_pre_unbind(struct udevice *dev) +{ + bootdev_clear_bootflows(dev); + + return 0; +} + +UCLASS_DRIVER(bootdev) = { + .id = UCLASS_BOOTDEV, + .name = "bootdev", + .flags = DM_UC_FLAG_SEQ_ALIAS, + .per_device_plat_auto = sizeof(struct bootdev_uc_plat), + .post_bind = bootdev_post_bind, + .pre_unbind = bootdev_pre_unbind, +}; diff --git a/doc/device-tree-bindings/bootdev.txt b/doc/device-tree-bindings/bootdev.txt new file mode 100644 index 00000000000..95b7fec8212 --- /dev/null +++ b/doc/device-tree-bindings/bootdev.txt @@ -0,0 +1,8 @@ +U-Boot boot device (bootdev) +============================ + +A bootdev provides a way to obtain a bootflow file from a device. It is a +child of the media device (UCLASS_MMC, UCLASS_SPI_FLASH, etc.) + +The bootdev driver is provided by the media devices. The bindings for each +are described in this file (to come). diff --git a/include/bootdev.h b/include/bootdev.h new file mode 100644 index 00000000000..a47b419cf77 --- /dev/null +++ b/include/bootdev.h @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __bootdev_h +#define __bootdev_h + +#include + +struct bootflow; +struct bootflow_iter; +struct udevice; + +/** + * enum bootdev_prio_t - priority of each bootdev + * + * These values are associated with each bootdev and set up by the driver. + * + * Smallest value is the highest priority. By default, bootdevs are scanned from + * highest to lowest priority + */ +enum bootdev_prio_t { + BOOTDEVP_0_INTERNAL_FAST = 10, + BOOTDEVP_1_INTERNAL_SLOW = 20, + BOOTDEVP_2_SCAN_FAST = 30, + BOOTDEVP_3_SCAN_SLOW = 40, + BOOTDEVP_4_NET_BASE = 50, + BOOTDEVP_5_NET_FALLBACK = 60, + BOOTDEVP_6_SYSTEM = 70, + + BOOTDEVP_COUNT, +}; + +/** + * struct bootdev_uc_plat - uclass information about a bootdev + * + * This is attached to each device in the bootdev uclass and accessible via + * dev_get_uclass_plat(dev) + * + * @bootflows: List of available bootflows for this bootdev + * @piro: Priority of this bootdev + */ +struct bootdev_uc_plat { + struct list_head bootflow_head; + enum bootdev_prio_t prio; +}; + +/** struct bootdev_ops - Operations for the bootdev uclass */ +struct bootdev_ops { + /** + * get_bootflow() - get a bootflow + * + * @dev: Bootflow device to check + * @iter: Provides current dev, part, method to get. Should update + * max_part if there is a partition table. Should update state, + * subdir, fname, buf, size according to progress + * @bflow: Updated bootflow if found + * @return 0 if OK, -ESHUTDOWN if there are no more bootflows on this + * device, -ENOSYS if this device doesn't support bootflows, + * other -ve value on other error + */ + int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow); +}; + +#define bootdev_get_ops(dev) ((struct bootdev_ops *)(dev)->driver->ops) + +/** + * bootdev_get_bootflow() - get a bootflow + * + * @dev: Bootflow device to check + * @iter: Provides current part, method to get + * @bflow: Returns bootflow if found + * @return 0 if OK, -ESHUTDOWN if there are no more bootflows on this device, + * -ENOSYS if this device doesn't support bootflows, other -ve value on + * other error + */ +int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow); + +/** + * bootdev_bind() - Bind a new named bootdev device + * + * @parent: Parent of the new device + * @drv_name: Driver name to use for the bootdev device + * @name: Name for the device (parent name is prepended) + * @devp: the new device (which has not been probed) + */ +int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name, + struct udevice **devp); + +/** + * bootdev_find_in_blk() - Find a bootdev in a block device + * + * @dev: Bootflow device associated with this block device + * @blk: Block device to search + * @iter: Provides current dev, part, method to get. Should update + * max_part if there is a partition table + * @bflow: On entry, provides information about the partition and device to + * check. On exit, returns bootflow if found + * @return 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error + */ +int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, + struct bootflow_iter *iter, struct bootflow *bflow); + +/** + * bootdev_list() - List all available bootdevs + * + * @probe: true to probe devices, false to leave them as is + */ +void bootdev_list(bool probe); + +/** + * bootdev_clear_bootflows() - Clear bootflows from a bootdev + * + * Each bootdev maintains a list of discovered bootflows. This provides a + * way to clear it. These bootflows are removed from the global list too. + * + * @dev: bootdev device to update + */ +void bootdev_clear_bootflows(struct udevice *dev); + +/** + * bootdev_add_bootflow() - Add a bootflow to the bootdev's list + * + * All fields in @bflow must be set up. Note that @bflow->dev is used to add the + * bootflow to that device. + * + * @dev: Bootdevice device to add to + * @bflow: Bootflow to add. Note that fields within bflow must be allocated + * since this function takes over ownership of these. This functions makes + * a copy of @bflow itself (without allocating its fields again), so the + * caller must dispose of the memory used by the @bflow pointer itself + * @return 0 if OK, -ENOMEM if out of memory + */ +int bootdev_add_bootflow(struct bootflow *bflow); + +/** + * bootdev_first_bootflow() - Get the first bootflow from a bootdev + * + * Returns the first bootflow attached to a bootdev + * + * @dev: bootdev device + * @bflowp: Returns a pointer to the bootflow + * @return 0 if found, -ENOENT if there are no bootflows + */ +int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp); + +/** + * bootdev_next_bootflow() - Get the next bootflow from a bootdev + * + * Returns the next bootflow attached to a bootdev + * + * @bflowp: On entry, the last bootflow returned , e.g. from + * bootdev_first_bootflow() + * @return 0 if found, -ENOENT if there are no more bootflows + */ +int bootdev_next_bootflow(struct bootflow **bflowp); + +/** + * bootdev_find_by_label() - Look up a bootdev by label + * + * Each bootdev has a label which contains the media-uclass name and a number, + * e.g. 'mmc2'. This looks up the label and returns the associated bootdev + * + * The lookup is performed based on the media device's sequence number. So for + * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2. + * + * @label: Label to look up (e.g. "mmc1" or "mmc0") + * @devp: Returns the bootdev device found, or NULL if none (note it does not + * return the media device, but its bootdev child) + * @return 0 if OK, -EINVAL if the uclass is not supported by this board, + * -ENOENT if there is no device with that number + */ +int bootdev_find_by_label(const char *label, struct udevice **devp); + +/** + * bootdev_find_by_any() - Find a bootdev by name, label or sequence + * + * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find + * @devp: returns the device found, on success + * @return 0 if OK, -ve on error + */ +int bootdev_find_by_any(const char *name, struct udevice **devp); + +/** + * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan + * + * This sets up the ordering information in @iter, based on the priority of each + * bootdev and the bootdev-order property in the bootstd node + * + * If a single device is requested, no ordering is needed + * + * @iter: Iterator to update with the order + * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single) + * device to scan. Returns the first device to use, which is the passed-in + * @devp if it was non-NULL + * @return 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve + * on other error + */ +int bootdev_setup_iter_order(struct bootflow_iter *iter, struct udevice **devp); + +#if CONFIG_IS_ENABLED(BOOTSTD) +/** + * bootdev_setup_for_dev() - Bind a new bootdev device + * + * Creates a bootdev device as a child of @parent. This should be called from + * the driver's bind() method or its uclass' post_bind() method. + * + * If a child bootdev already exists, this function does nothing + * + * @parent: Parent device (e.g. MMC or Ethernet) + * @drv_name: Name of bootdev driver to bind + * @return 0 if OK, -ve on error + */ +int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name); + +/** + * bootdev_setup_for_blk() - Bind a new bootdev device for a blk device + * + * Creates a bootdev device as a sibling of @blk. This should be called from + * the driver's bind() method or its uclass' post_bind() method, at the same + * time as the bould device is bound + * + * If a device of the same name already exists, this function does nothing + * + * @parent: Parent device (e.g. MMC or Ethernet) + * @drv_name: Name of bootdev driver to bind + * @return 0 if OK, -ve on error + */ +int bootdev_setup_sibling_blk(struct udevice *blk, const char *drv_name); + +/** + * bootdev_get_sibling_blk() - Locate the block device for a bootdev + * + * @dev: bootdev to check + * @blkp: returns associated block device + * @return 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other + * error + */ +int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp); + +/** + * bootdev_unbind_dev() - Unbind a bootdev device + * + * Remove and unbind a bootdev device which is a child of @parent. This should + * be called from the driver's unbind() method or its uclass' post_bind() + * method. + * + * @parent: Parent device (e.g. MMC or Ethernet) + * @return 0 if OK, -ve on error + */ +int bootdev_unbind_dev(struct udevice *parent); +#else +static inline int bootdev_setup_for_dev(struct udevice *parent, + const char *drv_name) +{ + return 0; +} + +static inline int bootdev_setup_sibling_blk(struct udevice *blk, + const char *drv_name) +{ + return 0; +} + +static inline int bootdev_unbind_dev(struct udevice *parent) +{ + return 0; +} +#endif + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index cece0626a11..97ba4c02c42 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -38,6 +38,7 @@ enum uclass_id { UCLASS_AXI, /* AXI bus */ UCLASS_BLK, /* Block device */ UCLASS_BOOTCOUNT, /* Bootcount backing store */ + UCLASS_BOOTDEV, /* Boot device for locating an OS to boot */ UCLASS_BOOTSTD, /* Standard boot driver */ UCLASS_BUTTON, /* Button */ UCLASS_CACHE, /* Cache controller */ From patchwork Wed Jan 19 01:42:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581605 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=j5nj+y56; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpQ603Yxz9sPC for ; Wed, 19 Jan 2022 12:46:05 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2D3E083852; Wed, 19 Jan 2022 02:44:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="j5nj+y56"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id E8C4A83830; Wed, 19 Jan 2022 02:44:09 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd31.google.com (mail-io1-xd31.google.com [IPv6:2607:f8b0:4864:20::d31]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 977EB8366B for ; Wed, 19 Jan 2022 02:43:53 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd31.google.com with SMTP id n137so972357iod.4 for ; Tue, 18 Jan 2022 17:43:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wSjMhTYuSZo3M2MBvAWo+qNah1J6Mtdj/I5ypMBEZUc=; b=j5nj+y56A3uZNJeIQpL47vRvOG51WkX76VHnZGxow5p4TsVWT4WxoJC2B2roQ7R7ZB 0URVp8IjVc6MvJaMrrq6nfIylZNdzpvtmfefeMs7OWNMEY2SvhPnD+FNE9AKN/8pEclz auUs2LGBJX/jpbL8NGSC59U9D5UPreihABLAI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wSjMhTYuSZo3M2MBvAWo+qNah1J6Mtdj/I5ypMBEZUc=; b=kBcCILxeBDqgV5lbd0sattEz0mMMWuJbt8FFrAAq0AizdUkH88M9/3C2RSTi0yf7fY B2w9TsJaLeZh+sLFnrwzWj0gYHTZ7oZDyHzX82LoiHoayGIec2G41Nu07PLew6i6LFGs njpHPY3+vj8i/q+GBbyah3pRvO+8RF4u6qEnLbm2gbtBrEcJNGH4vday7FmY7yvp0u8A uceWKSZEyccaVj0ZQNZxxuKcJqmk/NaozfIaI/OuYoEGk5dNJdJwny21JXJy5oxrPd6q d5/larhgL/5qA6VOhU1wL22X8PdUetNBwP3SC6OzMprUP3BtpG7LiEKyJmy0iXB1rmZs N2Eg== X-Gm-Message-State: AOAM530+cql3pPeLBa+z8y6XWHyyTw+hE4OvXs6fhiTkxp5SNM7fwway SHb0Ti+bLZ5m1J+VqoQQYhRqOkrDMfm13Q== X-Google-Smtp-Source: ABdhPJykKdWxK+kJvSrSCjYzajcg5G4kNbj59SRfy8XVk6pzUyQ/dVwfDwB2xC3AXY4K+BaZ/RE3uA== X-Received: by 2002:a05:6602:14c9:: with SMTP id b9mr6787382iow.3.1642556631842; Tue, 18 Jan 2022 17:43:51 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:51 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 13/31] bootstd: Add the bootmeth uclass and helpers Date: Tue, 18 Jan 2022 18:42:57 -0700 Message-Id: <20220119014315.1938157-11-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean A bootmeth is a method of locating an operating system. For now, just add the uclass itself. Drivers for particular bootmeths are added later. If no bootmeths devices are included in the devicetree, create them automatically. This avoids the need for boilerplate in the devicetree files. Signed-off-by: Simon Glass --- Changes in v3: - Move bootmeth ordering into the uclass - Support "bootmeths" env var - Add some more common functions MAINTAINERS | 2 + boot/Makefile | 1 + boot/bootmeth-uclass.c | 298 +++++++++++++++++++++++++++++++++++++++++ boot/bootstd-uclass.c | 29 +++- include/bootmeth.h | 234 ++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/env_callback.h | 7 + 7 files changed, 570 insertions(+), 2 deletions(-) create mode 100644 boot/bootmeth-uclass.c create mode 100644 include/bootmeth.h diff --git a/MAINTAINERS b/MAINTAINERS index 5b11d80f32b..ba912ddfc2f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -663,10 +663,12 @@ F: tools/binman/ BOOTDEVICE M: Simon Glass S: Maintained +F: boot/bootmeth*.c F: boot/bootdev*.c F: boot/bootstd.c F: include/bootdev*.h F: include/bootflow.h +F: include/bootmeth.h F: include/bootstd.h BTRFS diff --git a/boot/Makefile b/boot/Makefile index 35abfd37654..54ded9541e0 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c new file mode 100644 index 00000000000..7efe7d88387 --- /dev/null +++ b/boot/bootmeth-uclass.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int bootmeth_check(struct udevice *dev, struct bootflow_iter *iter) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->check) + return 0; + + return ops->check(dev, iter); +} + +int bootmeth_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->read_bootflow) + return -ENOSYS; + + return ops->read_bootflow(dev, bflow); +} + +int bootmeth_boot(struct udevice *dev, struct bootflow *bflow) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->boot) + return -ENOSYS; + + return ops->boot(dev, bflow); +} + +int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + const struct bootmeth_ops *ops = bootmeth_get_ops(dev); + + if (!ops->read_file) + return -ENOSYS; + + return ops->read_file(dev, bflow, file_path, addr, sizep); +} + +/** + * bootmeth_setup_iter_order() - Set up the ordering of bootmeths to scan + * + * This sets up the ordering information in @iter, based on the selected + * ordering of the bootmethds in bootstd_priv->bootmeth_order. If there is no + * ordering there, then all bootmethods are added + * + * @iter: Iterator to update with the order + * @return 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve + * on other error + */ +int bootmeth_setup_iter_order(struct bootflow_iter *iter) +{ + struct bootstd_priv *std; + struct udevice **order; + int count; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return ret; + + /* Create an array large enough */ + count = std->bootmeth_count ? std->bootmeth_count : + uclass_id_count(UCLASS_BOOTMETH); + if (!count) + return log_msg_ret("count", -ENOENT); + + order = calloc(count, sizeof(struct udevice *)); + if (!order) + return log_msg_ret("order", -ENOMEM); + + /* If we have an ordering, copy it */ + if (IS_ENABLED(CONFIG_BOOTSTD_FULL) && std->bootmeth_count) { + memcpy(order, std->bootmeth_order, + count * sizeof(struct bootmeth *)); + } else { + struct udevice *dev; + int i, upto; + + /* + * Get a list of bootmethods, in seq order (i.e. using aliases). + * There may be gaps so try to count up high enough to find them + * all. + */ + for (i = 0, upto = 0; upto < count && i < 20 + count * 2; i++) { + ret = uclass_get_device_by_seq(UCLASS_BOOTMETH, i, + &dev); + if (!ret) + order[upto++] = dev; + } + count = upto; + } + + iter->method_order = order; + iter->num_methods = count; + iter->cur_method = 0; + + return 0; +} + +int bootmeth_set_order(const char *order_str) +{ + struct bootstd_priv *std; + struct udevice **order; + int count, ret, i, len; + const char *s, *p; + + ret = bootstd_get_priv(&std); + if (ret) + return ret; + + if (!order_str) { + free(std->bootmeth_order); + std->bootmeth_order = NULL; + std->bootmeth_count = 0; + return 0; + } + + /* Create an array large enough */ + count = uclass_id_count(UCLASS_BOOTMETH); + if (!count) + return log_msg_ret("count", -ENOENT); + + order = calloc(count + 1, sizeof(struct udevice *)); + if (!order) + return log_msg_ret("order", -ENOMEM); + + for (i = 0, s = order_str; *s && i < count; s = p + (*p == ' '), i++) { + struct udevice *dev; + + p = strchrnul(s, ' '); + len = p - s; + ret = uclass_find_device_by_namelen(UCLASS_BOOTMETH, s, len, + &dev); + if (ret) { + printf("Unknown bootmeth '%.*s'\n", len, s); + free(order); + return ret; + } + order[i] = dev; + } + order[i] = NULL; + free(std->bootmeth_order); + std->bootmeth_order = order; + std->bootmeth_count = i; + + return 0; +} + +int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc, + const char *prefix, const char *fname) +{ + char path[200]; + loff_t size; + int ret, ret2; + + snprintf(path, sizeof(path), "%s%s", prefix ? prefix : "", fname); + log_debug("trying: %s\n", path); + + free(bflow->fname); + bflow->fname = strdup(path); + if (!bflow->fname) + return log_msg_ret("name", -ENOMEM); + + ret = fs_size(path, &size); + log_debug(" %s - err=%d\n", path, ret); + + /* Sadly FS closes the file after fs_size() so we must redo this */ + ret2 = fs_set_blk_dev_with_part(desc, bflow->part); + if (ret2) + return log_msg_ret("set", ret2); + if (ret) + return log_msg_ret("size", ret); + + bflow->size = size; + bflow->state = BOOTFLOWST_FILE; + + return 0; +} + +int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align) +{ + loff_t bytes_read; + ulong addr; + char *buf; + uint size; + int ret; + + size = bflow->size; + log_debug(" - script file size %x\n", size); + if (size > size_limit) + return log_msg_ret("chk", -E2BIG); + + buf = memalign(align, size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + addr = map_to_sysmem(buf); + + ret = fs_read(bflow->fname, addr, 0, 0, &bytes_read); + if (ret) { + free(buf); + return log_msg_ret("read", ret); + } + if (size != bytes_read) + return log_msg_ret("bread", -EINVAL); + buf[size] = '\0'; + bflow->state = BOOTFLOWST_READY; + bflow->buf = buf; + + return 0; +} + +int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + loff_t len_read; + loff_t size; + int ret; + + ret = fs_set_blk_dev_with_part(desc, bflow->part); + if (ret) + return log_msg_ret("set1", ret); + ret = fs_size(file_path, &size); + if (ret) + return log_msg_ret("size", ret); + if (size > *sizep) + return log_msg_ret("spc", -ENOSPC); + + ret = fs_set_blk_dev_with_part(desc, bflow->part); + if (ret) + return log_msg_ret("set2", ret); + ret = fs_read(file_path, addr, 0, 0, &len_read); + if (ret) + return ret; + *sizep = len_read; + + return 0; +} + +#ifdef CONFIG_BOOTSTD_FULL +/** + * on_bootmeths() - Update the bootmeth order + * + * This will check for a valid baudrate and only apply it if valid. + */ +static int on_bootmeths(const char *name, const char *value, enum env_op op, + int flags) +{ + int ret; + + switch (op) { + case env_op_create: + case env_op_overwrite: + ret = bootmeth_set_order(value); + if (ret) + return 1; + return 0; + case env_op_delete: + bootmeth_set_order(NULL); + fallthrough; + default: + return 0; + } +} +U_BOOT_ENV_CALLBACK(bootmeths, on_bootmeths); +#endif /* CONFIG_BOOTSTD_FULL */ + +UCLASS_DRIVER(bootmeth) = { + .id = UCLASS_BOOTMETH, + .name = "bootmeth", + .flags = DM_UC_FLAG_SEQ_ALIAS, + .per_device_plat_auto = sizeof(struct bootmeth_uc_plat), +}; diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c index 687d29d8073..5070f69f1c9 100644 --- a/boot/bootstd-uclass.c +++ b/boot/bootstd-uclass.c @@ -109,8 +109,10 @@ static int bootstd_probe(struct udevice *dev) /* For now, bind the boormethod device if none are found in the devicetree */ int dm_scan_other(bool pre_reloc_only) { - struct udevice *bootstd; - int ret; + struct driver *drv = ll_entry_start(struct driver, driver); + const int n_ents = ll_entry_count(struct driver, driver); + struct udevice *dev, *bootstd; + int i, ret; /* These are not needed before relocation */ if (!(gd->flags & GD_FLG_RELOC)) @@ -125,6 +127,29 @@ int dm_scan_other(bool pre_reloc_only) return log_msg_ret("bootstd", ret); } + /* If there are no bootmeth devices, create them */ + uclass_find_first_device(UCLASS_BOOTMETH, &dev); + if (dev) + return 0; + + for (i = 0; i < n_ents; i++, drv++) { + /* + * Disable EFI Manager for now as no one uses it so it is + * confusing + */ + if (drv->id == UCLASS_BOOTMETH && + strcmp("efi_mgr_bootmeth", drv->name)) { + const char *name = drv->name; + + if (!strncmp("bootmeth_", name, 9)) + name += 9; + ret = device_bind(bootstd, drv, name, 0, ofnode_null(), + &dev); + if (ret) + return log_msg_ret("meth", ret); + } + } + return 0; } diff --git a/include/bootmeth.h b/include/bootmeth.h new file mode 100644 index 00000000000..9ba9c4ecd69 --- /dev/null +++ b/include/bootmeth.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __bootmeth_h +#define __bootmeth_h + +struct blk_desc; +struct bootflow; +struct bootflow_iter; +struct udevice; + +/** + * struct bootmeth_uc_plat - information the uclass keeps about each bootmeth + * + * @desc: A long description of the bootmeth + */ +struct bootmeth_uc_plat { + const char *desc; +}; + +/** struct bootmeth_ops - Operations for boot methods */ +struct bootmeth_ops { + /** + * check_supported() - check if a bootmeth supports this bootflow + * + * This is optional. If not provided, the bootdev is assumed to be + * supported + * + * The bootmeth can check the bootdev (e.g. to make sure it is a + * network device) or the partition information. The following fields + * in @iter are available: + * + * name, dev, state, part + * max_part may be set if part != 0 (i.e. there is a valid partition + * table). Otherwise max_part is 0 + * method is available but is the same as @dev + * the partition has not yet been read, nor has the filesystem been + * checked + * + * It may update only the flags in @iter + * + * @dev: Bootmethod device to check against + * @iter: On entry, provides bootdev, hwpart, part + * @return 0 if OK, -ENOTSUPP if this bootdev is not supported + */ + int (*check)(struct udevice *dev, struct bootflow_iter *iter); + + /** + * read_bootflow() - read a bootflow for a device + * + * @dev: Bootmethod device to use + * @bflow: On entry, provides dev, hwpart, part and method. + * Returns updated bootflow if found + * @return 0 if OK, -ve on error + */ + int (*read_bootflow)(struct udevice *dev, struct bootflow *bflow); + + /** + * read_file() - read a file needed for a bootflow + * + * Read a file from the same place as the bootflow came from + * + * @dev: Bootmethod device to use + * @bflow: Bootflow providing info on where to read from + * @file_path: Path to file (may be absolute or relative) + * @addr: Address to load file + * @sizep: On entry provides the maximum permitted size; on exit + * returns the size of the file + * @return 0 if OK, -ENOSPC if the file is too large for @sizep, other + * -ve value if something else goes wrong + */ + int (*read_file)(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep); + + /** + * boot() - boot a bootflow + * + * @dev: Bootmethod device to boot + * @bflow: Bootflow to boot + * @return does not return on success, since it should boot the + * Operating Systemn. Returns -EFAULT if that fails, -ENOTSUPP if + * trying method resulted in finding out that is not actually + * supported for this boot and should not be tried again unless + * something changes, other -ve on other error + */ + int (*boot)(struct udevice *dev, struct bootflow *bflow); +}; + +#define bootmeth_get_ops(dev) ((struct bootmeth_ops *)(dev)->driver->ops) + +/** + * bootmeth_check() - check if a bootmeth supports this bootflow + * + * This is optional. If not provided, the bootdev is assumed to be + * supported + * + * The bootmeth can check the bootdev (e.g. to make sure it is a + * network device) or the partition information. The following fields + * in @iter are available: + * + * name, dev, state, part + * max_part may be set if part != 0 (i.e. there is a valid partition + * table). Otherwise max_part is 0 + * method is available but is the same as @dev + * the partition has not yet been read, nor has the filesystem been + * checked + * + * It may update only the flags in @iter + * + * @dev: Bootmethod device to check against + * @iter: On entry, provides bootdev, hwpart, part + * @return 0 if OK, -ENOTSUPP if this bootdev is not supported + */ +int bootmeth_check(struct udevice *dev, struct bootflow_iter *iter); + +/** + * bootmeth_read_bootflow() - set up a bootflow for a device + * + * @dev: Bootmethod device to check + * @bflow: On entry, provides dev, hwpart, part and method. + * Returns updated bootflow if found + * @return 0 if OK, -ve on error + */ +int bootmeth_read_bootflow(struct udevice *dev, struct bootflow *bflow); + +/** + * bootmeth_read_file() - read a file needed for a bootflow + * + * Read a file from the same place as the bootflow came from + * + * @dev: Bootmethod device to use + * @bflow: Bootflow providing info on where to read from + * @file_path: Path to file (may be absolute or relative) + * @addr: Address to load file + * @sizep: On entry provides the maximum permitted size; on exit + * returns the size of the file + * @return 0 if OK, -ENOSPC if the file is too large for @sizep, other + * -ve value if something else goes wrong + */ +int bootmeth_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep); + +/** + * bootmeth_boot() - boot a bootflow + * + * @dev: Bootmethod device to boot + * @bflow: Bootflow to boot + * @return does not return on success, since it should boot the + * Operating Systemn. Returns -EFAULT if that fails, other -ve on + * other error + */ +int bootmeth_boot(struct udevice *dev, struct bootflow *bflow); + +/** + * bootmeth_setup_iter_order() - Set up the ordering of bootmeths to scan + * + * This sets up the ordering information in @iter, based on the selected + * ordering of the bootmethds in bootstd_priv->bootmeth_order. If there is no + * ordering there, then all bootmethods are added + * + * @iter: Iterator to update with the order + * @return 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve + * on other error + */ +int bootmeth_setup_iter_order(struct bootflow_iter *iter); + +/** + * bootmeth_set_order() - Set the bootmeth order + * + * This selects the ordering to use for bootmeths + * + * @order_str: String containing the ordering. This is a comma-separate list of + * bootmeth-device names, e.g. "syslinux,efi". If empty then a default ordering + * is used, based on the sequence number of devices (i.e. using aliases) + * @return 0 if OK, -ENODEV if an unknown bootmeth is mentioned, -ENOMEM if + * out of memory, -ENOENT if there are no bootmeth devices + */ +int bootmeth_set_order(const char *order_str); + +/** + * bootmeth_try_file() - See we can access a given file + * + * Check for a file with a given name. If found, the filename is allocated in + * @bflow + * + * Sets the state to BOOTFLOWST_FILE on success. It also calls + * fs_set_blk_dev_with_part() so that this does not need to be done by the + * caller before reading the file. + * + * @bflow: Information about file to try + * @desc: Block descriptor to read from + * @prefix: Filename prefix to prepend to @fname (NULL for none) + * @fname: Filename to read + * @return 0 if OK, -ENOMEM if not enough memory to allocate bflow->fname, + * other -ve value on other error + */ +int bootmeth_try_file(struct bootflow *bflow, struct blk_desc *desc, + const char *prefix, const char *fname); + +/** + * bootmeth_alloc_file() - Allocate and read a bootflow file + * + * Allocates memory for a bootflow file and reads it in. Sets the state to + * BOOTFLOWST_READY on success + * + * Note that fs_set_blk_dev_with_part() must have been called previously. + * + * @bflow: Information about file to read + * @size_limit: Maximum file size to permit + * @align: Allocation alignment (1 for unaligned) + * @return 0 if OK, -E2BIG if file is too large, -ENOMEM if out of memory, + * other -ve on other error + */ +int bootmeth_alloc_file(struct bootflow *bflow, uint size_limit, uint align); + +/** + * bootmeth_common_read_file() - Common handler for reading a file + * + * Reads a named file from the same location as the bootflow file. + * + * @dev: bootmeth device to read from + * @bflow: Bootflow information + * @file_path: Path to file + * @addr: Address to load file to + * @sizep: On entry, the maximum file size to accept, on exit the actual file + * size read + */ +int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 97ba4c02c42..5cee8bebf8e 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -39,6 +39,7 @@ enum uclass_id { UCLASS_BLK, /* Block device */ UCLASS_BOOTCOUNT, /* Bootcount backing store */ UCLASS_BOOTDEV, /* Boot device for locating an OS to boot */ + UCLASS_BOOTMETH, /* Bootmethod for booting an OS */ UCLASS_BOOTSTD, /* Standard boot driver */ UCLASS_BUTTON, /* Button */ UCLASS_CACHE, /* Cache controller */ diff --git a/include/env_callback.h b/include/env_callback.h index 05e9516a0f4..d5d2b2fcad6 100644 --- a/include/env_callback.h +++ b/include/env_callback.h @@ -57,6 +57,12 @@ #define NET_CALLBACKS #endif +#ifdef CONFIG_BOOTSTD +#define BOOTSTD_CALLBACK "bootmeths:bootmeths," +#else +#define BOOTSTD_CALLBACK +#endif + /* * This list of callback bindings is static, but may be overridden by defining * a new association in the ".callbacks" environment variable. @@ -65,6 +71,7 @@ ENV_DOT_ESCAPE ENV_FLAGS_VAR ":flags," \ "baudrate:baudrate," \ NET_CALLBACKS \ + BOOTSTD_CALLBACK \ "loadaddr:loadaddr," \ SILENT_CALLBACK \ SPLASHIMAGE_CALLBACK \ From patchwork Wed Jan 19 01:42:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581604 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=QcvNUXJZ; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpPt44vXz9sPC for ; Wed, 19 Jan 2022 12:45:54 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0676983833; Wed, 19 Jan 2022 02:44:39 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="QcvNUXJZ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3BE2F83839; Wed, 19 Jan 2022 02:44:09 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd31.google.com (mail-io1-xd31.google.com [IPv6:2607:f8b0:4864:20::d31]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id CDF84801EA for ; Wed, 19 Jan 2022 02:43:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd31.google.com with SMTP id e79so917769iof.13 for ; Tue, 18 Jan 2022 17:43:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nmuqWvQQbehhsCVhaHEeuykyCHqTBByfNIm16ra3ByA=; b=QcvNUXJZq4uW4Vt61EAXBmitACY3U4H5kWUI63/y7I6BpOb7Nv82Z1ctcRn1Ix2Tx3 RoNxFyMMsvY3GFVLI0yYMWHZIOogRmcJFLsNMDsZNBqXvTLFDLOeI88wHlWSBzbVAkcS nkmcHbPezMur2KE7i1NMxMdQZBLW+YCuXN2Ng= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nmuqWvQQbehhsCVhaHEeuykyCHqTBByfNIm16ra3ByA=; b=1NyKKHxJryfE/C5iP5ZEPNxx55QeLq/G+fQZUfll+qZoRMT5soxLNPclRpXIy0zkYo 5eEltRs0KrTT8Te3eP5VLsmcp0J0pevevPnV2YwCCjRa3XvS8ezl8NdMe6dUE+a0LFJ6 x3+lT11I49PQNhM/5sZjhW2qElygN3XFVDmHfJ9J6kh3I7IqmrOgMEBHwcQUjgiJmAXJ Fkz8bsn3oOzloyXX7Pk3yLesQ6PnpsS9f58u6gY9Up/2Q/m7nfYAQcP3M5SjExbn/tsu eMdkldPpvcp19ImW6nfMClWdlatIWzwgknoXOcZ3VyVhWYdNMOWOQ190AyivebcQfFwe +jMg== X-Gm-Message-State: AOAM532ovexhKFcqAmu6B1Q7V88FKrwbZLB9F/8npO+rIVmBs48PqdEp 6NP/23EQ6lHXBBWYL4bk/NJWbloXS0xxIg== X-Google-Smtp-Source: ABdhPJz6VPBJ7XMTgQ/VtPzPIHoRfjsS8OBAOnC+MPvE2t/5iRKvdggQnZIBCdLPN+DedMjYyMShcA== X-Received: by 2002:a05:6638:628:: with SMTP id h8mr7622065jar.192.1642556633216; Tue, 18 Jan 2022 17:43:53 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:52 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 14/31] bootstd: Add support for bootflows Date: Tue, 18 Jan 2022 18:42:58 -0700 Message-Id: <20220119014315.1938157-12-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add support for bootflows, including maintaining a list of them and iterating to find them. Signed-off-by: Simon Glass --- Changes in v3: - Point to the header file for bootflow_state[] docs - Explain why it is OK to use "?" as an unknown bootflow state - Move bootmeth/bootdev ordering into the uclass MAINTAINERS | 3 +- boot/Makefile | 1 + boot/bootdev-uclass.c | 11 +- boot/bootflow.c | 410 ++++++++++++++++++++++++++++++++++++++++++ boot/bootstd-uclass.c | 2 +- include/bootflow.h | 50 ++++++ 6 files changed, 474 insertions(+), 3 deletions(-) create mode 100644 boot/bootflow.c diff --git a/MAINTAINERS b/MAINTAINERS index ba912ddfc2f..ec86be53791 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -663,8 +663,9 @@ F: tools/binman/ BOOTDEVICE M: Simon Glass S: Maintained -F: boot/bootmeth*.c F: boot/bootdev*.c +F: boot/bootflow.c +F: boot/bootmeth*.c F: boot/bootstd.c F: include/bootdev*.h F: include/bootflow.h diff --git a/boot/Makefile b/boot/Makefile index 54ded9541e0..f58c192ae07 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 93781b89af5..c077d6df29c 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, bflow->part = iter->part; + ret = bootmeth_check(bflow->method, iter); + if (ret) + return log_msg_ret("check", ret); + /* * partition numbers start at 0 so this cannot succeed, but it can tell * us whether there is valid media there @@ -171,6 +176,10 @@ int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, bflow->state = BOOTFLOWST_FS; } + ret = bootmeth_read_bootflow(bflow->method, bflow); + if (ret) + return log_msg_ret("method", ret); + return 0; } @@ -445,7 +454,7 @@ void bootdev_clear_bootflows(struct udevice *dev) bflow = list_first_entry(&ucp->bootflow_head, struct bootflow, bm_node); - /* later bootflow_remove(bflow); */ + bootflow_remove(bflow); } } diff --git a/boot/bootflow.c b/boot/bootflow.c new file mode 100644 index 00000000000..d77c463f7d9 --- /dev/null +++ b/boot/bootflow.c @@ -0,0 +1,410 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* error codes used to signal running out of things */ +enum { + BF_NO_MORE_PARTS = -ESHUTDOWN, + BF_NO_MORE_DEVICES = -ENODEV, +}; + +/** + * bootflow_state - name for each state + * + * See enum bootflow_state_t for what each of these means + */ +static const char *const bootflow_state[BOOTFLOWST_COUNT] = { + "base", + "media", + "part", + "fs", + "file", + "ready", +}; + +const char *bootflow_state_get_name(enum bootflow_state_t state) +{ + /* This doesn't need to be a useful name, since it will never occur */ + if (state < 0 || state >= BOOTFLOWST_COUNT) + return "?"; + + return bootflow_state[state]; +} + +int bootflow_first_glob(struct bootflow **bflowp) +{ + struct bootstd_priv *std; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return ret; + + if (list_empty(&std->glob_head)) + return -ENOENT; + + *bflowp = list_first_entry(&std->glob_head, struct bootflow, + glob_node); + + return 0; +} + +int bootflow_next_glob(struct bootflow **bflowp) +{ + struct bootstd_priv *std; + struct bootflow *bflow = *bflowp; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return ret; + + *bflowp = NULL; + + if (list_is_last(&bflow->glob_node, &std->glob_head)) + return -ENOENT; + + *bflowp = list_entry(bflow->glob_node.next, struct bootflow, glob_node); + + return 0; +} + +void bootflow_iter_init(struct bootflow_iter *iter, int flags) +{ + memset(iter, '\0', sizeof(*iter)); + iter->flags = flags; +} + +void bootflow_iter_uninit(struct bootflow_iter *iter) +{ + free(iter->dev_order); + free(iter->method_order); +} + +int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter, + const struct udevice *bmeth) +{ + /* We only support disabling the current bootmeth */ + if (bmeth != iter->method || iter->cur_method >= iter->num_methods || + iter->method_order[iter->cur_method] != bmeth) + return -EINVAL; + + memmove(&iter->method_order[iter->cur_method], + &iter->method_order[iter->cur_method + 1], + (iter->num_methods - iter->cur_method - 1) * sizeof(void *)); + + iter->num_methods--; + + return 0; +} + +static void bootflow_iter_set_dev(struct bootflow_iter *iter, + struct udevice *dev) +{ + iter->dev = dev; + if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) == + BOOTFLOWF_SHOW) { + if (dev) + printf("Scanning bootdev '%s':\n", dev->name); + else + printf("No more bootdevs\n"); + } +} + +/** + * iter_incr() - Move to the next item (method, part, bootdev) + * + * @return 0 if OK, BF_NO_MORE_DEVICES if there are no more bootdevs + */ +static int iter_incr(struct bootflow_iter *iter) +{ + struct udevice *dev; + int ret; + + if (iter->err == BF_NO_MORE_DEVICES) + return BF_NO_MORE_DEVICES; + + if (iter->err != BF_NO_MORE_PARTS) { + /* Get the next boothmethod */ + if (++iter->cur_method < iter->num_methods) { + iter->method = iter->method_order[iter->cur_method]; + return 0; + } + } + + /* No more bootmeths; start at the first one, and... */ + iter->cur_method = 0; + iter->method = iter->method_order[iter->cur_method]; + + if (iter->err != BF_NO_MORE_PARTS) { + /* ...select next partition */ + if (++iter->part <= iter->max_part) + return 0; + } + + /* No more partitions; start at the first one and...*/ + iter->part = 0; + + /* + * Note: as far as we know, there is no partition table on the next + * bootdev, so set max_part to 0 until we discover otherwise. See + * bootdev_find_in_blk() for where this is set. + */ + iter->max_part = 0; + + /* ...select next bootdev */ + if (iter->flags & BOOTFLOWF_SINGLE_DEV) { + ret = -ENOENT; + } else if (++iter->cur_dev == iter->num_devs) { + ret = -ENOENT; + bootflow_iter_set_dev(iter, NULL); + } else { + dev = iter->dev_order[iter->cur_dev]; + ret = device_probe(dev); + if (!log_msg_ret("probe", ret)) + bootflow_iter_set_dev(iter, dev); + } + + /* if there are no more bootdevs, give up */ + if (ret) + return log_msg_ret("incr", BF_NO_MORE_DEVICES); + + return 0; +} + +/** + * bootflow_check() - Check if a bootflow can be obtained + * + * @iter: Provides part, bootmeth to use + * @bflow: Bootflow to update on success + * @return 0 if OK, -ENOSYS if there is no bootflow support on this device, + * BF_NO_MORE_PARTS if there are no more partitions on bootdev + */ +static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow) +{ + struct udevice *dev; + int ret; + + dev = iter->dev; + ret = bootdev_get_bootflow(dev, iter, bflow); + + /* If we got a valid bootflow, return it */ + if (!ret) { + log_debug("Bootdevice '%s' part %d method '%s': Found bootflow\n", + dev->name, iter->part, iter->method->name); + return 0; + } + + /* Unless there is nothing more to try, move to the next device */ + else if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) { + log_debug("Bootdevice '%s' part %d method '%s': Error %d\n", + dev->name, iter->part, iter->method->name, ret); + /* + * For 'all' we return all bootflows, even + * those with errors + */ + if (iter->flags & BOOTFLOWF_ALL) + return log_msg_ret("all", ret); + } + if (ret) + return log_msg_ret("check", ret); + + return 0; +} + +int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter, + int flags, struct bootflow *bflow) +{ + int ret; + + bootflow_iter_init(iter, flags); + + ret = bootdev_setup_iter_order(iter, &dev); + if (ret) + return log_msg_ret("obdev", -ENODEV); + bootflow_iter_set_dev(iter, dev); + + ret = bootmeth_setup_iter_order(iter); + if (ret) + return log_msg_ret("obmeth", -ENODEV); + + /* Find the first bootmeth (there must be at least one!) */ + iter->method = iter->method_order[iter->cur_method]; + + ret = bootflow_check(iter, bflow); + if (ret) { + if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) { + if (iter->flags & BOOTFLOWF_ALL) + return log_msg_ret("all", ret); + } + iter->err = ret; + ret = bootflow_scan_next(iter, bflow); + if (ret) + return log_msg_ret("get", ret); + } + + return 0; +} + +int bootflow_scan_first(struct bootflow_iter *iter, int flags, + struct bootflow *bflow) +{ + int ret; + + ret = bootflow_scan_bootdev(NULL, iter, flags, bflow); + if (ret) + return log_msg_ret("start", ret); + + return 0; +} + +int bootflow_scan_next(struct bootflow_iter *iter, struct bootflow *bflow) +{ + int ret; + + do { + ret = iter_incr(iter); + if (ret == BF_NO_MORE_DEVICES) + return log_msg_ret("done", ret); + + if (!ret) { + ret = bootflow_check(iter, bflow); + if (!ret) + return 0; + iter->err = ret; + if (ret != BF_NO_MORE_PARTS && ret != -ENOSYS) { + if (iter->flags & BOOTFLOWF_ALL) + return log_msg_ret("all", ret); + } + } else { + iter->err = ret; + } + + } while (1); +} + +void bootflow_free(struct bootflow *bflow) +{ + free(bflow->name); + free(bflow->subdir); + free(bflow->fname); + free(bflow->buf); +} + +void bootflow_remove(struct bootflow *bflow) +{ + list_del(&bflow->bm_node); + list_del(&bflow->glob_node); + + bootflow_free(bflow); + free(bflow); +} + +int bootflow_boot(struct bootflow *bflow) +{ + int ret; + + if (bflow->state != BOOTFLOWST_READY) + return log_msg_ret("load", -EPROTO); + + ret = bootmeth_boot(bflow->method, bflow); + if (ret) + return log_msg_ret("boot", ret); + + /* + * internal error, should not get here since we should have booted + * something or returned an error + */ + + return log_msg_ret("end", -EFAULT); +} + +int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow) +{ + int ret; + + printf("** Booting bootflow '%s'\n", bflow->name); + ret = bootflow_boot(bflow); + if (!IS_ENABLED(CONFIG_BOOTSTD_FULL)) { + printf("Boot failed (err=%d)\n", ret); + return ret; + } + + switch (ret) { + case -EPROTO: + printf("Bootflow not loaded (state '%s')\n", + bootflow_state_get_name(bflow->state)); + break; + case -ENOSYS: + printf("Boot method '%s' not supported\n", bflow->method->name); + break; + case -ENOTSUPP: + /* Disable this bootflow for this iteration */ + if (iter) { + int ret2; + + ret2 = bootflow_iter_drop_bootmeth(iter, bflow->method); + if (!ret2) { + printf("Boot method '%s' failed and will not be retried\n", + bflow->method->name); + } + } + + break; + default: + printf("Boot failed (err=%d)\n", ret); + break; + } + + return ret; +} + +int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter) +{ + const struct udevice *media = dev_get_parent(iter->dev); + enum uclass_id id = device_get_uclass_id(media); + + log_debug("uclass %d: %s\n", id, uclass_get_name(id)); + if (id != UCLASS_ETH && id != UCLASS_BOOTSTD) + return 0; + + return -ENOTSUPP; +} + +int bootflow_iter_uses_network(const struct bootflow_iter *iter) +{ + const struct udevice *media = dev_get_parent(iter->dev); + enum uclass_id id = device_get_uclass_id(media); + + log_debug("uclass %d: %s\n", id, uclass_get_name(id)); + if (id == UCLASS_ETH) + return 0; + + return -ENOTSUPP; +} + +int bootflow_iter_uses_system(const struct bootflow_iter *iter) +{ + const struct udevice *media = dev_get_parent(iter->dev); + enum uclass_id id = device_get_uclass_id(media); + + log_debug("uclass %d: %s\n", id, uclass_get_name(id)); + if (id == UCLASS_BOOTSTD) + return 0; + + return -ENOTSUPP; +} diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c index 5070f69f1c9..63fded98baf 100644 --- a/boot/bootstd-uclass.c +++ b/boot/bootstd-uclass.c @@ -45,7 +45,7 @@ static void bootstd_clear_glob_(struct bootstd_priv *priv) bflow = list_first_entry(&priv->glob_head, struct bootflow, glob_node); - /* add later bootflow_remove(bflow); */ + bootflow_remove(bflow); } } diff --git a/include/bootflow.h b/include/bootflow.h index ef751179580..bfa4feaeb06 100644 --- a/include/bootflow.h +++ b/include/bootflow.h @@ -147,6 +147,18 @@ void bootflow_iter_init(struct bootflow_iter *iter, int flags); */ void bootflow_iter_uninit(struct bootflow_iter *iter); +/** + * bootflow_iter_drop_bootmeth() - Remove a bootmeth from an iterator + * + * Update the iterator so that the bootmeth will not be used again while this + * iterator is in use + * + * @iter: Iterator to update + * @bmeth: Boot method to remove + */ +int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter, + const struct udevice *bmeth); + /** * bootflow_scan_bootdev() - find the first bootflow in a bootdev * @@ -253,4 +265,42 @@ int bootflow_run_boot(struct bootflow_iter *iter, struct bootflow *bflow); */ const char *bootflow_state_get_name(enum bootflow_state_t state); +/** + * bootflow_remove() - Remove a bootflow and free its memory + * + * This updates the linked lists containing the bootflow then frees it. + * + * @bflow: Bootflow to remove + */ +void bootflow_remove(struct bootflow *bflow); + +/** + * bootflow_iter_uses_blk_dev() - Check that a bootflow uses a block device + * + * This checks the bootdev in the bootflow to make sure it uses a block device + * + * @return 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet) + */ +int bootflow_iter_uses_blk_dev(const struct bootflow_iter *iter); + +/** + * bootflow_iter_uses_network() - Check that a bootflow uses a network device + * + * This checks the bootdev in the bootflow to make sure it uses a network + * device + * + * @return 0 if OK, -ENOTSUPP if some other device is used (e.g. MMC) + */ +int bootflow_iter_uses_network(const struct bootflow_iter *iter); + +/** + * bootflow_iter_uses_system() - Check that a bootflow uses the bootstd device + * + * This checks the bootdev in the bootflow to make sure it uses the bootstd + * device + * + * @return 0 if OK, -ENOTSUPP if some other device is used (e.g. MMC) + */ +int bootflow_iter_uses_system(const struct bootflow_iter *iter); + #endif From patchwork Wed Jan 19 01:42:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581626 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Trv1NBIB; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpYm0J7pz9sPC for ; Wed, 19 Jan 2022 12:52:43 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 5E8A4837CC; Wed, 19 Jan 2022 02:52:39 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Trv1NBIB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 725578366B; Wed, 19 Jan 2022 02:44:10 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd35.google.com (mail-io1-xd35.google.com [IPv6:2607:f8b0:4864:20::d35]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 88E9D837E4 for ; Wed, 19 Jan 2022 02:43:55 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd35.google.com with SMTP id n137so972456iod.4 for ; Tue, 18 Jan 2022 17:43:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fpH4znFjU1eIieW9bqxhXTAJAvTELMgRFHPuXYcMdsE=; b=Trv1NBIBGL+O0uotaiMl0Li+I+w8q8Gu+ZAoxKi+anaQalICTIngspYq0SoGbakeGo PkQKZqchMFAH8udUyY12ZqmXB5WdZSuB3g2xiiVVoSUV6t0I9QV2lIS4PyKbIuVjfyVK ZX067SEopN49a2OS7KthEYswEskXdpG/t3rjk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fpH4znFjU1eIieW9bqxhXTAJAvTELMgRFHPuXYcMdsE=; b=LMcLhzGmMQzbhOJoebN/r/Mchdnbl852OGsCa3HLna+GxtJpUbNVw1ACcVDdlgta3U KxSsG+OmMNa+5ag/8pgerx5DXb5g+SY6UldUUlnQT85YNFN4VV0d1OM/Uho8RQ1S0P6z By2d58nzslcXBh4Cmcmnf2kM/LgxQI/Jc2JJo1zrD6ZiUqp5RQvruQ6ut8d1nZazbEf4 626svu6P1aNDaGTMQ2M/ahd1AxlroT+qgmtrC7cSj9HqCe+eryr6U/8NDA7dr+rtHGcU M7mIZ+yox6fe/03ManzF3a42bNaQHSt9jfyTNbocZfBkfSm0ekgL/XYoy6vGS1Z5+lAW G/rQ== X-Gm-Message-State: AOAM53324eAuNL3l6aO8cdSLi5NueGa4f+DWnQt2A2ULOTppWsojS9mP ddXKShcJbQ+iktpeLEoXk9EvXIPx5GLbBA== X-Google-Smtp-Source: ABdhPJx1815wpQh/bWfbF0CKDt/roBig34xO7XruJ9lKj9xvMeAdssw+UdxzdFWKDJushNR/qBsmjg== X-Received: by 2002:a5d:9709:: with SMTP id h9mr10070897iol.67.1642556634123; Tue, 18 Jan 2022 17:43:54 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:53 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 15/31] bootstd: Add a bootdev command Date: Tue, 18 Jan 2022 18:42:59 -0700 Message-Id: <20220118184259.v3.15.Ic1c0b48869db2404f5d8c89518eb88156b8bc46a@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a 'bootdev' command to handle listing and selection of bootdevs. Disable standard boot for a few boards which otherwise run out of space. Signed-off-by: Simon Glass --- Changes in v3: - Use separate Kconfig options for each command MAINTAINERS | 1 + cmd/Kconfig | 10 +++ cmd/Makefile | 1 + cmd/bootdev.c | 120 +++++++++++++++++++++++++++++ configs/amcore_defconfig | 1 + configs/rcar3_salvator-x_defconfig | 1 + configs/tbs2910_defconfig | 1 + 7 files changed, 135 insertions(+) create mode 100644 cmd/bootdev.c diff --git a/MAINTAINERS b/MAINTAINERS index ec86be53791..ea8f8fdec91 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -667,6 +667,7 @@ F: boot/bootdev*.c F: boot/bootflow.c F: boot/bootmeth*.c F: boot/bootstd.c +F: cmd/bootdev.c F: include/bootdev*.h F: include/bootflow.h F: include/bootmeth.h diff --git a/cmd/Kconfig b/cmd/Kconfig index 84ede90eee9..e70319fddf5 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -194,6 +194,16 @@ config CMD_BOOTM help Boot an application image from the memory. +config CMD_BOOTDEV + bool "bootdev" + depends on BOOTSTD + default y if BOOTSTD_FULL + help + Support listing available bootdevs (boot devices) which can provide an + OS to boot, as well as showing information about a particular one. + + This command is not necessary for bootstd to work. + config BOOTM_EFI bool "Support booting UEFI FIT images" depends on CMD_BOOTEFI && CMD_BOOTM && FIT diff --git a/cmd/Makefile b/cmd/Makefile index fb133e37037..7323709f602 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o obj-$(CONFIG_CMD_ADC) += adc.o obj-$(CONFIG_CMD_ARMFLASH) += armflash.o obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o +obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o obj-$(CONFIG_CMD_SOURCE) += source.o obj-$(CONFIG_CMD_BCB) += bcb.o obj-$(CONFIG_CMD_BDI) += bdinfo.o diff --git a/cmd/bootdev.c b/cmd/bootdev.c new file mode 100644 index 00000000000..ecd797c0503 --- /dev/null +++ b/cmd/bootdev.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * 'bootdev' command + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int bootdev_check_state(struct bootstd_priv **stdp) +{ + struct bootstd_priv *std; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return ret; + if (!std->cur_bootdev) { + printf("Please use 'bootdev select' first\n"); + return -ENOENT; + } + *stdp = std; + + return 0; +} + +static int do_bootdev_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + bool probe; + + probe = argc >= 2 && !strcmp(argv[1], "-p"); + bootdev_list(probe); + + return 0; +} + +static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct udevice *dev; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + if (argc < 2) { + std->cur_bootdev = NULL; + return 0; + } + if (bootdev_find_by_any(argv[1], &dev)) + return CMD_RET_FAILURE; + + std->cur_bootdev = dev; + + return 0; +} + +static int do_bootdev_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *priv; + struct bootflow *bflow; + int ret, i, num_valid; + struct udevice *dev; + bool probe; + + probe = argc >= 2 && !strcmp(argv[1], "-p"); + + ret = bootdev_check_state(&priv); + if (ret) + return CMD_RET_FAILURE; + + dev = priv->cur_bootdev; + + /* Count the number of bootflows, including how many are valid*/ + num_valid = 0; + for (ret = bootdev_first_bootflow(dev, &bflow), i = 0; + !ret; + ret = bootdev_next_bootflow(&bflow), i++) + num_valid += bflow->state == BOOTFLOWST_READY; + + /* + * Prove the device, if requested, otherwise assume that there is no + * error + */ + ret = 0; + if (probe) + ret = device_probe(dev); + + printf("Name: %s\n", dev->name); + printf("Sequence: %d\n", dev_seq(dev)); + printf("Status: %s\n", ret ? simple_itoa(ret) : device_active(dev) ? + "Probed" : "OK"); + printf("Uclass: %s\n", dev_get_uclass_name(dev_get_parent(dev))); + printf("Bootflows: %d (%d valid)\n", i, num_valid); + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char bootdev_help_text[] = + "list [-p] - list all available bootdevs (-p to probe)\n" + "bootdev select - select a bootdev by name | label | seq\n" + "bootdev info [-p] - show information about a bootdev (-p to probe)"; +#endif + +U_BOOT_CMD_WITH_SUBCMDS(bootdev, "Boot devices", bootdev_help_text, + U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootdev_list), + U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootdev_select), + U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootdev_info)); diff --git a/configs/amcore_defconfig b/configs/amcore_defconfig index afb3a7707fd..9906d736bd4 100644 --- a/configs/amcore_defconfig +++ b/configs/amcore_defconfig @@ -7,6 +7,7 @@ CONFIG_ENV_SECT_SIZE=0x1000 CONFIG_DEFAULT_DEVICE_TREE="amcore" CONFIG_TARGET_AMCORE=y CONFIG_SYS_LOAD_ADDR=0x20000 +# CONFIG_BOOTSTD is not set CONFIG_BOOTDELAY=1 CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="bootm ffc20000" diff --git a/configs/rcar3_salvator-x_defconfig b/configs/rcar3_salvator-x_defconfig index 57a2c01932f..b20a8f893c3 100644 --- a/configs/rcar3_salvator-x_defconfig +++ b/configs/rcar3_salvator-x_defconfig @@ -11,6 +11,7 @@ CONFIG_RCAR_GEN3=y CONFIG_TARGET_SALVATOR_X=y CONFIG_SYS_LOAD_ADDR=0x58000000 CONFIG_FIT=y +# CONFIG_BOOTSTD is not set CONFIG_SUPPORT_RAW_INITRD=y CONFIG_USE_BOOTARGS=y CONFIG_USE_BOOTCOMMAND=y diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig index e1278f2e70a..353c61fe7b9 100644 --- a/configs/tbs2910_defconfig +++ b/configs/tbs2910_defconfig @@ -14,6 +14,7 @@ CONFIG_DEFAULT_DEVICE_TREE="imx6q-tbs2910" CONFIG_PRE_CON_BUF_ADDR=0x7c000000 CONFIG_CMD_HDMIDETECT=y CONFIG_AHCI=y +# CONFIG_BOOTSTD is not set CONFIG_SUPPORT_RAW_INITRD=y CONFIG_BOOTDELAY=3 CONFIG_USE_BOOTCOMMAND=y From patchwork Wed Jan 19 01:43:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581607 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=JeZpd7Yh; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpQV0PRVz9sPC for ; Wed, 19 Jan 2022 12:46:26 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 2CF02837F5; Wed, 19 Jan 2022 02:44:56 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="JeZpd7Yh"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 030DF837E4; Wed, 19 Jan 2022 02:44:11 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd33.google.com (mail-io1-xd33.google.com [IPv6:2607:f8b0:4864:20::d33]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7DC62837E7 for ; Wed, 19 Jan 2022 02:43:56 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd33.google.com with SMTP id i82so954057ioa.8 for ; Tue, 18 Jan 2022 17:43:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=29hAyRfs8sjrXiqn3ESauG+AuKkR3i3e4KMPzz1quME=; b=JeZpd7YhLEyUlQOF05mbdkiN7AqbBEiGjTZMNx4u3zM0U5Fv+ObaVSRq9Vvz8tXsRT 8BAZLFGYIacoh9aQ5XUcFrYf7AdNvIkXhiTf5O4qwI6w0kSer7C3h0v5WGzuAgtvSz0v cvdFPjrItjei+sFsHHJrgLrafROFDzq9nxuo0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=29hAyRfs8sjrXiqn3ESauG+AuKkR3i3e4KMPzz1quME=; b=LkFl9OZz7zRl3bUDdhS/8aWNye8UlvrLRzfLDRvvCxUTobuIiwsonNIgREdmqwv8e+ 2WHa0D0vQqbY3PmZXoQrKTdmJl227K+RsO9kz1JryOQaHLMs3fXHdN1NErB3dEdpjJ6z tVIe/97DGdM5obyyJvbqkVD0N442JDGivGVngqIH+MYdtM5dH3OSSG6KvgQGC1NlbgqC 8lKw96RuG4oaPbrWOvi/6Hl+0bPEEVAlsDdBLcJSeLEfQB5SfUR3T+t59rPBqx+kwwAu XRYLhXnVRfC5bIdvUONDNnOrvTESY5iugrHSYWi/6OEwxgu4/uNHXVAfcE8/tBy9+X5P fkyw== X-Gm-Message-State: AOAM5323ytoEeppDako3aZPjLPc4v0Ep+ng0G1yRcMul2Dr6m9vemWzj 8aCV1iIYLQgFoa9a6ICbg0OZ9eAw+NzrVg== X-Google-Smtp-Source: ABdhPJyly62Oq5t5LopvAALwAGzgJivyOzgXJqE0Ibirm0PnjjfH5IZT03kOjOUK/9CgERB3ruA05A== X-Received: by 2002:a02:9483:: with SMTP id x3mr4182974jah.165.1642556634960; Tue, 18 Jan 2022 17:43:54 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:54 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 16/31] bootstd: Add a bootflow command Date: Tue, 18 Jan 2022 18:43:00 -0700 Message-Id: <20220118184259.v3.16.I6f3d772aa3671d526b66580c7989ae6c27c8538a@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a 'bootflow' command to handle listing and selection of bootflow. Signed-off-by: Simon Glass --- Changes in v3: - Use separate Kconfig options for each command - Put some features behind CONFIG_BOOTFLOW_FULL cmd/Kconfig | 18 +++ cmd/Makefile | 1 + cmd/bootflow.c | 399 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 418 insertions(+) create mode 100644 cmd/bootflow.c diff --git a/cmd/Kconfig b/cmd/Kconfig index e70319fddf5..d1c04f0446f 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -204,6 +204,24 @@ config CMD_BOOTDEV This command is not necessary for bootstd to work. +config CMD_BOOTFLOW + bool "bootflow" + depends on BOOTSTD + default y + help + Support scanning for bootflows available with the bootdevs. The + bootflows can optionally be booted. + +config CMD_BOOTFLOW_FULL + bool "bootflow - extract subcommands" + depends on BOOTSTD + default y if BOOTSTD_FULL + help + Add the ability to list the available bootflows, select one and obtain + information about it. + + This command is not necessary for bootstd to work. + config BOOTM_EFI bool "Support booting UEFI FIT images" depends on CMD_BOOTEFI && CMD_BOOTM && FIT diff --git a/cmd/Makefile b/cmd/Makefile index 7323709f602..2923bd98860 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_CMD_ADC) += adc.o obj-$(CONFIG_CMD_ARMFLASH) += armflash.o obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o +obj-$(CONFIG_CMD_BOOTFLOW) += bootflow.o obj-$(CONFIG_CMD_SOURCE) += source.o obj-$(CONFIG_CMD_BCB) += bcb.o obj-$(CONFIG_CMD_BDI) += bdinfo.o diff --git a/cmd/bootflow.c b/cmd/bootflow.c new file mode 100644 index 00000000000..942bceea494 --- /dev/null +++ b/cmd/bootflow.c @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * 'bootflow' command + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * report_bootflow_err() - Report where a bootflow failed + * + * When a bootflow does not make it to the 'loaded' state, something went wrong. + * Print a helpful message if there is an error + * + * @bflow: Bootflow to process + * @err: Error code (0 if none) + */ +static void report_bootflow_err(struct bootflow *bflow, int err) +{ + if (!err) + return; + + /* Indent out to 'Method' */ + printf(" ** "); + + switch (bflow->state) { + case BOOTFLOWST_BASE: + printf("No media/partition found"); + break; + case BOOTFLOWST_MEDIA: + printf("No partition found"); + break; + case BOOTFLOWST_PART: + printf("No filesystem found"); + break; + case BOOTFLOWST_FS: + printf("File not found"); + break; + case BOOTFLOWST_FILE: + printf("File cannot be loaded"); + break; + case BOOTFLOWST_READY: + printf("Ready"); + break; + case BOOTFLOWST_COUNT: + break; + } + + printf(", err=%d\n", err); +} + +/** + * show_bootflow() - Show the status of a bootflow + * + * @seq: Bootflow index + * @bflow: Bootflow to show + * @errors: True to show the error received, if any + */ +static void show_bootflow(int index, struct bootflow *bflow, bool errors) +{ + printf("%3x %-11s %-6s %-9.9s %4x %-25.25s %s\n", index, + bflow->method->name, bootflow_state_get_name(bflow->state), + dev_get_uclass_name(dev_get_parent(bflow->dev)), bflow->part, + bflow->name, bflow->fname); + if (errors) + report_bootflow_err(bflow, bflow->err); +} + +static void show_header(void) +{ + printf("Seq Method State Uclass Part Name Filename\n"); + printf("--- ----------- ------ -------- ---- ------------------------ ----------------\n"); +} + +static void show_footer(int count, int num_valid) +{ + printf("--- ----------- ------ -------- ---- ------------------------ ----------------\n"); + printf("(%d bootflow%s, %d valid)\n", count, count != 1 ? "s" : "", + num_valid); +} + +static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct bootflow_iter iter; + struct udevice *dev; + struct bootflow bflow; + bool all = false, boot = false, errors = false, list = false; + int num_valid = 0; + int ret, i; + int flags; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + dev = std->cur_bootdev; + + if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL)) { + if (argc > 1 && *argv[1] == '-') { + all = strchr(argv[1], 'a'); + boot = strchr(argv[1], 'b'); + errors = strchr(argv[1], 'e'); + list = strchr(argv[1], 'l'); + argc--; + argv++; + } + if (argc > 1) { + const char *label = argv[1]; + + if (bootdev_find_by_any(label, &dev)) + return CMD_RET_FAILURE; + } + } else { + boot = true; + } + + std->cur_bootflow = NULL; + + flags = 0; + if (list) + flags |= BOOTFLOWF_SHOW; + if (all) + flags |= BOOTFLOWF_ALL; + + /* + * If we have a device, just scan for bootflows attached to that device + */ + if (IS_ENABLED(CONFIG_CMD_BOOTFLOW_FULL) && dev) { + if (list) { + printf("Scanning for bootflows in bootdev '%s'\n", + dev->name); + show_header(); + } + bootdev_clear_bootflows(dev); + for (i = 0, + ret = bootflow_scan_bootdev(dev, &iter, flags, &bflow); + i < 1000 && ret != -ENODEV; + i++, ret = bootflow_scan_next(&iter, &bflow)) { + bflow.err = ret; + if (!ret) + num_valid++; + ret = bootdev_add_bootflow(&bflow); + if (ret) { + printf("Out of memory\n"); + return CMD_RET_FAILURE; + } + if (list) + show_bootflow(i, &bflow, errors); + if (boot && !bflow.err) + bootflow_run_boot(&iter, &bflow); + } + } else { + if (list) { + printf("Scanning for bootflows in all bootdevs\n"); + show_header(); + } + bootstd_clear_glob(); + + for (i = 0, + ret = bootflow_scan_first(&iter, flags, &bflow); + i < 1000 && ret != -ENODEV; + i++, ret = bootflow_scan_next(&iter, &bflow)) { + bflow.err = ret; + if (!ret) + num_valid++; + ret = bootdev_add_bootflow(&bflow); + if (ret) { + printf("Out of memory\n"); + return CMD_RET_FAILURE; + } + if (list) + show_bootflow(i, &bflow, errors); + if (boot && !bflow.err) { + bootflow_run_boot(&iter, &bflow); + } + } + } + bootflow_iter_uninit(&iter); + if (list) + show_footer(i, num_valid); + + return 0; +} + +#ifdef CONFIG_CMD_BOOTFLOW_FULL +static int do_bootflow_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct udevice *dev; + struct bootflow *bflow; + int num_valid = 0; + bool errors = false; + int ret, i; + + if (argc > 1 && *argv[1] == '-') + errors = strchr(argv[1], 'e'); + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + dev = std->cur_bootdev; + + /* If we have a device, just list bootflows attached to that device */ + if (dev) { + printf("Showing bootflows for bootdev '%s'\n", dev->name); + show_header(); + for (ret = bootdev_first_bootflow(dev, &bflow), i = 0; + !ret; + ret = bootdev_next_bootflow(&bflow), i++) { + num_valid += bflow->state == BOOTFLOWST_READY; + show_bootflow(i, bflow, errors); + } + } else { + printf("Showing all bootflows\n"); + show_header(); + for (ret = bootflow_first_glob(&bflow), i = 0; + !ret; + ret = bootflow_next_glob(&bflow), i++) { + num_valid += bflow->state == BOOTFLOWST_READY; + show_bootflow(i, bflow, errors); + } + } + show_footer(i, num_valid); + + return 0; +} + +static int do_bootflow_select(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct bootflow *bflow, *found; + struct udevice *dev; + const char *name; + char *endp; + int seq, i; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; +; + if (argc < 2) { + std->cur_bootflow = NULL; + return 0; + } + dev = std->cur_bootdev; + + name = argv[1]; + seq = simple_strtol(name, &endp, 16); + found = NULL; + + /* + * If we have a bootdev device, only allow selection of bootflows + * attached to that device + */ + if (dev) { + for (ret = bootdev_first_bootflow(dev, &bflow), i = 0; + !ret; + ret = bootdev_next_bootflow(&bflow), i++) { + if (*endp ? !strcmp(bflow->name, name) : (i == seq)) { + found = bflow; + break; + } + } + } else { + for (ret = bootflow_first_glob(&bflow), i = 0; + !ret; + ret = bootflow_next_glob(&bflow), i++) { + if (*endp ? !strcmp(bflow->name, name) : (i == seq)) { + found = bflow; + break; + } + } + } + + if (!found) { + printf("Cannot find bootflow '%s' ", name); + if (dev) + printf("in bootdev '%s' ", dev->name); + printf("(err=%d)\n", ret); + return CMD_RET_FAILURE; + } + std->cur_bootflow = found; + + return 0; +} + +static int do_bootflow_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct bootflow *bflow; + bool dump = false; + int ret; + + if (argc > 1 && *argv[1] == '-') + dump = strchr(argv[1], 'd'); + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + + if (!std->cur_bootflow) { + printf("No bootflow selected\n"); + return CMD_RET_FAILURE; + } + bflow = std->cur_bootflow; + + printf("Name: %s\n", bflow->name); + printf("Device: %s\n", bflow->dev->name); + printf("Block dev: %s\n", bflow->blk ? bflow->blk->name : "(none)"); + printf("Method: %s\n", bflow->method->name); + printf("State: %s\n", bootflow_state_get_name(bflow->state)); + printf("Partition: %d\n", bflow->part); + printf("Subdir: %s\n", bflow->subdir ? bflow->subdir : "(none)"); + printf("Filename: %s\n", bflow->fname); + printf("Buffer: %lx\n", (ulong)map_to_sysmem(bflow->buf)); + printf("Size: %x (%d bytes)\n", bflow->size, bflow->size); + printf("Error: %d\n", bflow->err); + if (dump && bflow->buf) { + /* Set some sort of maximum on the size */ + int size = min(bflow->size, 10 << 10); + int i; + + printf("Contents:\n\n"); + for (i = 0; i < size; i++) { + putc(bflow->buf[i]); + if (!(i % 128) && ctrlc()) { + printf("...interrupted\n"); + break; + } + } + } + + return 0; +} + +static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct bootflow *bflow; + int ret; + + ret = bootstd_get_priv(&std); + if (ret) + return CMD_RET_FAILURE; + + /* + * Require a current bootflow. Users can use 'bootflow scan -b' to + * automatically scan and boot, if needed. + */ + if (!std->cur_bootflow) { + printf("No bootflow selected\n"); + return CMD_RET_FAILURE; + } + bflow = std->cur_bootflow; + ret = bootflow_run_boot(NULL, bflow); + if (ret) + return CMD_RET_FAILURE; + + return 0; +} +#endif /* CONFIG_CMD_BOOTFLOW_FULL */ + +#ifdef CONFIG_SYS_LONGHELP +static char bootflow_help_text[] = +#ifdef CONFIG_CMD_BOOTFLOW_FULL + "scan [-abel] [bdev] - scan for valid bootflows (-l list, -a all, -e errors, -b boot)\n" + "bootflow list [-e] - list scanned bootflows (-e errors)\n" + "bootflow select [|] - select a bootflow\n" + "bootflow info [-d] - show info on current bootflow (-d dump bootflow)\n" + "bootflow boot - boot current bootflow (or first available if none selected)"; +#else + "scan - boot first available bootflow\n"; +#endif +#endif /* CONFIG_SYS_LONGHELP */ + +U_BOOT_CMD_WITH_SUBCMDS(bootflow, "Boot flows", bootflow_help_text, + U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_bootflow_scan), +#ifdef CONFIG_CMD_BOOTFLOW_FULL + U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootflow_list), + U_BOOT_SUBCMD_MKENT(select, 2, 1, do_bootflow_select), + U_BOOT_SUBCMD_MKENT(info, 2, 1, do_bootflow_info), + U_BOOT_SUBCMD_MKENT(boot, 1, 1, do_bootflow_boot) +#endif +); From patchwork Wed Jan 19 01:43:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581606 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=FqBqYNbP; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpQK053Zz9sPC for ; Wed, 19 Jan 2022 12:46:16 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0F2F383838; Wed, 19 Jan 2022 02:44:54 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="FqBqYNbP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 88BBB83214; Wed, 19 Jan 2022 02:44:17 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd29.google.com (mail-io1-xd29.google.com [IPv6:2607:f8b0:4864:20::d29]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 50162836E6 for ; Wed, 19 Jan 2022 02:43:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd29.google.com with SMTP id i82so954087ioa.8 for ; Tue, 18 Jan 2022 17:43:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JTrnrCRELLabOPSlldUgcpz5YVbOczNco74h7S4bhvo=; b=FqBqYNbPSZXlIn0M3Za0eq5DI8Fl2fH3phHeadEJ+T7depOkLnbOz6ET24fciciJB/ YMBYAU5PcuFYmddlhf53o2bwFvlr49G51Z1oseqMksY9U1pOBz57yXvQzS7b+S2WBV8p 8mQ3ImuUD4YTpp7Yk+Pf2bAX3rCdHpn9z3DSw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JTrnrCRELLabOPSlldUgcpz5YVbOczNco74h7S4bhvo=; b=7RTAObnvrS4KdqZbTnR3+2Cay7pyfhDG3N398xOPwvBKKvoXp07xM77AVLlthA8Ksd srrxU3A+GDwOweg4baXqlHhr6gXOMqwKOa0n9j5Hxlu6thZgAL+ulkg2IcQxXIM9n+SN p07/c2J92SwMaDTEIm2QbfUZmPOL8RYVaF7gapQcU6iWbCSc8z09jm1ETy33/jf0K1qY wOxOjpzIRG2AoPl+hcg/Zof9BBNC+6kpAHnUF5cIIiAgfys11KAdDK+BuC7iv90LcZH8 TVnhLRribcJ/wN+zc8gE+YozIdsCHgN0GiyBwZcU0aKae6swiWo/e8SiG7oamcv8VfnJ 96GA== X-Gm-Message-State: AOAM530CFJR/bPeT9wHOvb0VMF4pklvMAkanQpryqwP50c4CbJ50h6El v5QrptPXXlw/ZdLDcLvCQGk6Oq/kwDnokg== X-Google-Smtp-Source: ABdhPJxh8Lmpq1LIXIRYy1gyPdEx1t+XXzSsnBiqY3NTmDAesAfCT5WLkg/6vSwzt/cGlG3YIbI+FQ== X-Received: by 2002:a02:a403:: with SMTP id c3mr13683626jal.318.1642556635894; Tue, 18 Jan 2022 17:43:55 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:55 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 17/31] bootstd: Add a bootmeth command Date: Tue, 18 Jan 2022 18:43:01 -0700 Message-Id: <20220118184259.v3.17.I6f3d772aa3671d526b66580c7989ae6c27c8538a@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a 'bootmeth' command to handle listing and ordering of boot methods. Signed-off-by: Simon Glass --- Changes in v3: - Move bootmeth ordering into the uclass cmd/Kconfig | 11 +++++ cmd/Makefile | 1 + cmd/bootmeth.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 cmd/bootmeth.c diff --git a/cmd/Kconfig b/cmd/Kconfig index d1c04f0446f..c87dbe16b8d 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -222,6 +222,17 @@ config CMD_BOOTFLOW_FULL This command is not necessary for bootstd to work. +config CMD_BOOTMETH + bool "bootmeth" + depends on BOOTSTD + default y if BOOTSTD_FULL + help + Support listing available bootmethds (methods used to boot an + Operating System), as well as selecting the order that the bootmeths + are used. + + This command is not necessary for bootstd to work. + config BOOTM_EFI bool "Support booting UEFI FIT images" depends on CMD_BOOTEFI && CMD_BOOTM && FIT diff --git a/cmd/Makefile b/cmd/Makefile index 2923bd98860..e7c36e1023e 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_CMD_ARMFLASH) += armflash.o obj-$(CONFIG_HAVE_BLOCK_DEVICE) += blk_common.o obj-$(CONFIG_CMD_BOOTDEV) += bootdev.o obj-$(CONFIG_CMD_BOOTFLOW) += bootflow.o +obj-$(CONFIG_CMD_BOOTMETH) += bootmeth.o obj-$(CONFIG_CMD_SOURCE) += source.o obj-$(CONFIG_CMD_BCB) += bcb.o obj-$(CONFIG_CMD_BDI) += bdinfo.o diff --git a/cmd/bootmeth.c b/cmd/bootmeth.c new file mode 100644 index 00000000000..c9a27fe8ac6 --- /dev/null +++ b/cmd/bootmeth.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * 'bootmeth' command + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int do_bootmeth_list(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct bootstd_priv *std; + struct udevice *dev; + bool use_order; + bool all = false; + int ret; + int i; + + if (argc > 1 && *argv[1] == '-') { + all = strchr(argv[1], 'a'); + argc--; + argv++; + } + + ret = bootstd_get_priv(&std); + if (ret) { + printf("Cannot get bootstd (err=%d)\n", ret); + return CMD_RET_FAILURE; + } + + printf("Order Seq Name Description\n"); + printf("----- --- ------------------ ------------------\n"); + + /* + * Use the ordering if we have one, so long as we are not trying to list + * all bootmethds + */ + use_order = std->bootmeth_count && !all; + if (use_order) + dev = std->bootmeth_order[0]; + else + ret = uclass_find_first_device(UCLASS_BOOTMETH, &dev); + + for (i = 0; dev;) { + struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(dev); + int order = i; + + /* + * With the -a flag we may list bootdevs that are not in the + * ordering. Find their place in the order + */ + if (all && std->bootmeth_count) { + int j; + + /* Find the position of this bootmeth in the order */ + order = -1; + for (j = 0; j < std->bootmeth_count; j++) { + if (std->bootmeth_order[j] == dev) + order = j; + } + } + + if (order == -1) + printf("%5s", "-"); + else + printf("%5x", order); + printf(" %3x %-19.19s %s\n", dev_seq(dev), dev->name, + ucp->desc); + i++; + if (use_order) + dev = std->bootmeth_order[i]; + else + uclass_find_next_device(&dev); + } + printf("----- --- ------------------ ------------------\n"); + printf("(%d bootmeth%s)\n", i, i != 1 ? "s" : ""); + + return 0; +} + +static int do_bootmeth_order(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = bootmeth_set_order(argv[1]); + if (ret) { + printf("Failed (err=%d)\n", ret); + return CMD_RET_FAILURE; + } + env_set("bootmeths", argv[1]); + + return 0; +} + +#ifdef CONFIG_SYS_LONGHELP +static char bootmeth_help_text[] = + "list [-a] - list available bootmeths (-a all)\n" + "bootmeth order [ ...] - select bootmeth order / subset to use"; +#endif + +U_BOOT_CMD_WITH_SUBCMDS(bootmeth, "Boot methods", bootmeth_help_text, + U_BOOT_SUBCMD_MKENT(list, 2, 1, do_bootmeth_list), + U_BOOT_SUBCMD_MKENT(order, CONFIG_SYS_MAXARGS, 1, do_bootmeth_order)); From patchwork Wed Jan 19 01:43:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581610 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=mwFEjdCo; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpR22R4jz9sPC for ; Wed, 19 Jan 2022 12:46:54 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id A19E88386F; Wed, 19 Jan 2022 02:45:05 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="mwFEjdCo"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 714FB837FD; Wed, 19 Jan 2022 02:44:20 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd32.google.com (mail-io1-xd32.google.com [IPv6:2607:f8b0:4864:20::d32]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 54E1B834A0 for ; Wed, 19 Jan 2022 02:43:58 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd32.google.com with SMTP id h23so928481iol.11 for ; Tue, 18 Jan 2022 17:43:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9QaFrurSpjTjsiXfv3hez85T1PjGi36ifHkO0ywEM1Q=; b=mwFEjdCoQtMwyIw7t8dOZJGkgAEFxZ23/6hvZAKwiVeZ9EE1gaz/oJ5YYN0t3Dzpvt BuhuXabf/23eL5G4m5t24Wu8fhpcZ6PpvOzr//ZjtSuoxk55Gzw+hHgn8AAs84jp5hsZ lqAO+vOaCKlr5An4T1s/Er4zOTO8AC4rrOV4U= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9QaFrurSpjTjsiXfv3hez85T1PjGi36ifHkO0ywEM1Q=; b=1BgGA1x/o2VFwwrAlsb73GEiWpfbVE8Mccwdk9o7zUHCtCZs/dZDeRHhi4jSnjT4i/ efXh8zJ+UIgpFY8JuqlS0F5cRKtea7hJCMmGCryXy7rLofvYHnTmhZKQuj2l63rsOPGQ 5DCFM/+n/6t0hVzXXDnB1LpA6bM4WHBpOwFN13tG7qjW63t4Kii2Km/sGgl+xawDF+p6 pdcjhuBAa2Tn0XpEe96TFqA4KJ8j5UK4YsaUsZEbCcnYOd/MijEV929BzC1Mp4+jWkrB Ko0cxBwLzupGtG2mAIVsGvtSbyIWRyGuBqOqRjWR7H4xMiyWlfzgXuHSpGUzZmg8Feck eFiQ== X-Gm-Message-State: AOAM530NZ2SNp3dshFdlpXCDJEIjnJkBbuTBi6J+CAoWrihYDB1y3osI LCrF6biJ5F2L6lGyaO4HBNaR3HWs6QGqyA== X-Google-Smtp-Source: ABdhPJxQldNyEBQ68HgX3Ycnn0gbQXs/aqpZacwM7JWWPutOIMGm0mkGrD/T2xZN6sqIrvims339Qg== X-Received: by 2002:a05:6638:3450:: with SMTP id q16mr10714112jav.311.1642556636866; Tue, 18 Jan 2022 17:43:56 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:56 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 18/31] bootstd: Add an implementation of distro boot Date: Tue, 18 Jan 2022 18:43:02 -0700 Message-Id: <20220118184259.v3.18.Iafd004865970e7357960cacc4981e212e4cf3d16@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootmeth driver which handles distro boot from a disk, so we can boot a bootflow using this commonly used mechanism. In effect, this provides the same functionality as the 'sysboot' command and shares the same code. But the interface into it is via a bootmeth. For now this requires the 'pxe' command be enabled. Future work may tidy this up so that it can be used without CONFIG_CMDLINE being enabled. Signed-off-by: Simon Glass --- Changes in v3: - Use new bootmeth_try_file() function - Use a short name when BOOTSTD_FULL is not enabled - Use common bootmeth functions MAINTAINERS | 3 +- boot/Kconfig | 15 +++++ boot/Makefile | 2 + boot/bootmeth_distro.c | 142 +++++++++++++++++++++++++++++++++++++++++ include/distro.h | 24 +++++++ 5 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 boot/bootmeth_distro.c create mode 100644 include/distro.h diff --git a/MAINTAINERS b/MAINTAINERS index ea8f8fdec91..e907151276a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -668,7 +668,8 @@ F: boot/bootflow.c F: boot/bootmeth*.c F: boot/bootstd.c F: cmd/bootdev.c -F: include/bootdev*.h +F: cmd/bootflow.c +F: include/bootdev.h F: include/bootflow.h F: include/bootmeth.h F: include/bootstd.h diff --git a/boot/Kconfig b/boot/Kconfig index 032f0b93c68..45d38a226cb 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -315,6 +315,21 @@ config BOOTSTD_FULL - support for selecting the ordering of bootdevs using the devicetree as well as the "boot_targets" environment variable +if BOOTSTD + +config BOOTMETH_DISTRO + bool "Bootdev support for distro boot" + depends on CMD_PXE + default y + help + Enables support for distro boot using bootdevs. This makes the + bootdevs look for a 'extlinux/extlinux.conf' on each filesystem + they scan. + + This provides a way to try out standard boot on an existing boot flow. + +endif + config LEGACY_IMAGE_FORMAT bool "Enable support for the legacy image format" default y if !FIT_SIGNATURE diff --git a/boot/Makefile b/boot/Makefile index f58c192ae07..d8f5c340b85 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -28,6 +28,8 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o + obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o diff --git a/boot/bootmeth_distro.c b/boot/bootmeth_distro.c new file mode 100644 index 00000000000..7960b70979b --- /dev/null +++ b/boot/bootmeth_distro.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for distro boot (syslinux boot from a block device) + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int disto_getfile(struct pxe_context *ctx, const char *file_path, + char *file_addr, ulong *sizep) +{ + struct distro_info *info = ctx->userdata; + ulong addr; + int ret; + + addr = simple_strtoul(file_addr, NULL, 16); + + /* Allow up to 1GB */ + *sizep = 1 << 30; + ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr, + sizep); + if (ret) + return log_msg_ret("read", ret); + + return 0; +} + +static int distro_check(struct udevice *dev, struct bootflow_iter *iter) +{ + int ret; + + /* This only works on block devices */ + ret = bootflow_iter_uses_blk_dev(iter); + if (ret) + return log_msg_ret("blk", ret); + + return 0; +} + +static int distro_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + const char *const *prefixes; + struct udevice *bootstd; + const char *prefix; + loff_t size; + int ret, i; + + ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd); + if (ret) + return log_msg_ret("std", ret); + + /* We require a partition table */ + if (!bflow->part) + return -ENOENT; + + prefixes = bootstd_get_prefixes(bootstd); + i = 0; + do { + prefix = prefixes ? prefixes[i] : NULL; + + ret = bootmeth_try_file(bflow, desc, prefix, DISTRO_FNAME); + } while (ret && prefixes && prefixes[++i]); + if (ret) + return log_msg_ret("try", ret); + size = bflow->size; + + ret = bootmeth_alloc_file(bflow, 0x10000, 1); + if (ret) + return log_msg_ret("read", ret); + + return 0; +} + +static int distro_boot(struct udevice *dev, struct bootflow *bflow) +{ + struct cmd_tbl cmdtp = {}; /* dummy */ + struct pxe_context ctx; + struct distro_info info; + ulong addr; + int ret; + + addr = map_to_sysmem(bflow->buf); + info.dev = dev; + info.bflow = bflow; + ret = pxe_setup_ctx(&ctx, &cmdtp, disto_getfile, &info, true, + bflow->subdir); + if (ret) + return log_msg_ret("ctx", -EINVAL); + + ret = pxe_process(&ctx, addr, false); + if (ret) + return log_msg_ret("bread", -EINVAL); + + return 0; +} + +static int distro_bootmeth_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ? + "Syslinux boot from a block device" : "syslinux"; + + return 0; +} + +static struct bootmeth_ops distro_bootmeth_ops = { + .check = distro_check, + .read_bootflow = distro_read_bootflow, + .read_file = bootmeth_common_read_file, + .boot = distro_boot, +}; + +static const struct udevice_id distro_bootmeth_ids[] = { + { .compatible = "u-boot,distro-syslinux" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_distro) = { + .name = "bootmeth_distro", + .id = UCLASS_BOOTMETH, + .of_match = distro_bootmeth_ids, + .ops = &distro_bootmeth_ops, + .bind = distro_bootmeth_bind, +}; diff --git a/include/distro.h b/include/distro.h new file mode 100644 index 00000000000..2ee145871b2 --- /dev/null +++ b/include/distro.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __distro_h +#define __distro_h + +#define DISTRO_FNAME "extlinux/extlinux.conf" + +/** + * struct distro_info - useful information for distro_getfile() + * + * @dev: bootmethod device being used to boot + * @bflow: bootflow being booted + */ +struct distro_info { + struct udevice *dev; + struct bootflow *bflow; + struct cmd_tbl *cmdtp; +}; + +#endif From patchwork Wed Jan 19 01:43:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581609 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=VvkZtxT2; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpQs3CTbz9sPC for ; Wed, 19 Jan 2022 12:46:45 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 22DF483861; Wed, 19 Jan 2022 02:45:02 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="VvkZtxT2"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7B60783106; Wed, 19 Jan 2022 02:44:18 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x133.google.com (mail-il1-x133.google.com [IPv6:2607:f8b0:4864:20::133]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3C378837DE for ; Wed, 19 Jan 2022 02:43:59 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x133.google.com with SMTP id h30so827308ila.12 for ; Tue, 18 Jan 2022 17:43:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=swIoId1RzpWCHkz3ItihbFrVIR/1wNxp350Qv0F/H+Q=; b=VvkZtxT2sctj93tZArdLsvhQpuC/YmO5nS9eAw3fEi9KezmebsKMEOLzPZKYaap/an Kta2h+MK2EoLBBnDKqbwCjE3ZqPgVAk9YF+xTDGMpCkPvz9CYbHfB7iWpyFaMmJeKF3x y+SzWbYYXfiHv8rR2f9Ls/vAVkhw3JaVU6MrU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=swIoId1RzpWCHkz3ItihbFrVIR/1wNxp350Qv0F/H+Q=; b=U2VBXOegehMjSSGhhYdgIS/Liy5YC2KD9p1/ImJdW4GgHrLfLkYXN3//UJxjIPKHBD dN4p9RbnlN4iB+trFrS50rtiwHj1uTspSrWsiplDCTvARbwQ4MioHgXTtQeRQlAeVHN7 Yzq/kWzLtjXMudQYIicc8fiQec5o8TBd0PKHlOPyOSZ0o/fM0wo3lnDnvrqo9KkDvz4Z c7cK7nydE3FyJ0RXzO+RLyLLCP/YDRD7MfOopBvkf7Gvcd256IAXsTkzrIfw1WY3SjMw pFx0oRz2OZcuXX7u0roaw32s0KWLVQWWMWaQuykDybSzIPA3c5kiwUiVD0Kyr6no/nt/ Yjxw== X-Gm-Message-State: AOAM5319M5IDd0B9r0CBbzFZyIjjeuN/IInjq6xN7rO+Xt4YqkJjrSms lw8HG6CZgvnC08LDSrGGgnaEcKME1DQ6Qg== X-Google-Smtp-Source: ABdhPJwXdGBVPTX6pzhQ9DVyPajw0s4pi9pPYHapoGPUNljw/xcfLuXCfmuPdWsBxM6qNxmG0KEoIA== X-Received: by 2002:a92:2805:: with SMTP id l5mr12398677ilf.18.1642556637809; Tue, 18 Jan 2022 17:43:57 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:57 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass , Jaehoon Chung , Peng Fan Subject: [PATCH v3 19/31] bootstd: mmc: Add a bootdev driver Date: Tue, 18 Jan 2022 18:43:03 -0700 Message-Id: <20220118184259.v3.19.Idda0c29539776a431958d22f1ac59dd20eec9697@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootdev driver for MMC. It mostly just calls the bootdev helper function. Add a function to obtain the block device for an MMC controller. Fix up the comment for mmc_get_blk_desc() while we are here. Signed-off-by: Simon Glass --- Changes in v3: - Adjust for new blk_find_device() function MAINTAINERS | 1 + drivers/mmc/Makefile | 5 ++++ drivers/mmc/mmc-uclass.c | 23 +++++++++++++++ drivers/mmc/mmc_bootdev.c | 62 +++++++++++++++++++++++++++++++++++++++ include/mmc.h | 12 +++++++- 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 drivers/mmc/mmc_bootdev.c diff --git a/MAINTAINERS b/MAINTAINERS index e907151276a..102821564ca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -669,6 +669,7 @@ F: boot/bootmeth*.c F: boot/bootstd.c F: cmd/bootdev.c F: cmd/bootflow.c +F: drivers/mmc/mmc_bootdev.c F: include/bootdev.h F: include/bootflow.h F: include/bootmeth.h diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 17ebc04203e..96275093022 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -5,6 +5,11 @@ obj-y += mmc.o obj-$(CONFIG_$(SPL_)DM_MMC) += mmc-uclass.o + +ifdef CONFIG_$(SPL_TPL_)DM_MMC +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += mmc_bootdev.o +endif + obj-$(CONFIG_$(SPL_)MMC_WRITE) += mmc_write.o obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index b80e838066c..35b8cdbe35f 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY UCLASS_MMC #include +#include #include #include #include @@ -315,6 +316,20 @@ int mmc_get_next_devnum(void) return blk_find_max_devnum(IF_TYPE_MMC); } +int mmc_get_blk(struct udevice *dev, struct udevice **blkp) +{ + struct udevice *blk; + int ret; + + device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk); + ret = device_probe(blk); + if (ret) + return ret; + *blkp = blk; + + return 0; +} + struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) { struct blk_desc *desc; @@ -406,6 +421,10 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) mmc->cfg = cfg; mmc->priv = dev; + ret = bootdev_setup_for_dev(dev, "mmc_bootdev"); + if (ret) + return log_msg_ret("bootdev", ret); + /* the following chunk was from mmc_register() */ /* Setup dsr related values */ @@ -424,12 +443,16 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) int mmc_unbind(struct udevice *dev) { struct udevice *bdev; + int ret; device_find_first_child_by_uclass(dev, UCLASS_BLK, &bdev); if (bdev) { device_remove(bdev, DM_REMOVE_NORMAL); device_unbind(bdev); } + ret = bootdev_unbind_dev(dev); + if (ret) + return log_msg_ret("bootdev", ret); return 0; } diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c new file mode 100644 index 00000000000..b4f41fb3a67 --- /dev/null +++ b/drivers/mmc/mmc_bootdev.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootdevice for MMC + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include + +static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + struct udevice *mmc_dev = dev_get_parent(dev); + struct udevice *blk; + int ret; + + ret = mmc_get_blk(mmc_dev, &blk); + /* + * If there is no media, indicate that no more partitions should be + * checked + */ + if (ret == -EOPNOTSUPP) + ret = -ESHUTDOWN; + if (ret) + return log_msg_ret("blk", ret); + assert(blk); + ret = bootdev_find_in_blk(dev, blk, iter, bflow); + if (ret) + return log_msg_ret("find", ret); + + return 0; +} + +static int mmc_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_0_INTERNAL_FAST; + + return 0; +} + +struct bootdev_ops mmc_bootdev_ops = { + .get_bootflow = mmc_get_bootflow, +}; + +static const struct udevice_id mmc_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-mmc" }, + { } +}; + +U_BOOT_DRIVER(mmc_bootdev) = { + .name = "mmc_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &mmc_bootdev_ops, + .bind = mmc_bootdev_bind, + .of_match = mmc_bootdev_ids, +}; diff --git a/include/mmc.h b/include/mmc.h index 244d2dc5921..3637903392a 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -956,10 +956,20 @@ int mmc_get_env_dev(void); * mmc_get_blk_desc() - Get the block descriptor for an MMC device * * @mmc: MMC device - * @return block device if found, else NULL + * @return block descriptor if found, else NULL */ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc); +/** + * mmc_get_blk() - Get the block device for an MMC device + * + * @dev: MMC device + * @blkp: Returns pointer to probed block device on sucesss + * + * @return 0 on success, -ve on error + */ +int mmc_get_blk(struct udevice *dev, struct udevice **blkp); + /** * mmc_send_ext_csd() - read the extended CSD register * From patchwork Wed Jan 19 01:43:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581612 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Zao9IyoN; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpRQ4XW3z9sPC for ; Wed, 19 Jan 2022 12:47:14 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 86F5683868; Wed, 19 Jan 2022 02:45:16 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Zao9IyoN"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2E6B283178; Wed, 19 Jan 2022 02:44:23 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2e.google.com (mail-io1-xd2e.google.com [IPv6:2607:f8b0:4864:20::d2e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B180583807 for ; Wed, 19 Jan 2022 02:44:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2e.google.com with SMTP id v1so935625ioj.10 for ; Tue, 18 Jan 2022 17:44:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NhiFLqxIwUT9EabbdJvylDRGRU68sCXhf7L2bgorAOc=; b=Zao9IyoNZ2vVbgbpBAlWjc5HigvjXuSG6YDFHqQ4RAXWgN21oA88U6eMpweVuQDudW 57bK8/aaXW6+VC/5mgzeVbBOd5E29JWO4r0Mc0iQzwgYg38goMP85XZviZYtnwOF0Jqh vbq7nY0MaxmnZwzHY0r5Yv4/XbCyCq6588zGo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NhiFLqxIwUT9EabbdJvylDRGRU68sCXhf7L2bgorAOc=; b=5/uGGA47tCvvkgiTGfAFNF+8QyWsVy4x/cT3cl8TDfpaQkr3gDSpLnzuAaijmKB8VY iC29H01BtT/UOHNgjWDVcQM2+sTJXNfv85gA62RBKV8gHck/ypTXSA3mano67WrOh99X bE6PLxUditwyd1ieu5Z1ZyIsCFw9mFxQRalEQSp73HTgYDvSAZWXRcCtWevJNuiY3uud tfBfQ7uQJRWHi5gvplCSLHnUnP0FBPPY7b7GlkYY13ddElIR70+JN7VzkPU5C0si8DEk mFYbpZPW5xanEDuIXx7sikkCw6MNlvaJPJDnZGEk/P+zwRa8i45UU6O78N1ProHQmXwD 8omw== X-Gm-Message-State: AOAM530++f8AYwUBL+/z4rczYenUNt9qZoBXpgTALIlYrtvmsXhPPTtR 4QlJQ43228XDhc5Sz37xryH881jKvw5NAg== X-Google-Smtp-Source: ABdhPJzG9FWlkm7gm90lbM4ytMuojJpi8coVESxoz+phKOZpn8O2GePPJMoxR4ugKlBbjC0kYlk54g== X-Received: by 2002:a05:6638:410a:: with SMTP id ay10mr13494894jab.237.1642556639075; Tue, 18 Jan 2022 17:43:59 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:58 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 20/31] bootstd: ethernet: Add a bootdev driver Date: Tue, 18 Jan 2022 18:43:04 -0700 Message-Id: <20220118184259.v3.20.Ibb454281fc9a82c3ad084f0f2f876e46809eee02@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootdev driver for Ethernet. It can use the PXE boot mechanism to locate a file, added later. Signed-off-by: Simon Glass --- (no changes since v1) MAINTAINERS | 1 + net/Kconfig | 9 +++++ net/Makefile | 1 + net/eth-uclass.c | 8 ++++ net/eth_bootdev.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 net/eth_bootdev.c diff --git a/MAINTAINERS b/MAINTAINERS index 102821564ca..fe168b51a59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -674,6 +674,7 @@ F: include/bootdev.h F: include/bootflow.h F: include/bootmeth.h F: include/bootstd.h +F: net/eth_bootdevice.c BTRFS M: Marek Behun diff --git a/net/Kconfig b/net/Kconfig index 7a2d1450188..e110930553a 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -14,6 +14,15 @@ config PROT_UDP Enable a generic udp framework that allows defining a custom handler for udp protocol. +config BOOTDEV_ETH + bool "Enable bootdev for ethernet" + depends on BOOTSTD + default y + help + Provide a bootdev for ethernet so that is it possible to boot + an operationg system over the network, using the PXE (Preboot + Execution Environment) protocol. + config BOOTP_SEND_HOSTNAME bool "Send hostname to DNS server" help diff --git a/net/Makefile b/net/Makefile index fb3eba840ff..6c812502d3e 100644 --- a/net/Makefile +++ b/net/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CMD_DNS) += dns.o obj-$(CONFIG_DM_DSA) += dsa-uclass.o ifdef CONFIG_DM_ETH obj-$(CONFIG_NET) += eth-uclass.o +obj-$(CONFIG_$(SPL_TPL_)BOOTDEV_ETH) += eth_bootdev.o else obj-$(CONFIG_NET) += eth_legacy.o endif diff --git a/net/eth-uclass.c b/net/eth-uclass.c index 0da0e85be03..cccbc87ab29 100644 --- a/net/eth-uclass.c +++ b/net/eth-uclass.c @@ -8,6 +8,7 @@ #define LOG_CATEGORY UCLASS_ETH #include +#include #include #include #include @@ -473,6 +474,8 @@ int eth_initialize(void) static int eth_post_bind(struct udevice *dev) { + int ret; + if (strchr(dev->name, ' ')) { printf("\nError: eth device name \"%s\" has a space!\n", dev->name); @@ -482,6 +485,11 @@ static int eth_post_bind(struct udevice *dev) #ifdef CONFIG_DM_ETH_PHY eth_phy_binds_nodes(dev); #endif + if (CONFIG_IS_ENABLED(BOOTDEV_ETH)) { + ret = bootdev_setup_for_dev(dev, "eth_bootdev"); + if (ret) + return log_msg_ret("bootdev", ret); + } return 0; } diff --git a/net/eth_bootdev.c b/net/eth_bootdev.c new file mode 100644 index 00000000000..b735966d2bc --- /dev/null +++ b/net/eth_bootdev.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootdevice for ethernet (uses PXE) + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int eth_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + char name[60]; + int ret; + + /* Must be an Ethernet device */ + ret = bootflow_iter_uses_network(iter); + if (ret) + return log_msg_ret("net", ret); + + ret = bootmeth_check(bflow->method, iter); + if (ret) + return log_msg_ret("check", ret); + + /* + * Like distro boot, this assumes there is only one Ethernet device. + * In this case, that means that @eth is ignored + */ + + snprintf(name, sizeof(name), "%s.%d", dev->name, iter->part); + bflow->name = strdup(name); + if (!bflow->name) + return log_msg_ret("name", -ENOMEM); + + /* + * There is not a direct interface to the network stack so run + * everything through the command-line interpreter for now. + * + * Don't bother checking the result of dhcp. It can fail with: + * + * DHCP client bound to address 192.168.4.50 (4 ms) + * *** Warning: no boot file name; using 'C0A80432.img' + * Using smsc95xx_eth device + * TFTP from server 192.168.4.1; our IP address is 192.168.4.50 + * Filename 'C0A80432.img'. + * Load address: 0x200000 + * Loading: * + * TFTP error: 'File not found' (1) + * + * This is not a real failure, since we don't actually care if the + * boot file exists. + */ + log_debug("running dhcp\n"); + run_command("dhcp", 0); + bflow->state = BOOTFLOWST_MEDIA; + + /* See distro_pxe_read_bootflow() for the standard impl of this */ + log_debug("dhcp complete - reading bootflow with method %s\n", + bflow->method->name); + ret = bootmeth_read_bootflow(bflow->method, bflow); + log_debug("reading bootflow returned %d\n", ret); + if (ret) + return log_msg_ret("method", ret); + + return 0; +} + +static int eth_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_4_NET_BASE; + + return 0; +} + +struct bootdev_ops eth_bootdev_ops = { + .get_bootflow = eth_get_bootflow, +}; + +static const struct udevice_id eth_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-eth" }, + { } +}; + +U_BOOT_DRIVER(eth_bootdev) = { + .name = "eth_bootdev", + .id = UCLASS_BOOTDEV, + .ops = ð_bootdev_ops, + .bind = eth_bootdev_bind, + .of_match = eth_bootdev_ids, +}; From patchwork Wed Jan 19 01:43:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581611 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=eOuZJtS0; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpRC6rDMz9sPC for ; Wed, 19 Jan 2022 12:47:03 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8BA4083876; Wed, 19 Jan 2022 02:45:08 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="eOuZJtS0"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9F2C183178; Wed, 19 Jan 2022 02:44:21 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12d.google.com (mail-il1-x12d.google.com [IPv6:2607:f8b0:4864:20::12d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 7A84A83810 for ; Wed, 19 Jan 2022 02:44:01 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12d.google.com with SMTP id v17so867742ilg.4 for ; Tue, 18 Jan 2022 17:44:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lloZJ7gmOC/re0qxBCkpNOwYk1w9gikjziH4ZfsE9PM=; b=eOuZJtS0DIBsviLNNRUfheJbACYFutmy7GinT70Ggzn3vhunuK1h0zs0bFog6Ot84K 40m2q+g63zacAsFdOdj1HSCpN/nXBa7rEp4R9Y9JXaaL+6dJfV6VjBBHHjVKe0an9+hr Xm9wJmYH/mWfoAk9uuaU812856qqH2haGNhvM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lloZJ7gmOC/re0qxBCkpNOwYk1w9gikjziH4ZfsE9PM=; b=SGeiNNqxBlVrSENoE07iH6UFALFr9uQ9skm86QGBL7WXGp1C/I+N/EcK/qD7DL6o3x HfX+I93cu/s7ig09xVG88n2//JHqNkpfkaX68/FrEb2HO3VX/nsUV9q6Q9KSzo0B79ol 4WAir0l8kpKKYjvhTcukoMn7uBdEyqIWmM02znkeDPB7FG5xyM0YIoMU432tDvCUPufX a9G2vUPnPrELdU9AYW8lw8K5B8GXZ7M+KIEOe1dReg2HL6iCXc0ue0rItipxIfQCv7ZJ tQJk3NZaxPVEUPeHgZe5INGC8Pw6Y7iTvj04hLKk1aOb/Ju62wik/NT/lq81WUABmlIK TjoA== X-Gm-Message-State: AOAM531ifU0RRVChVsZPofFyfQd9wWFaVuaz5O5IW5r+X34fdW7bkXjt Osj04GTYsq+2TgtTiJohGasVCuayIUceZA== X-Google-Smtp-Source: ABdhPJys3AvNpSMAuNdhtJnUNqNpiFcBBWgrBKcz6QzE4hNZuJM1h8MlN1PS85poR3N+tQzRpnX7Lg== X-Received: by 2002:a05:6e02:1908:: with SMTP id w8mr8851590ilu.50.1642556639987; Tue, 18 Jan 2022 17:43:59 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.43.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:43:59 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 21/31] bootstd: Add an implementation of distro PXE boot Date: Tue, 18 Jan 2022 18:43:05 -0700 Message-Id: <20220119014315.1938157-13-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootmeth driver which handles distro boot from a network device, so we can boot a bootflow using this commonly used mechanism. In effect, this provides the same functionality as the 'pxe' command and shares the same code. But the interface into it is via a bootmeth. For now this requires the 'pxe' command be enabled. Future work may tidy this up so that it can be used without CONFIG_CMDLINE being enabled. Signed-off-by: Simon Glass --- Changes in v3: - Add a log category - Use a short name when BOOTSTD_FULL is not enabled boot/Kconfig | 10 +++ boot/Makefile | 1 + boot/bootmeth_pxe.c | 186 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) create mode 100644 boot/bootmeth_pxe.c diff --git a/boot/Kconfig b/boot/Kconfig index 45d38a226cb..61df705141d 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -328,6 +328,16 @@ config BOOTMETH_DISTRO This provides a way to try out standard boot on an existing boot flow. +config BOOTMETH_DISTRO_PXE + bool "Bootdev support for distro boot over network" + depends on CMD_PXE && CMD_NET && DM_ETH + default y + help + Enables support for distro boot using bootdevs. This makes the + bootdevs look for a 'extlinux/extlinux.conf' on the tftp server. + + This provides a way to try out standard boot on an existing boot flow. + endif config LEGACY_IMAGE_FORMAT diff --git a/boot/Makefile b/boot/Makefile index d8f5c340b85..170fcac8ec4 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c new file mode 100644 index 00000000000..f1e2b4c7762 --- /dev/null +++ b/boot/bootmeth_pxe.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for distro boot using PXE (network boot) + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int disto_pxe_getfile(struct pxe_context *ctx, const char *file_path, + char *file_addr, ulong *sizep) +{ + struct distro_info *info = ctx->userdata; + ulong addr; + int ret; + + addr = simple_strtoul(file_addr, NULL, 16); + ret = bootmeth_read_file(info->dev, info->bflow, file_path, addr, + sizep); + if (ret) + return log_msg_ret("read", ret); + + return 0; +} + +static int distro_pxe_check(struct udevice *dev, struct bootflow_iter *iter) +{ + int ret; + + /* This only works on network devices */ + ret = bootflow_iter_uses_network(iter); + if (ret) + return log_msg_ret("net", ret); + + return 0; +} + +static int distro_pxe_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + const char *addr_str; + char fname[200]; + char *bootdir; + ulong addr; + ulong size; + char *buf; + int ret; + + addr_str = env_get("pxefile_addr_r"); + if (!addr_str) + return log_msg_ret("pxeb", -EPERM); + addr = simple_strtoul(addr_str, NULL, 16); + + log_debug("calling pxe_get()\n"); + ret = pxe_get(addr, &bootdir, &size); + log_debug("pxe_get() returned %d\n", ret); + if (ret) + return log_msg_ret("pxeb", ret); + bflow->size = size; + + /* Use the directory of the dhcp bootdir as our subdir, if provided */ + if (bootdir) { + const char *last_slash; + int path_len; + + last_slash = strrchr(bootdir, '/'); + if (last_slash) { + path_len = (last_slash - bootdir) + 1; + bflow->subdir = malloc(path_len + 1); + memcpy(bflow->subdir, bootdir, path_len); + bflow->subdir[path_len] = '\0'; + } + } + snprintf(fname, sizeof(fname), "%s%s", + bflow->subdir ? bflow->subdir : "", DISTRO_FNAME); + + bflow->fname = strdup(fname); + if (!bflow->fname) + return log_msg_ret("name", -ENOMEM); + + bflow->state = BOOTFLOWST_READY; + + /* Allocate the buffer, including the \0 byte added by get_pxe_file() */ + buf = malloc(size + 1); + if (!buf) + return log_msg_ret("buf", -ENOMEM); + memcpy(buf, map_sysmem(addr, 0), size + 1); + bflow->buf = buf; + + return 0; +} + +static int distro_pxe_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + char *tftp_argv[] = {"tftp", NULL, NULL, NULL}; + struct pxe_context *ctx = dev_get_priv(dev); + char file_addr[17]; + ulong size; + int ret; + + sprintf(file_addr, "%lx", addr); + tftp_argv[1] = file_addr; + tftp_argv[2] = (void *)file_path; + + if (do_tftpb(ctx->cmdtp, 0, 3, tftp_argv)) + return -ENOENT; + ret = pxe_get_file_size(&size); + if (ret) + return log_msg_ret("tftp", ret); + if (size > *sizep) + return log_msg_ret("spc", -ENOSPC); + *sizep = size; + + return 0; +} + +static int distro_pxe_boot(struct udevice *dev, struct bootflow *bflow) +{ + struct pxe_context *ctx = dev_get_priv(dev); + struct cmd_tbl cmdtp = {}; /* dummy */ + struct distro_info info; + ulong addr; + int ret; + + addr = map_to_sysmem(bflow->buf); + info.dev = dev; + info.bflow = bflow; + info.cmdtp = &cmdtp; + ret = pxe_setup_ctx(ctx, &cmdtp, disto_pxe_getfile, &info, false, + bflow->subdir); + if (ret) + return log_msg_ret("ctx", -EINVAL); + + ret = pxe_process(ctx, addr, false); + if (ret) + return log_msg_ret("bread", -EINVAL); + + return 0; +} + +static int distro_bootmeth_pxe_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ? + "PXE boot from a network device" : "PXE"; + + return 0; +} + +static struct bootmeth_ops distro_bootmeth_pxe_ops = { + .check = distro_pxe_check, + .read_bootflow = distro_pxe_read_bootflow, + .read_file = distro_pxe_read_file, + .boot = distro_pxe_boot, +}; + +static const struct udevice_id distro_bootmeth_pxe_ids[] = { + { .compatible = "u-boot,distro-pxe" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_pxe) = { + .name = "bootmeth_pxe", + .id = UCLASS_BOOTMETH, + .of_match = distro_bootmeth_pxe_ids, + .ops = &distro_bootmeth_pxe_ops, + .bind = distro_bootmeth_pxe_bind, + .priv_auto = sizeof(struct pxe_context), +}; From patchwork Wed Jan 19 01:43:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581615 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=ZGB9jTio; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpS20q0Wz9sPC for ; Wed, 19 Jan 2022 12:47:46 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 94AAF8384B; Wed, 19 Jan 2022 02:45:24 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="ZGB9jTio"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BAFA3837B6; Wed, 19 Jan 2022 02:44:24 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd32.google.com (mail-io1-xd32.google.com [IPv6:2607:f8b0:4864:20::d32]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 78C65837B6 for ; Wed, 19 Jan 2022 02:44:02 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd32.google.com with SMTP id y22so958475iof.7 for ; Tue, 18 Jan 2022 17:44:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HPBsjTzeejMAmfygWgfQ1m0DeWcxahc6/kDR4FhPD/A=; b=ZGB9jTiokm3OSHJXt7o7OxsUOQW0TCI7eI7PxNKi2NNsXbcTHdNHqDyH781bhumG0+ Kw6G0CD1+benDAojrZEfXRU9uZhFGBUOb9rI+5KsMkzdceRsYT+2FBgCRRURYyGNpcMZ UDtuGwP6U4Hv+P56cIVQUPxKwyn5wQ/tlsKsE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HPBsjTzeejMAmfygWgfQ1m0DeWcxahc6/kDR4FhPD/A=; b=Z4utLrUJxxgpwKSDtTmCanx4HiZ2HV2sHPM87Z1Vqq/pSTv/RmISryqRaizUQ/OJ6G 2ACHOQu0S949ZY/pbN7/qKRgs5RaSoQq13QfDRdRT4AkW+opjarrAPiBsLysen4bAa+9 SoAURRaFagQS5srRLAzReVqLf35HEVdaR+OJbqsxw6MTQ1vknetceMIuNgqkCMxUSLcv sgBpVKfsedsinXx8a7LHg34skQSAdqxTW4gblpGWAmuuTUbq4Gr6xq/QysWYCUj/QAVq 0ckkwpGWG+rOQtFg3PaCb41zLHXYsokgBg00EoIaoV2sqhUFzb71+YuISiB3axK8q/CY 5SuQ== X-Gm-Message-State: AOAM530CqnYsW2Q//WL7y9N23R+bLbQcvbFg87LkYvbraHbQ/7kDV6Gl Gg+pYKIO1ZbPeqCPQEQ8v0cLRzVBpRS0HQ== X-Google-Smtp-Source: ABdhPJxSqjcXlApMSKqG8ewrluQi+7MRP12Lctmyw1zDr2khuvFpbeHeJ4d8yNYPcEDsO40IxJm08Q== X-Received: by 2002:a05:6602:1548:: with SMTP id h8mr9200157iow.91.1642556640772; Tue, 18 Jan 2022 17:44:00 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:00 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 22/31] bootstd: Add an implementation of EFI boot Date: Tue, 18 Jan 2022 18:43:06 -0700 Message-Id: <20220119014315.1938157-14-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootmeth driver which handles EFI boot, using EFI_LOADER. In effect, this provides the same functionality as the 'bootefi' command and shares the same code. But the interface into it is via a bootmeth, so it does not require any special scripts, etc. For now this requires the 'bootefi' command be enabled. Future work may tidy this up so that it can be used without CONFIG_CMDLINE being enabled. There was much discussion about whether this is needed, but it seems that it is, at least for now. Signed-off-by: Simon Glass --- Changes in v3: - Add a log category - Use a short name when BOOTSTD_FULL is not enabled - Align the EFI load address - Use common bootmeth functions boot/Kconfig | 21 +++++ boot/Makefile | 1 + boot/bootmeth_efi.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 boot/bootmeth_efi.c diff --git a/boot/Kconfig b/boot/Kconfig index 61df705141d..0fee35070b0 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -338,6 +338,27 @@ config BOOTMETH_DISTRO_PXE This provides a way to try out standard boot on an existing boot flow. +config BOOTMETH_EFILOADER + bool "Bootdev support for EFI boot" + depends on CMD_BOOTEFI + default y + help + Enables support for EFI boot using bootdevs. This makes the + bootdevs look for a 'boot.efi' on each filesystem + they scan. The resulting file is booted after enabling U-Boot's + EFI loader support. + + The depends on the architecture of the board: + + aa64 - aarch64 (ARM 64-bit) + arm - ARM 32-bit + ia32 - x86 32-bit + x64 - x86 64-bit + riscv32 - RISC-V 32-bit + riscv64 - RISC-V 64-bit + + This provides a way to try out standard boot on an existing boot flow. + endif config LEGACY_IMAGE_FORMAT diff --git a/boot/Makefile b/boot/Makefile index 170fcac8ec4..c2345435201 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c new file mode 100644 index 00000000000..4c0c3494c3b --- /dev/null +++ b/boot/bootmeth_efi.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for distro boot via EFI + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFI_DIRNAME "efi/boot/" + +/** + * get_efi_leafname() - Get the leaf name for the EFI file we expect + * + * @str: Place to put leaf name for this architecture, e.g. "bootaa64.efi". + * Must have at least 16 bytes of space + * @max_len: Length of @str, must be >=16 + */ +static int get_efi_leafname(char *str, int max_len) +{ + const char *base; + + if (max_len < 16) + return log_msg_ret("spc", -ENOSPC); + if (IS_ENABLED(CONFIG_ARM64)) + base = "bootaa64"; + else if (IS_ENABLED(CONFIG_ARM)) + base = "bootarm"; + else if (IS_ENABLED(CONFIG_X86_RUN_32BIT)) + base = "bootia32"; + else if (IS_ENABLED(CONFIG_X86_RUN_64BIT)) + base = "bootx64"; + else if (IS_ENABLED(CONFIG_ARCH_RV32I)) + base = "bootriscv32"; + else if (IS_ENABLED(CONFIG_ARCH_RV64I)) + base = "bootriscv64"; + else if (IS_ENABLED(CONFIG_SANDBOX)) + base = "bootsbox"; + else + return -EINVAL; + + strcpy(str, base); + strcat(str, ".efi"); + + return 0; +} + +static int efiload_read_file(struct blk_desc *desc, struct bootflow *bflow) +{ + const struct udevice *media_dev; + int size = bflow->size; + char devnum_str[9]; + char dirname[200]; + char *last_slash; + int ret; + + ret = bootmeth_alloc_file(bflow, 0x2000000, 0x10000); + if (ret) + return log_msg_ret("read", ret); + + /* + * This is a horrible hack to tell EFI about this boot device. Once we + * unify EFI with the rest of U-Boot we can clean this up. The same hack + * exists in multiple places, e.g. in the fs, tftp and load commands. + * + * Once we can clean up the EFI code to make proper use of driver model, + * this can go away. + */ + media_dev = dev_get_parent(bflow->dev); + snprintf(devnum_str, sizeof(devnum_str), "%x", dev_seq(media_dev)); + + strlcpy(dirname, bflow->fname, sizeof(dirname)); + last_slash = strrchr(dirname, '/'); + if (last_slash) + *last_slash = '\0'; + + log_debug("setting bootdev %s, %s\n", dev_get_uclass_name(media_dev), + bflow->fname); + efi_set_bootdev(dev_get_uclass_name(media_dev), devnum_str, + bflow->fname, bflow->buf, size); + + return 0; +} + +static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter) +{ + int ret; + + /* This only works on block devices */ + ret = bootflow_iter_uses_blk_dev(iter); + if (ret) + return log_msg_ret("blk", ret); + + return 0; +} + +static int distro_efi_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + char fname[sizeof(EFI_DIRNAME) + 16]; + int ret; + + /* We require a partition table */ + if (!bflow->part) + return -ENOENT; + + strcpy(fname, EFI_DIRNAME); + ret = get_efi_leafname(fname + strlen(fname), + sizeof(fname) - strlen(fname)); + if (ret) + return log_msg_ret("leaf", ret); + + ret = bootmeth_try_file(bflow, desc, NULL, fname); + if (ret) + return log_msg_ret("try", ret); + + ret = efiload_read_file(desc, bflow); + if (ret) + return log_msg_ret("read", -EINVAL); + + return 0; +} + +int distro_efi_boot(struct udevice *dev, struct bootflow *bflow) +{ + char cmd[50]; + + /* + * At some point we can add a real interface to bootefi so we can call + * this directly. For now, go through the CLI like distro boot. + */ + snprintf(cmd, sizeof(cmd), "bootefi %lx %lx", + (ulong)map_to_sysmem(bflow->buf), + (ulong)map_to_sysmem(gd->fdt_blob)); + if (run_command(cmd, 0)) + return log_msg_ret("run", -EINVAL); + + return 0; +} + +static int distro_bootmeth_efi_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ? + "EFI boot from a .efi file" : "EFI"; + + return 0; +} + +static struct bootmeth_ops distro_efi_bootmeth_ops = { + .check = distro_efi_check, + .read_bootflow = distro_efi_read_bootflow, + .read_file = bootmeth_common_read_file, + .boot = distro_efi_boot, +}; + +static const struct udevice_id distro_efi_bootmeth_ids[] = { + { .compatible = "u-boot,distro-efi" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_efi) = { + .name = "bootmeth_efi", + .id = UCLASS_BOOTMETH, + .of_match = distro_efi_bootmeth_ids, + .ops = &distro_efi_bootmeth_ops, + .bind = distro_bootmeth_efi_bind, +}; From patchwork Wed Jan 19 01:43:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581629 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=LgdP/hub; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpYy0T5Wz9sPC for ; Wed, 19 Jan 2022 12:52:54 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6148C837E7; Wed, 19 Jan 2022 02:52:43 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="LgdP/hub"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C307D831EA; Wed, 19 Jan 2022 02:52:40 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2f.google.com (mail-io1-xd2f.google.com [IPv6:2607:f8b0:4864:20::d2f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2392F83815 for ; Wed, 19 Jan 2022 02:44:03 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2f.google.com with SMTP id p7so989956iod.2 for ; Tue, 18 Jan 2022 17:44:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MwHZzbXNR7wQHiLnrcgymfVcvG29nj0B0nj9x/qIIFY=; b=LgdP/hubAOOCFKJcTU78qDqYn62Vvm/XWdidajZJRPh3tHoPvF37ZII7S3IetnSIAJ Cxh/19PZ7Y1yqDe34UMMBdvTkY6ppq0T14CQcHiDdqPcGcQ6miukv34Uu0yqj2pNCeBk GBWLfniRCEV7So2jGXRz4FXH29zKjaouvTS1w= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MwHZzbXNR7wQHiLnrcgymfVcvG29nj0B0nj9x/qIIFY=; b=1TMOM+XcF35LzLPyJrsGjSiqqmgCGyzApv7mH844/ck5+ZrtYrl1btLpLJxRO/a41k 4IwqYpaWVEtoPRsA/7krspdB0Ryo1eUPX7BasKA6uBTr3IjPX12soqkqrMzagAEauomQ dze2kJmbSy6ZG0XYVY+WwnwHUKmfHGN3K6TKnA+EG0er2oFK7pWQhYUpIbfOG9DNyKBc cwK4laabuUsGABuY/EZimQJoV69mdT17I5K7+/u1pDg3cpgJYFzccJHSaxdNcTFoQMce XxlmJgC9PnkHNREKzGsuF7gqtAMwyB2ah0s8THFe1CD/kIj6crfVKz7V+LO+8bcV3/oS dxeQ== X-Gm-Message-State: AOAM53388p6VthU/Rd7Vm7HNJPWjVJn8k0R6zRxrQI4iwd0AoMbjOTaY /5MX4T6Nq+N4PIiHsp4sAuDlwaYFidtbXw== X-Google-Smtp-Source: ABdhPJx1CaT54DsWZmIFH+Ed+bWTFsLcLcFggg54pYr/b6+5sWwGgbC/dcLtC6N0C2rD0fwTami/Dw== X-Received: by 2002:a5d:87d8:: with SMTP id q24mr13802414ios.154.1642556641811; Tue, 18 Jan 2022 17:44:01 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:01 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 23/31] bootstd: Add a system bootdev for strange boot methods Date: Tue, 18 Jan 2022 18:43:07 -0700 Message-Id: <20220119014315.1938157-15-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Some boot methods don't act on a single bootdev but instead do their own thing. An example is EFI bootmgr which scan various devices using its own logic. Add a bootdev to handle this. Signed-off-by: Simon Glass --- Changes in v3: - Add a log category boot/Makefile | 2 +- boot/bootstd-uclass.c | 6 ++++ boot/system_bootdev.c | 66 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 boot/system_bootdev.c diff --git a/boot/Makefile b/boot/Makefile index c2345435201..795665f7ce5 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -23,7 +23,7 @@ obj-y += image.o image-board.o obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o -obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootdev-uclass.o system_bootdev.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootflow.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootmeth-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c index 63fded98baf..e29a34366ee 100644 --- a/boot/bootstd-uclass.c +++ b/boot/bootstd-uclass.c @@ -150,6 +150,12 @@ int dm_scan_other(bool pre_reloc_only) } } + /* Create the system bootdev too */ + ret = device_bind_driver(bootstd, "system_bootdev", "system-bootdev", + &dev); + if (ret) + return log_msg_ret("sys", ret); + return 0; } diff --git a/boot/system_bootdev.c b/boot/system_bootdev.c new file mode 100644 index 00000000000..432d2034780 --- /dev/null +++ b/boot/system_bootdev.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootdevice for system, used for bootmeths not tied to any partition device + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int system_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + int ret; + + /* Must be an bootstd device */ + ret = bootflow_iter_uses_system(iter); + if (ret) + return log_msg_ret("net", ret); + + ret = bootmeth_check(bflow->method, iter); + if (ret) + return log_msg_ret("check", ret); + + ret = bootmeth_read_bootflow(bflow->method, bflow); + if (ret) + return log_msg_ret("method", ret); + + return 0; +} + +static int system_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_6_SYSTEM; + + return 0; +} + +struct bootdev_ops system_bootdev_ops = { + .get_bootflow = system_get_bootflow, +}; + +static const struct udevice_id system_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-system" }, + { } +}; + +U_BOOT_DRIVER(system_bootdev) = { + .name = "system_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &system_bootdev_ops, + .bind = system_bootdev_bind, + .of_match = system_bootdev_ids, +}; From patchwork Wed Jan 19 01:43:08 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581616 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=C/niN/8+; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpSD3ry2z9sPC for ; Wed, 19 Jan 2022 12:47:56 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CCA078388E; Wed, 19 Jan 2022 02:45:26 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="C/niN/8+"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 829CC837CF; Wed, 19 Jan 2022 02:44:27 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x12f.google.com (mail-il1-x12f.google.com [IPv6:2607:f8b0:4864:20::12f]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 0F5FA83818 for ; Wed, 19 Jan 2022 02:44:04 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x12f.google.com with SMTP id o10so907926ilh.0 for ; Tue, 18 Jan 2022 17:44:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZDQ+oXOiyXh0/B/royaWCj+FXXBxxIroYSwI/C/Oto0=; b=C/niN/8+/ivRdFl9cdIQLbexaC+pVIpYOFmMP03CqeQoIcqBEhQNXlQEXcPBp3lgku 443E12lGAGb1bj43gnJq+DSgqtsh60pvAs9D+ZIN3ZBkgRaF+3Tvw9ZyWAcRQcLgO5V8 qmbYi4MTPPq58Tdj4rdiDFhDLHmDx7U8iN8gk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZDQ+oXOiyXh0/B/royaWCj+FXXBxxIroYSwI/C/Oto0=; b=7Gj743ceC+ZkSL1VM7k+FCGD2Rb1LEHNenjB4Ft0bwRNiXOwmWA7Uj1ldAphX4vP7Q 48MN9nVrCwej1V90RKV+unHlCh3n/f2gLhvZ8THKbQgTsuKYsI3Yh8hEOppBUKLFb0vb ydah35/BoGhMY41b64UIvG/Yl3/LUyw9KiKr855qjye37Y83nKcHWsIiOz17HE5kIVzt tnxbGTfVxFCsg9zRdXwSl/t6MK5V3XV+E+IfElEYoBejjPtRmyG+fvIJ/xW3x7GfoX/g xMkbv5EHjmqIo8/czPLWgiLdm8V+0NAdJygjGmZLsSCk6KL+PR65RkYLi3HNGCGZdZWX whtg== X-Gm-Message-State: AOAM5325MzR5R3IQ++bo72IOqHeY2dJQPIPud6b6da3snMHIE4izxv7k dML2W2vTeHBLlkLKEQURFvE8SS9YOBCmmA== X-Google-Smtp-Source: ABdhPJxZxvOuZHIU+R6QM3Cqw7VUPFOC12PJngZX7DkkyPWGL62sJBVD00IAFoF9Gr/4UpJFNp3Aog== X-Received: by 2002:a92:d68b:: with SMTP id p11mr13936825iln.222.1642556642614; Tue, 18 Jan 2022 17:44:02 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:02 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 24/31] bootstd: Add an implementation of EFI bootmgr Date: Tue, 18 Jan 2022 18:43:08 -0700 Message-Id: <20220119014315.1938157-16-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootmeth driver which handles EFI boot manager, using EFI_LOADER. In effect, this provides the same functionality as the 'bootefi bootmgr' command and shares the same code. But the interface into it is via a bootmeth, so it does not require any special scripts, etc. For now this requires the 'bootefi' command be enabled. Future work may tidy this up so that it can be used without CONFIG_CMDLINE being enabled. Signed-off-by: Simon Glass --- Changes in v3: - Add a log category boot/Makefile | 3 ++ boot/bootmeth_efi_mgr.c | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 boot/bootmeth_efi_mgr.c diff --git a/boot/Makefile b/boot/Makefile index 795665f7ce5..38b10d81f0d 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -31,6 +31,9 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o +ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL +obj-$(CONFIG_$(SPL_TPL_)CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o +endif obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o diff --git a/boot/bootmeth_efi_mgr.c b/boot/bootmeth_efi_mgr.c new file mode 100644 index 00000000000..a6914466db7 --- /dev/null +++ b/boot/bootmeth_efi_mgr.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for EFI boot manager + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include +#include + +static int efi_mgr_check(struct udevice *dev, struct bootflow_iter *iter) +{ + int ret; + + /* Must be an bootstd device */ + ret = bootflow_iter_uses_system(iter); + if (ret) + return log_msg_ret("net", ret); + + return 0; +} + +static int efi_mgr_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + /* + * Just assume there is something to boot since we don't have any way + * of knowing in advance + */ + bflow->state = BOOTFLOWST_READY; + + return 0; +} + +static int efi_mgr_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + /* Files are loaded by the 'bootefi bootmgr' command */ + + return -ENOSYS; +} + +static int efi_mgr_boot(struct udevice *dev, struct bootflow *bflow) +{ + int ret; + + /* Booting is handled by the 'bootefi bootmgr' command */ + ret = run_command("bootefi bootmgr", 0); + + return 0; +} + +static int bootmeth_efi_mgr_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = "EFI bootmgr flow"; + + return 0; +} + +static struct bootmeth_ops efi_mgr_bootmeth_ops = { + .check = efi_mgr_check, + .read_bootflow = efi_mgr_read_bootflow, + .read_file = efi_mgr_read_file, + .boot = efi_mgr_boot, +}; + +static const struct udevice_id efi_mgr_bootmeth_ids[] = { + { .compatible = "u-boot,efi-bootmgr" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_zefi_mgr) = { + .name = "bootmeth_efi_mgr", + .id = UCLASS_BOOTMETH, + .of_match = efi_mgr_bootmeth_ids, + .ops = &efi_mgr_bootmeth_ops, + .bind = bootmeth_efi_mgr_bind, +}; From patchwork Wed Jan 19 01:43:09 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581614 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=BPg5hbYc; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpRq67Cvz9sPC for ; Wed, 19 Jan 2022 12:47:35 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id E92C98388B; Wed, 19 Jan 2022 02:45:21 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="BPg5hbYc"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 54BCC83849; Wed, 19 Jan 2022 02:44:26 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x129.google.com (mail-il1-x129.google.com [IPv6:2607:f8b0:4864:20::129]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DDC0083563 for ; Wed, 19 Jan 2022 02:44:04 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x129.google.com with SMTP id h30so827492ila.12 for ; Tue, 18 Jan 2022 17:44:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XI3VtnSiLpa9mBrbMu42edHqj5i1pvwmz4Rt6tGOQ4c=; b=BPg5hbYcnTFvMN8CU+IexBfZIfmjIOQkvDaF5G64IcjXc17N23UKUMYxiN7FZEGgPA FagUz11Tv9UBmbJ7SoVeG0rJuoAmYgX1HIwkdkR6k56pLz4wJPBSsEOxnByQ3dkYIoD8 sgosSa+guxUf2spyz1Wjdmk6/E4RdCPHicmsE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XI3VtnSiLpa9mBrbMu42edHqj5i1pvwmz4Rt6tGOQ4c=; b=aRGXPXx9uRmSWGOvBmVVypbVdr7ufyBiBKQJBjbW5fVTJOVFfl5xsXI8T47P+4Ix73 UtJppTsQ1a9pticb6g4qXRUbB4lsndHrndBY20Ut/UO/OfHfARrdt6ZT+fmpPLQkNRkr Cg3dQU0rD+t6V7fkGX2Bwptl2wg/1/fN+Xk/u8HTRNiaYnsulKPMr3AtYDtQ8J8J5/Jb i1uO/+Kl5BpNv1YUSh/bo8ldfqoLlOehxCOaL3dHt6f1JlwrQts6osTYg2oxAxSG2eqp HtB5KwMvmFP6QBokc1VrdqFjQmVxnJsvV3DtltXvjHzjU19yTPQJGqcKWxbXMjyV+bvb Mfeg== X-Gm-Message-State: AOAM532VPTfbIV4gJX70mXia0wtPEy/bA3X1NwTnusYVzknTPUgvx3dY e+SzQ9SaAtxcVJrQhVPIfMxzugkBgU1S8Q== X-Google-Smtp-Source: ABdhPJzr5W6FRh1h99ee4koxx2ZMz/ktyAX5l45OOhz73psAzrH1MzIQ5nP4Ox7rPzdO5HpeXNNbmw== X-Received: by 2002:a05:6e02:16cd:: with SMTP id 13mr15936294ilx.139.1642556643511; Tue, 18 Jan 2022 17:44:03 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:03 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 25/31] bootstd: Add a sandbox bootmeth driver Date: Tue, 18 Jan 2022 18:43:09 -0700 Message-Id: <20220119014315.1938157-17-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootmeth driver for sandbox, used for testing. Signed-off-by: Simon Glass --- Changes in v3: - Add a log category boot/Kconfig | 7 +++++ boot/Makefile | 1 + boot/bootmeth_sandbox.c | 69 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 boot/bootmeth_sandbox.c diff --git a/boot/Kconfig b/boot/Kconfig index 0fee35070b0..69a3e28502e 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -359,6 +359,13 @@ config BOOTMETH_EFILOADER This provides a way to try out standard boot on an existing boot flow. +config BOOTMETH_SANDBOX + def_bool y + depends on SANDBOX + help + This is a sandbox bootmeth driver used for testing. It always returns + -ENOTSUPP when attempting to boot. + endif config LEGACY_IMAGE_FORMAT diff --git a/boot/Makefile b/boot/Makefile index 38b10d81f0d..db8cb1187ed 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL obj-$(CONFIG_$(SPL_TPL_)CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o endif diff --git a/boot/bootmeth_sandbox.c b/boot/bootmeth_sandbox.c new file mode 100644 index 00000000000..13ec5e95e64 --- /dev/null +++ b/boot/bootmeth_sandbox.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for sandbox testing + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD + +#include +#include +#include +#include +#include + +static int sandbox_check(struct udevice *dev, struct bootflow_iter *iter) +{ + return 0; +} + +static int sandbox_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + /* pretend we are ready */ + bflow->state = BOOTFLOWST_READY; + + return 0; +} + +static int sandbox_read_file(struct udevice *dev, struct bootflow *bflow, + const char *file_path, ulong addr, ulong *sizep) +{ + return -ENOSYS; +} + +static int sandbox_boot(struct udevice *dev, struct bootflow *bflow) +{ + /* always fail: see bootflow_iter_disable() */ + return -ENOTSUPP; +} + +static int sandbox_bootmeth_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = "Sandbox boot for testing"; + + return 0; +} + +static struct bootmeth_ops sandbox_bootmeth_ops = { + .check = sandbox_check, + .read_bootflow = sandbox_read_bootflow, + .read_file = sandbox_read_file, + .boot = sandbox_boot, +}; + +static const struct udevice_id sandbox_bootmeth_ids[] = { + { .compatible = "u-boot,sandbox-syslinux" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_sandbox) = { + .name = "bootmeth_sandbox", + .id = UCLASS_BOOTMETH, + .of_match = sandbox_bootmeth_ids, + .ops = &sandbox_bootmeth_ops, + .bind = sandbox_bootmeth_bind, +}; From patchwork Wed Jan 19 01:43:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581613 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=IvbG/Z1K; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpRd3sgkz9sPC for ; Wed, 19 Jan 2022 12:47:25 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id DEC5283883; Wed, 19 Jan 2022 02:45:19 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="IvbG/Z1K"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C04EC801EA; Wed, 19 Jan 2022 02:44:26 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd2d.google.com (mail-io1-xd2d.google.com [IPv6:2607:f8b0:4864:20::d2d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id C705683824 for ; Wed, 19 Jan 2022 02:44:05 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd2d.google.com with SMTP id y22so958604iof.7 for ; Tue, 18 Jan 2022 17:44:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=k+ddwhN2jxFTFnPxQwrAxkcL+DzfgS2egXqEtUirL3w=; b=IvbG/Z1KdEgK1iL/mBVMGvKkIOmiUn/duxHW++sXH5l9n8mNnxvlGRV+UHUrCbpH7K GUXt0l2o3mq/Q2QPsLaB4Lmp0yEmlf9Su8wvKS32UPh3hyj6vQ2VNkxzhhBTmKQpj/P8 ROHdGmFr4zizwl1PWkO5I5mvaf9aeQzpGq5iw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=k+ddwhN2jxFTFnPxQwrAxkcL+DzfgS2egXqEtUirL3w=; b=6cfjWic0TRls1kMmbeAAKll1bvaLL8hRdsalEu3oJFHcS3P9+jIeMhFYevLI5K2ZXV TpvVjAjeQZGaGzTGyXdHsBvNok1rV13YslUHCsx21Iq7CERLJEiR1Bv7VsZGJ/1IYZfH 9QZwyg9MblM7KKhQYDltPdkF5907ljt5aAEBWTPY5uJhQP4wFihmZUwhSpjVzK0f9PpY 3gljqyZ1xrM1/kigRESyjBw9Bo1HjwUldaGYVRG5icYpnvIo/XRbauhQ/EvkmWT+pkqK hitKkKUVvHb0pISYxAT0R2JpkWxQgLBsV5HAUDsyy+WtARUmv/RY4gz2TLU2a9yF/bch yPYA== X-Gm-Message-State: AOAM533DeebFaqgn2Aj8MQFDvA+zoqsHFf4+Jy3MVLRGslJRsewKIKHy I6HrBgnuMeXqCDYm2Qne4A9DNqJvYbOBfQ== X-Google-Smtp-Source: ABdhPJxIt7Z2oqMQayysrD+fu/CbpRwiahCxj3QjHNvi/6PQNhhYcPtsZl1l2hl4KJktah+5btY7Ow== X-Received: by 2002:a5d:9f44:: with SMTP id u4mr13600708iot.163.1642556644326; Tue, 18 Jan 2022 17:44:04 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:04 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 26/31] bootstd: Add an implementation of script boot Date: Tue, 18 Jan 2022 18:43:10 -0700 Message-Id: <20220119014315.1938157-18-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootmeth driver which handles distro boot from a disk via a U-Boot script, so we can boot a bootflow using this commonly used mechanism. This is required by Armbian, for example. Signed-off-by: Simon Glass --- Changes in v3: - Add support for script boot boot/Kconfig | 11 ++++ boot/Makefile | 1 + boot/bootmeth_script.c | 137 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 boot/bootmeth_script.c diff --git a/boot/Kconfig b/boot/Kconfig index 69a3e28502e..9cf1d013f20 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -366,6 +366,17 @@ config BOOTMETH_SANDBOX This is a sandbox bootmeth driver used for testing. It always returns -ENOTSUPP when attempting to boot. +config BOOTMETH_SCRIPT + bool "Bootdev support for U-Boot scripts" + default y if BOOTSTD_FULL + help + Enables support for booting a distro via a U-Boot script. This makes + the bootdevs look for a 'boot/boot.scr' file which can be used to + boot the distro. + + This provides a way to try out standard boot on an existing boot flow. + It is not enabled by default to save space. + endif config LEGACY_IMAGE_FORMAT diff --git a/boot/Makefile b/boot/Makefile index db8cb1187ed..9d4801e86ae 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO) += bootmeth_distro.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_DISTRO_PXE) += bootmeth_pxe.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_EFILOADER) += bootmeth_efi.o obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_SCRIPT) += bootmeth_script.o ifdef CONFIG_$(SPL_TPL_)BOOTSTD_FULL obj-$(CONFIG_$(SPL_TPL_)CMD_BOOTEFI_BOOTMGR) += bootmeth_efi_mgr.o endif diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c new file mode 100644 index 00000000000..efbf4c0312a --- /dev/null +++ b/boot/bootmeth_script.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootmethod for booting via a U-Boot script + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#define LOG_CATEGORY UCLASS_BOOTSTD +#define LOG_DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SCRIPT_FNAME1 "boot.scr.uimg" +#define SCRIPT_FNAME2 "boot.scr" + +static int script_check(struct udevice *dev, struct bootflow_iter *iter) +{ + int ret; + + /* This only works on block devices */ + ret = bootflow_iter_uses_blk_dev(iter); + if (ret) + return log_msg_ret("blk", ret); + + return 0; +} + +static int script_read_bootflow(struct udevice *dev, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + const char *const *prefixes; + struct udevice *bootstd; + const char *prefix; + int ret, i; + + ret = uclass_first_device_err(UCLASS_BOOTSTD, &bootstd); + if (ret) + return log_msg_ret("std", ret); + + /* We require a partition table */ + if (!bflow->part) + return -ENOENT; + + prefixes = bootstd_get_prefixes(bootstd); + i = 0; + do { + prefix = prefixes ? prefixes[i] : NULL; + + ret = bootmeth_try_file(bflow, desc, prefix, SCRIPT_FNAME1); + if (ret) + ret = bootmeth_try_file(bflow, desc, prefix, + SCRIPT_FNAME2); + } while (ret && prefixes && prefixes[++i]); + if (ret) + return log_msg_ret("try", ret); + + bflow->subdir = strdup(prefix ? prefix : ""); + if (!bflow->subdir) + return log_msg_ret("prefix", -ENOMEM); + + ret = bootmeth_alloc_file(bflow, 0x10000, 1); + if (ret) + return log_msg_ret("read", ret); + + return 0; +} + +static int script_boot(struct udevice *dev, struct bootflow *bflow) +{ + struct blk_desc *desc = dev_get_uclass_plat(bflow->blk); + ulong addr; + int ret; + + ret = env_set("devtype", blk_get_devtype(bflow->blk)); + if (!ret) + ret = env_set_hex("devnum", desc->devnum); + if (!ret) + ret = env_set("prefix", bflow->subdir); + if (!ret && IS_ENABLED(CONFIG_ARCH_SUNXI) && + !strcmp("mmc", blk_get_devtype(bflow->blk))) + ret = env_set_hex("mmc_bootdev", desc->devnum); + if (ret) + return log_msg_ret("env", ret); + + log_debug("devtype: %s\n", env_get("devtype")); + log_debug("devnum: %s\n", env_get("devnum")); + log_debug("prefix: %s\n", env_get("prefix")); + log_debug("mmc_bootdev: %s\n", env_get("mmc_bootdev")); + + addr = map_to_sysmem(bflow->buf); + ret = image_source_script(addr, NULL); + if (ret) + return log_msg_ret("boot", ret); + + return 0; +} + +static int script_bootmeth_bind(struct udevice *dev) +{ + struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ? + "Script boot from a block device" : "script"; + + return 0; +} + +static struct bootmeth_ops script_bootmeth_ops = { + .check = script_check, + .read_bootflow = script_read_bootflow, + .read_file = bootmeth_common_read_file, + .boot = script_boot, +}; + +static const struct udevice_id script_bootmeth_ids[] = { + { .compatible = "u-boot,script" }, + { } +}; + +U_BOOT_DRIVER(bootmeth_script) = { + .name = "bootmeth_script", + .id = UCLASS_BOOTMETH, + .of_match = script_bootmeth_ids, + .ops = &script_bootmeth_ops, + .bind = script_bootmeth_bind, +}; From patchwork Wed Jan 19 01:43:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581617 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=iJ1fKMRW; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpSQ4nxxz9sPC for ; Wed, 19 Jan 2022 12:48:06 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 325CE8389E; Wed, 19 Jan 2022 02:45:29 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="iJ1fKMRW"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id F246B837CF; Wed, 19 Jan 2022 02:44:30 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-il1-x132.google.com (mail-il1-x132.google.com [IPv6:2607:f8b0:4864:20::132]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B105A8382C for ; Wed, 19 Jan 2022 02:44:06 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x132.google.com with SMTP id r15so852050ilj.7 for ; Tue, 18 Jan 2022 17:44:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VxEXOwXtXN1ZJ6bMw72w1I4Zo/HgrmSxVU+1F9fFIDM=; b=iJ1fKMRWkBvpBVpPU9/Js28r13n2d6IOZ2MOLdzjs+TgUvQ8IHy7P8ZvQf+6/mpN9N LoR4cf61jR7gi9iNc7MZtm4gQznKKauhF0lC5GoHA+9V7E0NgLtvZgKUEMadeKr4K4eV w6IwI9uLMco/33zbbwPaQ3fvkIYddTl+kHFKY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VxEXOwXtXN1ZJ6bMw72w1I4Zo/HgrmSxVU+1F9fFIDM=; b=7GSA4F6f9QrbTH9G57wgyZHuaemkZVngLuy10l4DU7R+GZ++XZ4B9er/V/peGslWWJ 8wHHuA85lfq9P+4VgLgCVnBM6PERZrT1IQqIRjvAD5VkS/BO9X48LjBSj+ct4FEhJk8O ZafmhDyN2ber+oiVyB7LCtk3CQisq50pGRh9Krc/7MCHAoVPgNpZBzd08R8vyXLop0VZ SC57uZhStpaOwvLGFqct52DCofBjVBJ5PSgZtkTaQ8xV8z4tp9AbrZy5OpFoNS9jYgle Qr4rxjLD5dEynbaQRS3uadE2y/QafoUZm+edXRjmE1oMH78R5hHENJolQLLMMtIUkhY/ KyzQ== X-Gm-Message-State: AOAM533mHPci1wXghvz/Bglg48szTh9P7U3XT2yW0t96lksCF9IJpLmS lGy9xNPXBwhw7/g3U+5trcw5pKrqRzACwQ== X-Google-Smtp-Source: ABdhPJw6BI9vfSZV3IUfW7Eqpz4pJXi5ObB7yh5WqnIR99tM8F+MoKs4hyODcNShaS0kWii8iMYOkw== X-Received: by 2002:a05:6e02:1e07:: with SMTP id g7mr16398947ila.158.1642556645309; Tue, 18 Jan 2022 17:44:05 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:04 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass , Marek Vasut Subject: [PATCH v3 27/31] bootstd: usb: Add a bootdev driver Date: Tue, 18 Jan 2022 18:43:11 -0700 Message-Id: <20220118184259.v3.27.Ibb454281fc9a82c3ad084f0f2f876e46809eee02@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a bootdev driver for USB host. It can use the distro boot mechanism to locate a file, or any other available bootmeth. Signed-off-by: Simon Glass --- (no changes since v1) common/usb_storage.c | 12 +++++++ drivers/usb/host/Makefile | 4 +++ drivers/usb/host/usb_bootdev.c | 61 ++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 drivers/usb/host/usb_bootdev.c diff --git a/common/usb_storage.c b/common/usb_storage.c index c9e2d7343ce..24ccb21701c 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -239,6 +240,17 @@ static int usb_stor_probe_device(struct usb_device *udev) if (ret) return ret; } + + ret = bootdev_setup_sibling_blk(dev, "usb_bootdev"); + if (ret) { + int ret2; + + ret2 = device_unbind(dev); + if (ret2) + return log_msg_ret("bootdev", ret2); + return log_msg_ret("bootdev", ret); + } + } #else /* We don't have space to even probe if we hit the maximum */ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index eb6fe9f6b30..742957d199c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -8,6 +8,10 @@ obj-y += usb-uclass.o obj-$(CONFIG_SANDBOX) += usb-sandbox.o endif +ifdef CONFIG_$(SPL_TPL_)USB_STORAGE +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += usb_bootdev.o +endif + # ohci obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o obj-$(CONFIG_USB_ATMEL) += ohci-at91.o diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c new file mode 100644 index 00000000000..b85f699933d --- /dev/null +++ b/drivers/usb/host/usb_bootdev.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Bootdevice for USB + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include + +static int usb_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + struct udevice *blk; + int ret; + + ret = bootdev_get_sibling_blk(dev, &blk); + /* + * If there is no media, indicate that no more partitions should be + * checked + */ + if (ret == -EOPNOTSUPP) + ret = -ESHUTDOWN; + if (ret) + return log_msg_ret("blk", ret); + assert(blk); + ret = bootdev_find_in_blk(dev, blk, iter, bflow); + if (ret) + return log_msg_ret("find", ret); + + return 0; +} + +static int usb_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_3_SCAN_SLOW; + + return 0; +} + +struct bootdev_ops usb_bootdev_ops = { + .get_bootflow = usb_get_bootflow, +}; + +static const struct udevice_id usb_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-usb" }, + { } +}; + +U_BOOT_DRIVER(usb_bootdev) = { + .name = "usb_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &usb_bootdev_ops, + .bind = usb_bootdev_bind, + .of_match = usb_bootdev_ids, +}; From patchwork Wed Jan 19 01:43:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581620 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=IHsc4zXH; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpSz5Xtdz9sPC for ; Wed, 19 Jan 2022 12:48:35 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 0DC29838AB; Wed, 19 Jan 2022 02:45:38 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="IHsc4zXH"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4F98B837CF; Wed, 19 Jan 2022 02:44:35 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd34.google.com (mail-io1-xd34.google.com [IPv6:2607:f8b0:4864:20::d34]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3904F83831 for ; Wed, 19 Jan 2022 02:44:08 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd34.google.com with SMTP id z19so992900ioj.1 for ; Tue, 18 Jan 2022 17:44:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cpy3a1K8OFcv/4NQ77yI5vzVFJhGiDccqW4YWnJ4d1A=; b=IHsc4zXHcvkAdIBvKdqgF+SgDuVUeDyccTPW3RHCL8rTzMKOk5tgDx2ZNtUTLNcDNr ma3Zeb35xvY23Hz+A2pprCdrby3Q1OLj6TzRBg8rpz2scbMHLFZ1ABcA4+HdEP9g9mbB UXIQ5pYNgcbc2/MlkbbHFJOBrpMx6cmekxm7g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cpy3a1K8OFcv/4NQ77yI5vzVFJhGiDccqW4YWnJ4d1A=; b=cVM2fYXOP7INY7A57EFx7gH64mzSzRBp3Xb+VV8JjroVOmN8QsKhMIQ+bnvETPDXQw 0zClT4luMhvKmbldDMmcNMvr4zFfgHR6WqmcltLHxS2UDU7HTw/wn4UuDcdVNF1Cu6T+ 5ixOP5jsAom6jdLE2hOUOZr8R+NqnUCdrkEkV5vgQMVCpYp76qsVPAWqbL0SwVXYBXCm zcdaB+8kDKFZe2c1nw52ucDoDLWUReBmasOWsR9tn9uOFhmOYK/dMdeivUFt/Ji0Tq0h DFbigtsdE84L61ewxHD3y7R++K9PBC1Y8hz9z1GTOBt3zP0+mI8ZAIrhhIs+K/9QnzSR 3dvg== X-Gm-Message-State: AOAM533L6brhZkz7k5bscNtapvqpzUQ5+XJxN4KiFm8p493/XKzmrHqE dPLZkP9cA4GgdQ793I/93Rm+qDpXczkIhw== X-Google-Smtp-Source: ABdhPJy/433liVhWG03mscmF1dnccxpQh8ZE6MJ8WXBtRRm6Oz+BNJ4sKq82WfZxjKCLTcMTqudyAg== X-Received: by 2002:a5d:9681:: with SMTP id m1mr13900035ion.53.1642556646345; Tue, 18 Jan 2022 17:44:06 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:05 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 28/31] bootstd: Add tests for bootstd including all uclasses Date: Tue, 18 Jan 2022 18:43:12 -0700 Message-Id: <20220118184259.v3.28.I936bf6fe715bd1feac569478aded46ab75579148@changeid> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add a set of combined tests for the bootdev, bootflow and bootmeth commands, along with associated functionality. Expand the sandbox console-recording limit so that these can work. These tests rely on a filesystem script which is not yet added to the Python tests. It is included here as a shell script. Signed-off-by: Simon Glass --- Changes in v3: - Update bootdev_test_order() for boot_targets env var - Add tests for the "bootmeths" env var - Update tests for the new 'bootmeth order' syntax MAINTAINERS | 1 + arch/sandbox/dts/test.dts | 18 ++ configs/sandbox_defconfig | 3 +- configs/sandbox_flattree_defconfig | 3 +- include/test/suites.h | 2 + test/Makefile | 1 + test/boot/Makefile | 5 + test/boot/bootdev.c | 223 ++++++++++++++++ test/boot/bootflow.c | 398 +++++++++++++++++++++++++++++ test/boot/bootmeth.c | 122 +++++++++ test/boot/bootstd_common.c | 35 +++ test/boot/bootstd_common.h | 27 ++ test/cmd_ut.c | 7 + 13 files changed, 843 insertions(+), 2 deletions(-) create mode 100644 test/boot/Makefile create mode 100644 test/boot/bootdev.c create mode 100644 test/boot/bootflow.c create mode 100644 test/boot/bootmeth.c create mode 100644 test/boot/bootstd_common.c create mode 100644 test/boot/bootstd_common.h diff --git a/MAINTAINERS b/MAINTAINERS index fe168b51a59..8ad70d3d968 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -675,6 +675,7 @@ F: include/bootflow.h F: include/bootmeth.h F: include/bootstd.h F: net/eth_bootdevice.c +F: test/boot/ BTRFS M: Marek Behun diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 48ca3e1e472..228411f9696 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -71,6 +71,21 @@ }; }; + bootstd { + compatible = "u-boot,boot-std"; + + filename-prefixes = "/", "/boot/"; + bootdev-order = "mmc2", "mmc1"; + + syslinux { + compatible = "u-boot,distro-syslinux"; + }; + + efi { + compatible = "u-boot,distro-efi"; + }; + }; + reboot-mode0 { compatible = "reboot-mode-gpio"; gpios = <&gpio_c 0 GPIO_ACTIVE_HIGH>, <&gpio_c 1 GPIO_ACTIVE_HIGH>; @@ -891,10 +906,13 @@ non-removable; }; + /* This is used for the bootdev tests */ mmc1 { compatible = "sandbox,mmc"; + filename = "mmc1.img"; }; + /* This is used for the fastboot tests */ mmc0 { compatible = "sandbox,mmc"; }; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 4f413582fb2..5825ac1fc14 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -28,7 +28,7 @@ CONFIG_AUTOBOOT_NEVER_TIMEOUT=y CONFIG_AUTOBOOT_STOP_STR_ENABLE=y CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9" CONFIG_CONSOLE_RECORD=y -CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000 CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y @@ -118,6 +118,7 @@ CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0" CONFIG_ENV_IMPORT_FDT=y +# CONFIG_BOOTDEV_ETH is not set CONFIG_BOOTP_SEND_HOSTNAME=y CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 4d5a73fce09..817b8bb82fc 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -18,7 +18,7 @@ CONFIG_BOOTSTAGE_FDT=y CONFIG_BOOTSTAGE_STASH=y CONFIG_BOOTSTAGE_STASH_SIZE=0x4096 CONFIG_CONSOLE_RECORD=y -CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x6000 CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_MISC_INIT_F=y CONFIG_CMD_CPU=y @@ -73,6 +73,7 @@ CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0" +# CONFIG_BOOTDEV_ETH is not set CONFIG_BOOTP_SEND_HOSTNAME=y CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y diff --git a/include/test/suites.h b/include/test/suites.h index d35cd83a4eb..bf79b008c1a 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -29,6 +29,8 @@ int cmd_ut_category(const char *name, const char *prefix, int do_ut_addrmap(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_common(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); diff --git a/test/Makefile b/test/Makefile index b3b2902e2e7..abd605a4351 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_UT_TIME) += time_ut.o obj-y += ut.o ifeq ($(CONFIG_SPL_BUILD),) +obj-$(CONFIG_UNIT_TEST) += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-$(CONFIG_UNIT_TEST) += lib/ obj-y += log/ diff --git a/test/boot/Makefile b/test/boot/Makefile new file mode 100644 index 00000000000..1730792b5fa --- /dev/null +++ b/test/boot/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2021 Google LLC + +obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c new file mode 100644 index 00000000000..1c2a79fb108 --- /dev/null +++ b/test/boot/bootdev.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bootstd_common.h" + +/* Allow reseting the USB-started flag */ +extern char usb_started; + +/* Check 'bootdev list' command */ +static int bootdev_test_cmd_list(struct unit_test_state *uts) +{ + int probed; + + console_record_reset_enable(); + for (probed = 0; probed < 2; probed++) { + int probe_ch = probed ? '+' : ' '; + + ut_assertok(run_command(probed ? "bootdev list -p" : + "bootdev list", 0)); + ut_assert_nextline("Seq Probed Status Uclass Name"); + ut_assert_nextlinen("---"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 0, probe_ch, "OK", + "mmc", "mmc2.bootdev"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 1, probe_ch, "OK", + "mmc", "mmc1.bootdev"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 2, probe_ch, "OK", + "mmc", "mmc0.bootdev"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(3 bootdevs)"); + ut_assert_console_end(); + } + + return 0; +} +BOOTSTD_TEST(bootdev_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootdev select' and 'info' commands */ +static int bootdev_test_cmd_select(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + /* get access to the CLI's cur_bootdev */ + ut_assertok(bootstd_get_priv(&std)); + + console_record_reset_enable(); + ut_asserteq(1, run_command("bootdev info", 0)); + ut_assert_nextlinen("Please use"); + ut_assert_console_end(); + + /* select by sequence */ + ut_assertok(run_command("bootdev select 0", 0)); + ut_assert_console_end(); + + ut_assertok(run_command("bootdev info", 0)); + ut_assert_nextline("Name: mmc2.bootdev"); + ut_assert_nextline("Sequence: 0"); + ut_assert_nextline("Status: Probed"); + ut_assert_nextline("Uclass: mmc"); + ut_assert_nextline("Bootflows: 0 (0 valid)"); + ut_assert_console_end(); + + /* select by bootdev name */ + ut_assertok(run_command("bootdev select mmc1.bootdev", 0)); + ut_assert_console_end(); + ut_assertnonnull(std->cur_bootdev); + ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name); + + /* select by bootdev label*/ + ut_assertok(run_command("bootdev select mmc1", 0)); + ut_assert_console_end(); + ut_assertnonnull(std->cur_bootdev); + ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name); + + /* deselect */ + ut_assertok(run_command("bootdev select", 0)); + ut_assert_console_end(); + ut_assertnull(std->cur_bootdev); + + ut_asserteq(1, run_command("bootdev info", 0)); + ut_assert_nextlinen("Please use"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check bootdev labels */ +static int bootdev_test_labels(struct unit_test_state *uts) +{ + struct udevice *dev, *media; + + ut_assertok(bootdev_find_by_label("mmc2", &dev)); + ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev)); + media = dev_get_parent(dev); + ut_asserteq(UCLASS_MMC, device_get_uclass_id(media)); + ut_asserteq_str("mmc2", media->name); + + /* Check invalid uclass */ + ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev)); + + /* Check unknown sequence number */ + ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev)); + + return 0; +} +BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check bootdev ordering with the bootdev-order property */ +static int bootdev_test_order(struct unit_test_state *uts) +{ + struct bootflow_iter iter; + struct bootflow bflow; + + /* + * First try the order set by the bootdev-order property + * Like all sandbox unit tests this relies on the devicetree setting up + * the required devices: + * + * mmc0 - nothing connected + * mmc1 - connected to mmc1.img file + * mmc2 - nothing connected + */ + ut_assertok(env_set("boot_targets", NULL)); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name); + bootflow_iter_uninit(&iter); + + /* Use the environment variable to override it */ + ut_assertok(env_set("boot_targets", "mmc1 mmc2")); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name); + bootflow_iter_uninit(&iter); + + /* + * Now drop both orderings, to check the default (prioriy/sequence) + * ordering + */ + ut_assertok(env_set("boot_targets", NULL)); + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(3, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_order[2]->name); + + /* + * Check that adding aliases for the bootdevs works. We just fake it by + * setting the sequence numbers directly. + */ + iter.dev_order[0]->seq_ = 0; + iter.dev_order[1]->seq_ = 3; + iter.dev_order[2]->seq_ = 2; + bootflow_iter_uninit(&iter); + + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(3, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_order[1]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[2]->name); + bootflow_iter_uninit(&iter); + + return 0; +} +BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check bootdev ordering with the uclass priority */ +static int bootdev_test_prio(struct unit_test_state *uts) +{ + struct bootdev_uc_plat *ucp; + struct bootflow_iter iter; + struct bootflow bflow; + struct udevice *blk; + + /* Start up USB which gives us three additional bootdevs */ + usb_started = false; + ut_assertok(run_command("usb start", 0)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + /* 3 MMC and 3 USB bootdevs: MMC should come before USB */ + console_record_reset_enable(); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(6, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("usb_mass_storage.lun0.bootdev", + iter.dev_order[3]->name); + + ut_assertok(bootdev_get_sibling_blk(iter.dev_order[3], &blk)); + ut_asserteq_str("usb_mass_storage.lun0", blk->name); + + /* adjust the priority of the first USB bootdev to the highest */ + ucp = dev_get_uclass_plat(iter.dev_order[3]); + ucp->prio = 1; + + bootflow_iter_uninit(&iter); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(6, iter.num_devs); + ut_asserteq_str("usb_mass_storage.lun0.bootdev", + iter.dev_order[0]->name); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name); + + return 0; +} +BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c new file mode 100644 index 00000000000..b1287958eb5 --- /dev/null +++ b/test/boot/bootflow.c @@ -0,0 +1,398 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "bootstd_common.h" + +/* Check 'bootflow scan/list' commands */ +static int bootflow_cmd(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootdev select 1", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan' with a name / label / seq */ +static int bootflow_cmd_label(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l mmc1", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); + ut_assert_skip_to_line("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'"); + ut_assert_skip_to_line("(0 bootflows, 0 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow scan -l 0", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'"); + ut_assert_skip_to_line("(0 bootflows, 0 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan/list' commands using all bootdevs */ +static int bootflow_cmd_glob(struct unit_test_state *uts) +{ + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_nextline("Scanning for bootflows in all bootdevs"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); + ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':"); + ut_assert_nextline("No more bootdevs"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing all bootflows"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_glob, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan -e' */ +static int bootflow_cmd_scan_e(struct unit_test_state *uts) +{ + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -ale", 0)); + ut_assert_nextline("Scanning for bootflows in all bootdevs"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); + ut_assert_nextline(" 0 syslinux media mmc 0 mmc2.bootdev.whole "); + ut_assert_nextline(" ** No partition found, err=-93"); + ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole "); + ut_assert_nextline(" ** No partition found, err=-93"); + + ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); + ut_assert_nextline(" 2 syslinux media mmc 0 mmc1.bootdev.whole "); + ut_assert_nextline(" ** No partition found, err=-2"); + ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole "); + ut_assert_nextline(" ** No partition found, err=-2"); + ut_assert_nextline(" 4 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextline(" 5 efi fs mmc 1 mmc1.bootdev.part_1 efi/boot/bootsbox.efi"); + + ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':"); + ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole "); + ut_assert_nextline(" ** No partition found, err=-93"); + ut_assert_nextline("No more bootdevs"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(64 bootflows, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing all bootflows"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux media mmc 0 mmc2.bootdev.whole "); + ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole "); + ut_assert_skip_to_line(" 4 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole "); + ut_assert_nextlinen("---"); + ut_assert_nextline("(64 bootflows, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_scan_e, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow info' */ +static int bootflow_cmd_info(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootdev select 1", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow select 0", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow info", 0)); + ut_assert_nextline("Name: mmc1.bootdev.part_1"); + ut_assert_nextline("Device: mmc1.bootdev"); + ut_assert_nextline("Block dev: mmc1.blk"); + ut_assert_nextline("Method: syslinux"); + ut_assert_nextline("State: ready"); + ut_assert_nextline("Partition: 1"); + ut_assert_nextline("Subdir: (none)"); + ut_assert_nextline("Filename: /extlinux/extlinux.conf"); + ut_assert_nextlinen("Buffer: "); + ut_assert_nextline("Size: 253 (595 bytes)"); + ut_assert_nextline("Error: 0"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow info -d", 0)); + ut_assert_nextline("Name: mmc1.bootdev.part_1"); + ut_assert_skip_to_line("Error: 0"); + ut_assert_nextline("Contents:"); + ut_assert_nextline("%s", ""); + ut_assert_nextline("# extlinux.conf generated by appliance-creator"); + ut_assert_skip_to_line(" initrd /initramfs-5.3.7-301.fc31.armv7hl.img"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_info, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan -b' to boot the first available bootdev */ +static int bootflow_scan_boot(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -b", 0)); + ut_assert_nextline("** Booting bootflow 'mmc1.bootdev.part_1'"); + ut_assert_nextline("Ignoring unknown command: ui"); + + /* + * We expect it to get through to boot although sandbox always returns + * -EFAULT as it cannot actually boot the kernel + */ + ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux"); + ut_assert_nextline("Boot failed (err=-14)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_scan_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check iterating through available bootflows */ +static int bootflow_iter(struct unit_test_state *uts) +{ + struct bootflow_iter iter; + struct bootflow bflow; + + bootstd_clear_glob(); + + /* The first device is mmc2.bootdev which has no media */ + ut_asserteq(-EPROTONOSUPPORT, + bootflow_scan_first(&iter, BOOTFLOWF_ALL, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + + /* + * This shows MEDIA even though there is none, since int + * bootdev_find_in_blk() we call part_get_info() which returns + * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would + * know. + */ + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + + ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(1, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0, iter.max_part); + ut_asserteq_str("efi", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + /* The next device is mmc1.bootdev - at first we use the whole device */ + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(1, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("efi", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + /* Then more to partition 1 where we find something */ + ut_assertok(bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(1, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_READY, bflow.state); + bootflow_free(&bflow); + + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(1, iter.cur_method); + ut_asserteq(1, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("efi", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_FS, bflow.state); + bootflow_free(&bflow); + + /* Then more to partition 2 which doesn't exist */ + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(2, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + bootflow_iter_uninit(&iter); + + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_iter, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check using the system bootdev */ +static int bootflow_system(struct unit_test_state *uts) +{ + struct udevice *bootstd, *dev; + + /* Add the EFI bootmgr driver */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind_driver(bootstd, "bootmeth_efi_mgr", "bootmgr", + &dev)); + + /* Add the system bootdev that it uses */ + ut_assertok(device_bind_driver(bootstd, "system_bootdev", + "system-bootdev", &dev)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + /* We should get a single 'bootmgr' method right at the end */ + bootstd_clear_glob(); + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_skip_to_line(" 1 bootmgr ready bootstd 0 "); + ut_assert_nextline("No more bootdevs"); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_system, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check disabling a bootmethod if it requests it */ +static int bootflow_iter_disable(struct unit_test_state *uts) +{ + struct udevice *bootstd, *dev; + struct bootflow_iter iter; + struct bootflow bflow; + int i; + + /* Add the EFI bootmgr driver */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox", + &dev)); + + /* Add the system bootdev that it uses */ + ut_assertok(device_bind_driver(bootstd, "system_bootdev", + "system-bootdev", &dev)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + bootstd_clear_glob(); + ut_assertok(run_command("bootflow scan -lb", 0)); + + /* Try to boot the bootmgr flow, which will fail */ + console_record_reset_enable(); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(3, iter.num_methods); + ut_asserteq_str("sandbox", iter.method->name); + ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow)); + + ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried"); + ut_assert_console_end(); + + /* Check that the sandbox bootmeth has been removed */ + ut_asserteq(2, iter.num_methods); + for (i = 0; i < iter.num_methods; i++) + ut_assert(strcmp("sandbox", iter.method_order[i]->name)); + + return 0; +} +BOOTSTD_TEST(bootflow_iter_disable, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow boot' to boot a selected bootflow */ +static int bootflow_cmd_boot(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootdev select 1", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow select 0", 0)); + ut_assert_console_end(); + ut_asserteq(1, run_command("bootflow boot", 0)); + ut_assert_nextline("** Booting bootflow 'mmc1.bootdev.part_1'"); + ut_assert_nextline("Ignoring unknown command: ui"); + + /* + * We expect it to get through to boot although sandbox always returns + * -EFAULT as it cannot actually boot the kernel + */ + ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux"); + ut_assert_nextline("Boot failed (err=-14)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c new file mode 100644 index 00000000000..955eea2426a --- /dev/null +++ b/test/boot/bootmeth.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include "bootstd_common.h" + +/* Check 'bootmeth list' command */ +static int bootmeth_cmd_list(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 0 syslinux Syslinux boot from a block device"); + ut_assert_nextline(" 1 1 efi EFI boot from a .efi file"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootmeth_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootmeth order' command */ +static int bootmeth_cmd_order(struct unit_test_state *uts) +{ + /* Select just one bootmethod */ + console_record_reset_enable(); + ut_assertok(run_command("bootmeth order syslinux", 0)); + ut_assert_console_end(); + ut_assertnonnull(env_get("bootmeths")); + ut_asserteq_str("syslinux", env_get("bootmeths")); + + /* Only that one should be listed */ + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 0 syslinux Syslinux boot from a block device"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootmeth)"); + ut_assert_console_end(); + + /* Check the -a flag, efi should show as not in the order ("-") */ + ut_assertok(run_command("bootmeth list -a", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 0 syslinux Syslinux boot from a block device"); + ut_assert_nextline(" - 1 efi EFI boot from a .efi file"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assert_console_end(); + + /* Check the -a flag with the reverse order */ + ut_assertok(run_command("bootmeth order \"efi syslinux\"", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootmeth list -a", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 1 0 syslinux Syslinux boot from a block device"); + ut_assert_nextline(" 0 1 efi EFI boot from a .efi file"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assert_console_end(); + + /* Now reset the order to empty, which should show all of them again */ + ut_assertok(run_command("bootmeth order", 0)); + ut_assert_console_end(); + ut_assertnull(env_get("bootmeths")); + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_skip_to_line("(2 bootmeths)"); + + /* Try reverse order */ + ut_assertok(run_command("bootmeth order \"efi syslinux\"", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 1 efi EFI boot from a .efi file"); + ut_assert_nextline(" 1 0 syslinux Syslinux boot from a block device"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assertnonnull(env_get("bootmeths")); + ut_asserteq_str("efi syslinux", env_get("bootmeths")); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootmeth_cmd_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootmeths' env var */ +static int bootmeth_env(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + ut_assertok(bootstd_get_priv(&std)); + + /* Select just one bootmethod */ + console_record_reset_enable(); + ut_assertok(env_set("bootmeths", "syslinux")); + ut_asserteq(1, std->bootmeth_count); + + /* Select an invalid bootmethod */ + ut_asserteq(1, run_command("setenv bootmeths fred", 0)); + ut_assert_nextline("Unknown bootmeth 'fred'"); + ut_assert_nextlinen("## Error inserting"); + ut_assert_console_end(); + + ut_assertok(env_set("bootmeths", "efi syslinux")); + ut_asserteq(2, std->bootmeth_count); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootmeth_env, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/bootstd_common.c b/test/boot/bootstd_common.c new file mode 100644 index 00000000000..05347d87106 --- /dev/null +++ b/test/boot/bootstd_common.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include "bootstd_common.h" + +int bootstd_test_drop_bootdev_order(struct unit_test_state *uts) +{ + struct bootstd_priv *priv; + struct udevice *bootstd; + + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + priv = dev_get_priv(bootstd); + priv->bootdev_order = NULL; + + return 0; +} + +int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(bootstd_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(bootstd_test); + + return cmd_ut_category("bootstd", "bootstd_test_", + tests, n_ents, argc, argv); +} diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h new file mode 100644 index 00000000000..676ef0a57f9 --- /dev/null +++ b/test/boot/bootstd_common.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Common header file for bootdev, bootflow, bootmeth tests + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __bootstd_common_h +#define __bootstd_common_h + +/* Declare a new bootdev test */ +#define BOOTSTD_TEST(_name, _flags) \ + UNIT_TEST(_name, _flags, bootstd_test) + +struct unit_test_state; + +/** + * bootstd_test_drop_bootdev_order() - Remove the existing boot order + * + * Drop the boot order so that all bootdevs are used in their alias order + * + * @uts: Unit test state to use for ut_assert...() functions + */ +int bootstd_test_drop_bootdev_order(struct unit_test_state *uts); + +#endif diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 90b260f72d6..67a13ee32b8 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -28,6 +28,10 @@ int cmd_ut_category(const char *name, const char *prefix, static struct cmd_tbl cmd_ut_sub[] = { U_BOOT_CMD_MKENT(all, CONFIG_SYS_MAXARGS, 1, do_ut_all, "", ""), +#ifdef CONFIG_BOOTSTD + U_BOOT_CMD_MKENT(bootstd, CONFIG_SYS_MAXARGS, 1, do_ut_bootstd, + "", ""), +#endif U_BOOT_CMD_MKENT(common, CONFIG_SYS_MAXARGS, 1, do_ut_common, "", ""), #if defined(CONFIG_UT_DM) U_BOOT_CMD_MKENT(dm, CONFIG_SYS_MAXARGS, 1, do_ut_dm, "", ""), @@ -115,6 +119,9 @@ static char ut_help_text[] = "ut bloblist - Test bloblist implementation\n" "ut compression - Test compressors and bootm decompression\n" #endif +#ifdef CONFIG_BOOTSTD + "ut bootstd - Test standard boot implementation\n" +#endif #ifdef CONFIG_UT_DM "ut dm [test-name]\n" #endif From patchwork Wed Jan 19 01:43:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581618 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=RG22uv0n; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpSc0KC7z9sPC for ; Wed, 19 Jan 2022 12:48:15 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id AF964838A6; Wed, 19 Jan 2022 02:45:31 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="RG22uv0n"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BD1B483813; Wed, 19 Jan 2022 02:44:32 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd36.google.com (mail-io1-xd36.google.com [IPv6:2607:f8b0:4864:20::d36]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 2994383837 for ; Wed, 19 Jan 2022 02:44:09 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd36.google.com with SMTP id v1so935909ioj.10 for ; Tue, 18 Jan 2022 17:44:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Ir4NsB6khTD+9fLOQh8UhR+exhuRjKmxsxeh+Z9Uc/U=; b=RG22uv0ndLHMbs/JHmuxasIKIJIwu5WkHMGD5jUx+DlmpgMdGuVIxS0vqojRIHI5TK YxtF+0V8W7CAa9VILJXnoOWLVi3B+H53Q0dqZOIWnNcdMXeKp1UfUCEj92wiHAUH0e7j Ri9l/09Hcluamj4ximHtNfg5VqNu/AQfZpwm4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Ir4NsB6khTD+9fLOQh8UhR+exhuRjKmxsxeh+Z9Uc/U=; b=tHHJscUmPsX2o2SlweuL9XtA8MnthU5myxwIyLYmFp/ko61e081Z6Fv0xkH+TBCXXM HCzK5vHVACbpWHhdu4CTMC4d+XjnosSD0ohs64IMLlFh1BkuzvREhcp3OMsajF2DLN97 Etbyu+vrnN67BZwpixmlpWqzw8tmOaY5+m83GDcesoeiAueNChkl96Eys/6QPNC7fXyf 9QNGIpRELNPliqcoir65qWmPC9t2g4iWASE+1REt2ke9VR8nw+0iwg4rG0901JtMHI24 VpwdxnIOgIhz2fqbBQ91rnn/FuTfrDIZUpfL+9m6FWz948dtQ2myvSdwBg+ZIqfYV8n3 NxbA== X-Gm-Message-State: AOAM531EYWV/haIgMo5SJRe3k7GHvFkhwa72fdWrQOKjBY1dq1W0ECkL wzOn0ng8Lb/I3oxkk0kJ3a1fZv+mnGjzQw== X-Google-Smtp-Source: ABdhPJx2SLaeTfHNG68iQ79OCTuy+uF4JRgAuy/s5rZO6kO9+9dNf34pMg35zQKYeXKyNfj5Rn/eFw== X-Received: by 2002:a5e:9613:: with SMTP id a19mr9867841ioq.159.1642556647640; Tue, 18 Jan 2022 17:44:07 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:07 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 29/31] bootstd: Add setup for the bootflow tests Date: Tue, 18 Jan 2022 18:43:13 -0700 Message-Id: <20220119014315.1938157-19-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean We need to create a disk image with a partition table and a DOS-format filesystem containing a few files. Provide a fallback binary for CI since it does not seem able to detect the loopback partitions. Add this to a dm_init test so that it happens when needed. Signed-off-by: Simon Glass --- Changes in v3: - Update test condition to use CMD_BOOTFLOW test/py/tests/bootstd/mmc1.img.xz | Bin 0 -> 4448 bytes test/py/tests/test_ut.py | 103 ++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 test/py/tests/bootstd/mmc1.img.xz diff --git a/test/py/tests/bootstd/mmc1.img.xz b/test/py/tests/bootstd/mmc1.img.xz new file mode 100644 index 0000000000000000000000000000000000000000..4e7f39b830eb4bddcb9ff6df39e89f130b5706b9 GIT binary patch literal 4448 zcmeI0c{JOJ7RP@`Y(-R5?X`}rGNKxz9Y1f(ncsMm4@s?)THBgy{6U{9Xf zjhWyTLq>&G;svF#Bje#;bOmkhhE$q9$<~I^9H$OcZc$TV zMm~rDFT{WWjO6gcMYYHc+6;^JG8pkme*14Ce5le4a3Xkbt70^O7K>VGXX_ybx)*eD zw6^43jCQ-EnZSx&neK#B$O{UBSSV)XEs1b#mSt8v(^ROEPcQ~?h~&+LRdcB!|Pg*6V;d|HfzwOc`HZ0F{bOiS(PfoQ$+96!SnBncAog%~~q+ z4pv?MwLy<7e_muzu9NC3mOJG=EjfgHZ^&EDT#iavdv!R~fYhpQHts|&4o{9py`Y_% z31`~6QY-sMx{bA(spJ|Hg0FssAbqKREdQ!nnHCFF(SgD|u*oO@)b?YHOfi`nb2iqE zo#dvbuHH>ts%D|qG|pzTpV-7MtB>3Vq!+w8Zx#o9YoLQmNagFld# zP(41!ib&tauzdKXL3Wdvj^TFM^wfBX8wSVK3`s(RwOWClx9g+fhLgZM^F}%6wv}i0 z_2T0?&*=|tVg38)KCU;((P$nEiz00YJ12kgQ7#!ImFl3}h1PaL*2_u7xNC-Xp8x}W zrZ#;_6cWGawviOU!FpMa4xBc8BKBpF@HY;3jrzikAK)rrz7cK3SIdLk);?Swpj+u! zauVI(Z3zMX;2AoFtX#dnXQY97ZpySTjNrJ{%!f$Y`gK%8nEg4geO3mc z-OP*|Ch_5AWY9NP%p&~M>ZAJ??-^R7P2+1Hb2rgsO2X$eMJ<7l))#5bjryO*Dqa)` z%;XHzXL<#CLI9X5|4{QLx2n8#cjne^EA6#n{fUKE*apICl#Rr5`b4w-6|DH9x(%>u zAblDl+7gOW;#{pAugK1-4d((cKffC%}1y~xAgK-kIY#om$h-hU6uL%6{?p4=faq|cA$OJ7|(inY7C)NOBNMaX+?yr2|aOhe9tKnj)<)sFT!^mcwJjoRb=G@*C$wRry zPTo*uOsdFL<_`GKQyEJE$O5|axr@ik&j;SomgcM_v6f@QoLawwxx>yHJePg!~N z!c}v~e55d};P9~2ji z?smHa;#j<|fU46!w;JJ1IC}O?Fiq)m)lfbK=CSvquxAa|fn+FXteGTw`$1R2xqL53 z+Rq|Rc3KPV#k%(QqK*DO9AuCG9)ulipIS+(&QWE;*777sZ;1-R&S=7_hqYtJ>Yt>x zRotR}1x$Vx6<|HkrtGAnCK4`M(3A?t`n@QVbzN5+h#$$$O^Q~|*ii`H7a_Cfn&+NO z){dt`y5(&cyBP>LxU_EbL6@I7if1I_d_}d}Uo+;vP2meZmVEF3+S&?&e02uw_ZaxU zc6A2q_a>e*VE<)AJOg$H?0@1nXBu{3A05H(`mV)`mrvw0O h4`jqrLheQZEG;rP9FCigsLUjGdmgd=vj{>v{RVxmraJ%t literal 0 HcmV?d00001 diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 01c2b3ffa12..35fb393c1ff 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -1,9 +1,102 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +import gzip +import os import os.path import pytest +import u_boot_utils + +def mkdir_cond(dirname): + """Create a directory if it doesn't already exist + + Args: + dirname: Name of directory to create + """ + if not os.path.exists(dirname): + os.mkdir(dirname) + +def setup_bootflow_image(u_boot_console): + """Create a 20MB disk image with a single FAT partition""" + cons = u_boot_console + fname = os.path.join(cons.config.source_dir, 'mmc1.img') + mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') + mkdir_cond(mnt) + + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) + u_boot_utils.run_and_log(cons, 'sudo sfdisk %s' % fname, + stdin=b'type=c') + + loop = None + mounted = False + complete = False + try: + out = u_boot_utils.run_and_log(cons, + 'sudo losetup --show -f -P %s' % fname) + loop = out.strip() + fatpart = '%sp1' % loop + u_boot_utils.run_and_log(cons, 'sudo mkfs.vfat %s' % fatpart) + u_boot_utils.run_and_log( + cons, 'sudo mount -o loop %s %s -o uid=%d,gid=%d' % + (fatpart, mnt, os.getuid(), os.getgid())) + mounted = True + + vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl' + initrd = 'initramfs-5.3.7-301.fc31.armv7hl.img' + dtbdir = 'dtb-5.3.7-301.fc31.armv7hl' + script = '''# extlinux.conf generated by appliance-creator +ui menu.c32 +menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. +menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. +menu hidden +timeout 20 +totaltimeout 600 + +label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + kernel /%s + append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + fdtdir /%s/ + initrd /%s''' % (vmlinux, dtbdir, initrd) + ext = os.path.join(mnt, 'extlinux') + mkdir_cond(ext) + + with open(os.path.join(ext, 'extlinux.conf'), 'w') as fd: + print(script, file=fd) + + inf = os.path.join(cons.config.persistent_data_dir, 'inf') + with open(inf, 'wb') as fd: + fd.write(gzip.compress(b'vmlinux')) + u_boot_utils.run_and_log(cons, 'mkimage -f auto -d %s %s' % + (inf, os.path.join(mnt, vmlinux))) + + with open(os.path.join(mnt, initrd), 'w') as fd: + print('initrd', file=fd) + + mkdir_cond(os.path.join(mnt, dtbdir)) + + dtb_file = os.path.join(mnt, '%s/sandbox.dtb' % dtbdir) + u_boot_utils.run_and_log( + cons, 'dtc -o %s' % dtb_file, stdin=b'/dts-v1/; / {};') + complete = True + except ValueError as exc: + print('Falled to create image, failing back to prepared copy: %s', + str(exc)) + finally: + if mounted: + u_boot_utils.run_and_log(cons, 'sudo umount %s' % mnt) + if loop: + u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop) + + if not complete: + # Use a prepared image since we cannot create one + infname = os.path.join(cons.config.source_dir, + 'test/py/tests/bootstd/mmc1.img.xz') + u_boot_utils.run_and_log( + cons, + ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)]) + + @pytest.mark.buildconfigspec('ut_dm') def test_ut_dm_init(u_boot_console): """Initialize data for ut dm tests.""" @@ -21,6 +114,16 @@ def test_ut_dm_init(u_boot_console): with open(fn, 'wb') as fh: fh.write(data) +@pytest.mark.buildconfigspec('cmd_bootflow') +def test_ut_dm_init_bootstd(u_boot_console): + """Initialise data for bootflow tests""" + + setup_bootflow_image(u_boot_console) + + # Restart so that the new mmc1.img is picked up + u_boot_console.restart_uboot() + + def test_ut(u_boot_console, ut_subtest): """Execute a "ut" subtest. From patchwork Wed Jan 19 01:43:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581621 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=IOeDDMkf; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpT96XLbz9sPC for ; Wed, 19 Jan 2022 12:48:45 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 818A583877; Wed, 19 Jan 2022 02:45:40 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="IOeDDMkf"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 664E983839; Wed, 19 Jan 2022 02:44:45 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x129.google.com (mail-il1-x129.google.com [IPv6:2607:f8b0:4864:20::129]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8DF9683841 for ; Wed, 19 Jan 2022 02:44:11 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x129.google.com with SMTP id v17so868080ilg.4 for ; Tue, 18 Jan 2022 17:44:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9xxsJRiXDxqCpVJ3VVwDElDnJpQL9tTyaO4LDnN5E1A=; b=IOeDDMkff4yGSIuZCN08/Z/TvziS9SfvR3U3mps9USYmHktHktiCzLCNQ40UBV5209 TI5mkdwINGPh+s47h57lahWpYO3S/4beQX3Q7k7uJVejGGtYkqbLtTpuDaSJrIo1SyEG enPHN/tdwgm0AIJgHP8tPFT2zUzZIsP78nvZ0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9xxsJRiXDxqCpVJ3VVwDElDnJpQL9tTyaO4LDnN5E1A=; b=v+uXddAkJrHlBgzvRztSojLLglPDxxlZQ48txxiYPvfQGc0cq8o7mMYZUW8Hf4eE9r Q3E1SjwVMLl/exNIhOX0JLTH4Lp0KaCaoEFjri/qGPsAf2NfnqV6bQU42cLbUkwBIoeF O/BFPdhq5rotuBpWv5MwalUuo8z/0F82EthA6MnfNOENqLVZ8pQnGYBtlKh25MqAykZC K+VZ1KshYEMiH5x9ouHAc+CrWeO0eURgqQMTGZU7ymdGGWJ1PoB0aZyS9HcqLay/7ef2 5n4scepGoW5eTWdEXNE4osiYKLrg7tit/cR0inO3HpYPu7xVWyDolTMZ+DHgwGSVTLEx VX/Q== X-Gm-Message-State: AOAM530GeH6ih69cFJYsQK0j++aWmHvOkVxAu2lB659ih2X8a0RMCG11 EgzJUSUpDpUhQ+j4Lhbbiq/nG2aEU4A0iQ== X-Google-Smtp-Source: ABdhPJwRCeRRO1GJpBFmdCjxbYKo2XLyFe6wHOef5htQ5epiy0FSC6/+gxd6P/dema+l3kboZ+neyA== X-Received: by 2002:a05:6e02:188a:: with SMTP id o10mr9816100ilu.81.1642556648654; Tue, 18 Jan 2022 17:44:08 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:08 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 30/31] bootstd: doc: Add documentation Date: Tue, 18 Jan 2022 18:43:14 -0700 Message-Id: <20220119014315.1938157-20-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add documentation for this feature, including the commands and full devicetree bindings. Signed-off-by: Simon Glass --- Changes in v3: - Update docs for "bootmeths" and "boot_targets" env vars MAINTAINERS | 4 + doc/develop/bootstd.rst | 638 ++++++++++++++++++++++++++ doc/develop/distro.rst | 3 + doc/develop/index.rst | 1 + doc/device-tree-bindings/bootdev.txt | 18 + doc/device-tree-bindings/bootmeth.txt | 31 ++ doc/device-tree-bindings/bootstd.txt | 8 + doc/usage/bootdev.rst | 135 ++++++ doc/usage/bootflow.rst | 427 +++++++++++++++++ doc/usage/bootmeth.rst | 108 +++++ doc/usage/index.rst | 3 + 11 files changed, 1376 insertions(+) create mode 100644 doc/develop/bootstd.rst create mode 100644 doc/device-tree-bindings/bootmeth.txt create mode 100644 doc/usage/bootdev.rst create mode 100644 doc/usage/bootflow.rst create mode 100644 doc/usage/bootmeth.rst diff --git a/MAINTAINERS b/MAINTAINERS index 8ad70d3d968..c2af8ada3c9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -669,6 +669,10 @@ F: boot/bootmeth*.c F: boot/bootstd.c F: cmd/bootdev.c F: cmd/bootflow.c +F: doc/develop/bootstd.rst +F: doc/usage/bootdev.rst +F: doc/usage/bootflow.rst +F: doc/usage/bootmeth.rst F: drivers/mmc/mmc_bootdev.c F: include/bootdev.h F: include/bootflow.h diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst new file mode 100644 index 00000000000..1b65a806efb --- /dev/null +++ b/doc/develop/bootstd.rst @@ -0,0 +1,638 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +U-Boot Standard Boot +==================== + +Introduction +------------ + +Standard boot provides a built-in way for U-Boot to automatically boot +an Operating System without custom scripting and other customisation. It +introduces the following concepts: + + - bootdev - a device which can hold or access a distro (e.g. MMC, Ethernet) + - bootmeth - a method to scan a bootdev to find bootflows (e.g. distro boot) + - bootflow - a description of how to boot (provided by the distro) + +For Linux, the distro (Linux distribution, e.g. Debian, Fedora) is responsible +for creating a bootflow for each kernel combination that it wants to offer. +These bootflows are stored on media so they can be discovered by U-Boot. This +feature is typically called `distro boot` (see :doc:`distro`) because it is +a way for distributions to boot on any hardware. + +Traditionally U-Boot has relied on scripts to implement this feature. See +disto_boodcmd_ for details. This is done because U-Boot has no native support +for scanning devices. While the scripts work remarkably well, they can be hard +to understand and extend, and the feature does not include tests. They are also +making it difficult to move away from ad-hoc CONFIGs, since they are implemented +using the environment and a lot of #defines. + +Standard boot is a generalisation of distro boot. It provides a more built-in +way to boot with U-Boot. The feature is extensible to different Operating +Systems (such as Chromium OS) and devices (beyond just block and network +devices). It supports EFI boot and EFI bootmgr too. + + +Bootflow +-------- + +A bootflow is a file that describes how to boot a distro. Conceptually there can +be different formats for that file but at present U-Boot only supports the +BootLoaderSpec_ format. which looks something like this:: + + menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. + menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. + menu hidden + + label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + kernel /vmlinuz-5.3.7-301.fc31.armv7hl + append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + fdtdir /dtb-5.3.7-301.fc31.armv7hl/ + initrd /initramfs-5.3.7-301.fc31.armv7hl.img + +As you can see it specifies a kernel, a ramdisk (initrd) and a directory from +which to load devicetree files. The details are described in disto_boodcmd_. + +The bootflow is provided by the distro. It is not part of U-Boot. U-Boot's job +is simply to interpret the file and carry out the instructions. This allows +distros to boot on essentially any device supported by U-Boot. + +Typically the first available bootflow is selected and booted. If that fails, +then the next one is tried. + + +Bootdev +------- + +Where does U-Boot find the media that holds the operating systems? That is the +job of bootdev. A bootdev is simply a layer on top of a media device (such as +MMC, NVMe). The bootdev accesses the device, including partitions and +filesystems that might contain things related to an operating system. + +For example, an MMC bootdev provides access to the individual partitions on the +MMC device. It scans through these to find filesystems, then provides a list of +these for consideration. + + +Bootmeth +-------- + +Once the list of filesystems is provided, how does U-Boot find the bootflow +files in these filesystems. That is the job of bootmeth. Each boot method has +its own way of doing this. + +For example, the distro bootmeth simply looks through the provided filesystem +for a file called `extlinux/extlinux.conf`. This files constitutes a bootflow. +If the distro bootmeth is used on multiple partitions it may produce multiple +bootflows. + +Note: it is possible to have a bootmeth that uses a partition or a whole device +directly, but it is more common to use a filesystem. + + +Boot process +------------ + +U-Boot tries to use the 'lazy init' approach whereever possible and distro boot +is no exception. The algorithm is:: + + while (get next bootdev) + while (get next bootmeth) + while (get next bootflow) + try to boot it + +So U-Boot works its way through the bootdevs, trying each bootmeth in turn to +obtain bootflows, until it either boots or exhausts the available options. + +Instead of 500 lines of #defines and a 4KB boot script, all that is needed is +the following command:: + + bootflow scan -lb + +which scans for available bootflows, optionally listing each find it finds (-l) +and trying to boot it (-b). + + +Controlling ordering +-------------------- + +Several options are available to control the ordering of boot scanning: + + +boot_targets +~~~~~~~~~~~~ + +This environment variable can be used to control the list of bootdevs searched +and their ordering, for example:: + + setenv boot_targets "mmc0 mmc1 usb pxe" + +Entries may be removed or re-ordered in this list to affect the boot order. If +the variable is empty, the default ordering is used, based on the priority of +bootdevs and their sequence numbers. + + +bootmeths +~~~~~~~~~ + +This environment variable can be used to control the list of bootmeths used and +their ordering for example:: + + setenv bootmeths "syslinux efi" + +Entries may be removed or re-ordered in this list to affect the order the +bootmeths are tried on each bootdev. If the variable is empty, the default +ordering is used, based on the bootmeth sequence numbers, which can be +controlled by aliases. + +The :ref:`usage/bootmeth:bootmeth command` (`bootmeth order`) operates in the +same way as setting this variable. + + +Bootdev uclass +-------------- + +The bootdev uclass provides an simple API call to obtain a bootflows from a +device:: + + int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow); + +This takes a iterator which indicates the bootdev, partition and bootmeth to +use. It returns a bootflow. This is the core of the bootdev implementation. The +bootdev drivers that implement this differ depending on the media they are +reading from, but each is responsible for returning a valid bootflow if +available. + +A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this +function for each media device uclass, in a few lines of code. + + +Bootdev drivers +--------------- + +A bootdev driver is typically fairly simple. Here is one for mmc:: + + static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) + { + struct udevice *mmc_dev = dev_get_parent(dev); + struct udevice *blk; + int ret; + + ret = mmc_get_blk(mmc_dev, &blk); + /* + * If there is no media, indicate that no more partitions should be + * checked + */ + if (ret == -EOPNOTSUPP) + ret = -ESHUTDOWN; + if (ret) + return log_msg_ret("blk", ret); + assert(blk); + ret = bootdev_find_in_blk(dev, blk, iter, bflow); + if (ret) + return log_msg_ret("find", ret); + + return 0; + } + + static int mmc_bootdev_bind(struct udevice *dev) + { + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_0_INTERNAL_FAST; + + return 0; + } + + struct bootdev_ops mmc_bootdev_ops = { + .get_bootflow = mmc_get_bootflow, + }; + + static const struct udevice_id mmc_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-mmc" }, + { } + }; + + U_BOOT_DRIVER(mmc_bootdev) = { + .name = "mmc_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &mmc_bootdev_ops, + .bind = mmc_bootdev_bind, + .of_match = mmc_bootdev_ids, + }; + +The implementation of the `get_bootflow()` method is simply to obtain the +block device and call a bootdev helper function to do the rest. The +implementation of `bootdev_find_in_blk()` checks the partition table, and +attempts to read a file from a filesystem on the partition number given by the +`@iter->part` parameter. + +Each bootdev has a priority, which indicates the order in which it is used. +Faster bootdevs are used first, since they are more likely to be able to boot +the device quickly. + + +Device hierarchy +---------------- + +A bootdev device is a child of the media device. In this example, you can see +that the bootdev is a sibling of the block device and both are children of +media device:: + + mmc 0 [ + ] bcm2835-sdhost | |-- mmc@7e202000 + blk 0 [ + ] mmc_blk | | |-- mmc@7e202000.blk + bootdev 0 [ ] mmc_bootdev | | `-- mmc@7e202000.bootdev + mmc 1 [ + ] sdhci-bcm2835 | |-- sdhci@7e300000 + blk 1 [ ] mmc_blk | | |-- sdhci@7e300000.blk + bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev + +The bootdev device is typically created automatically in the media uclass' +`post_bind()` method by calling `bootdev_setup_for_dev()`. The code typically +something like this:: + + ret = bootdev_setup_for_dev(dev, "eth_bootdev"); + if (ret) + return log_msg_ret("bootdev", ret); + +Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev` +is the ethernet device. This function is safe to call even if standard boot is +not enabled, since it does nothing in that case. It can be added to all uclasses +which implement suitable media. + + +The bootstd device +------------------ + +Standard boot requires a single instance of the bootstd device to make things +work. This includes global information about the state of standard boot. See +`struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`. + +Within the devicetree, if you add bootmeth devices or a system bootdev, they +should be children of the bootstd device. See `arch/sandbox/dts/test.dts` for +an example of this. + + +The system bootdev +------------------ + +Some bootmeths don't operate on individual bootdevs, but on the whole system. +For example, the EFI boot manager does its own device scanning and does not +make use of the bootdev devices. Such bootmeths can make use of the system +bootdev, typically considered last, after everything else has been tried. + + +.. _`Automatic Devices`: + +Automatic devices +----------------- + +It is possible to define all the required devices in the devicetree manually, +but it is not necessary. The bootstd uclass includes a `dm_scan_other()` +function which creates the bootstd device if not found. If no bootmeth devices +are found at all, it creates one for each available bootmeth driver as well as a +system bootdev. + +If your devicetree has any bootmeth device it must have all of them that you +want to use, as well as the system bootdev if needed, since no bootmeth devices +will be created automatically in that case. + + +Using devicetree +---------------- + +If a bootdev is complicated or needs configuration information, it can be +added to the devicetree as a child of the media device. For example, imagine a +bootdev which reads a bootflow from SPI flash. The devicetree fragment might +look like this:: + + spi@0 { + flash@0 { + reg = <0>; + compatible = "spansion,m25p16", "jedec,spi-nor"; + spi-max-frequency = <40000000>; + + bootdev { + compatible = "u-boot,sf-bootdev"; + offset = <0x2000>; + size = <0x1000>; + }; + }; + }; + +The `sf-bootdev` driver can implement a way to read from the SPI flash, using +the offset and size provided, and return that bootflow file back to the caller. +When distro boot wants to read the kernel it calls disto_getfile() which must +provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_ +for more details. + +Of course this is all internal to U-Boot. All the distro sees is another way +to boot. + + +Configuration +------------- + +Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG +option also. For example, `CONFIG_BOOTMETH_DISTRO` enables support for distro +boot from a disk. + + +Available bootmeth drivers +-------------------------- + +Bootmeth drivers are provided for: + + - distro boot from a disk (syslinux) + - distro boot from a network (PXE) + - EFI boot using bootefi + - EFI boot using boot manager + + +Command interface +----------------- + +Three commands are available: + +`bootdev` + Allows listing of available bootdevs, selecting a particular one and + getting information about it. See :doc:`../usage/bootdev` + +`bootflow` + Allows scanning one or more bootdevs for bootflows, listing available + bootflows, selecting one, obtaining information about it and booting it. + See :doc:`../usage/bootflow` + +`bootmeth` + Allow listing of available bootmethds and setting the order in which they + are tried. See :doc:`../usage/bootmeth` + +.. _BootflowStates: + +Bootflow states +--------------- + +Here is a list of states that a bootflow can be in: + +======= ======================================================================= +State Meaning +======= ======================================================================= +base Starting-out state, indicates that no media/partition was found. For an + SD card socket it may indicate that the card is not inserted. +media Media was found (e.g. SD card is inserted) but no partition information + was found. It might lack a partition table or have a read error. +part Partition was found but a filesystem could not be read. This could be + because the partition does not hold a filesystem or the filesystem is + very corrupted. +fs Filesystem was found but the file could not be read. It could be + missing or in the wrong subdirectory. +file File was found and its size detected, but it could not be read. This + could indicate filesystem corruption. +ready File was loaded and is ready for use. In this state the bootflow is + ready to be booted. +======= ======================================================================= + + +Theory of operation +------------------- + +This describes how standard boot progresses through to booting an operating +system. + +To start. all the necessary devices must be bound, including bootstd, which +provides the top-level `struct bootstd_priv` containing optional configuration +information. The bootstd device is also holds the various lists used while +scanning. This step is normally handled automatically by driver model, as +described in `Automatic Devices`_. + +Bootdevs are also required, to provide access to the media to use. These are not +useful by themselves: bootmeths are needed to provide the means of scanning +those bootdevs. So, all up, we need a single bootstd device, one or more bootdev +devices and one or more bootmeth devices. + +Once these are ready, typically a `bootflow scan` command is issued. This kicks +of the iteration process, which involves looking through the bootdevs and their +partitions one by one to find bootflows. + +Iteration is kicked off using `bootflow_scan_first()`, which calls +`bootflow_scan_bootdev()`. + +The iterator is set up with `bootflow_iter_init()`. This simply creates an +empty one with the given flags. Flags are used to control whether each +iteration is displayed, whether to return iterations even if they did not result +in a valid bootflow, whether to iterate through just a single bootdev, etc. + +Then the ordering of bootdevs is determined, by `bootdev_setup_iter_order()`. By +default, the bootdevs are used in the order specified by the `boot_targets` +environment variable (e.g. "mmc2 mmc0 usb"). If that is missing then their +sequence order is used, as determined by the `/aliases` node, or failing that +their order in the devicetree. For BOOTSTD_FULL, if there is a `bootdev-order` +property in the bootstd node, then this is used as a final fallback. In any +case, the iterator ends up with a `dev_order` array containing the bootdevs that +are going to be used, with `num_devs` set to the number of bootdevs and +`cur_dev` starting at 0. + +Next, the ordering of bootdevs is determined, by `bootmeth_setup_iter_order()`. +By default the ordering is again by sequence number, i.e. the `/aliases` node, +or failing that the order in the devicetree. But the `bootmeth order` command +or `bootmeths` environment variable can be used to set up an ordering. If that +has been done, the ordering is in `struct bootstd_priv`, so that ordering is +simply copied into the iterator. Either way, the `method_order` array it set up, +along with `num_methods`. Then `cur_method` is set to 0. + +At this point the iterator is ready to use, with the first bootdev and bootmeth +selected. All the other fields are 0. This means that the current partition is +0, which is taken to mean the whole device, since partition numbers start at 1. +It also means that `max_part` is 0, i.e. the maximum partition number we know +about is 0, meaning that, as far as we know, there is no partition table on this +bootdev. + +With the iterator ready, `bootflow_scan_bootdev()` checks whether the current +settings produce a valid bootflow. This is handled by `bootflow_check()`, which +either returns 0 (if it got something) or an error if not (more on that later). +If the `BOOTFLOWF_ALL` iterator flag is set, even errors are returned as +incomplete bootflows, but normally an error results in moving onto the next +iteration. + +The `bootflow_scan_next()` function handles moving onto the next iteration and +checking it. In fact it sits in a loop doing that repeatedly until it finds +something it wants to return. + +The actual 'moving on' part is implemented in `iter_incr()`. This is a very +simple function. It increments the first counter. If that hits its maximum, it +sets it to zero and increments the second counter. You can think of all the +counters together as a number with three digits which increment in order, with +the least-sigificant digit on the right, counting like this: + + ======== ======= ======= + bootdev part method + ======== ======= ======= + 0 0 0 + 0 0 1 + 0 0 2 + 0 1 0 + 0 1 1 + 0 1 1 + 1 0 0 + 1 0 1 + ======== ======= ======= + +The maximum value for `method` is `num_methods - 1` so when it exceeds that, it +goes back to 0 and the next `part` is considered. The maximum value for that is +`max_part`, which is initially zero for all bootdevs. If we find a partition +table on that bootdev, `max_part` can be updated during the iteration to a +higher value - see `bootdev_find_in_blk()` for that, described later. If that +exceeds its maximum, then the next bootdev is used. In this way, iter_incr() +works its way through all possibilities, moving forward one each time it is +called. + +There is no expectation that iteration will actually finish. Quite often a +valid bootflow is found early on. With `bootflow scan -b`, that causes the +bootflow to be immediately booted. Assuming it is successful, the iteration never +completes. + +Also note that the iterator hold the **current** combination being considered. +So when `iter_incr()` is called, it increments to the next one and returns it, +the new **current** combination. + +Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has +thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error, +it indicates to the iterator what it should do when called. It can force moving +to the next partition, or bootdev, for example. The special values +`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees +`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev. +When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do +so it should immediately return. The caller of `iter_incr()` is responsible for +updating the `err` field, based on the return value it sees. + +The above describes the iteration process at a high level. It is basically a +very simple increment function with a checker called `bootflow_check()` that +checks the result of each iteration generated, to determine whether it can +produce a bootflow. + +So what happens inside of `bootflow_check()`? It simply calls the uclass +method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It +passes the iterator to the bootdev method, so that function knows what we are +talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`, +with just the `method` and `dev` intiialised. But the bootdev may fill in more, +e.g. updating the state, depending on what it finds. + +Based on what the bootdev responds with, `bootflow_check()` either +returns a valid bootflow, or a partial one with an error. A partial bootflow +is one that has some fields set up, but did not reach the `BOOTFLOWST_READY` +state. As noted before, if the `BOOTFLOWF_ALL` iterator flag is set, then all +bootflows are returned, even partial ones. This can help with debugging. + +So at this point you can see that total control over whether a bootflow can +be generated from a particular iteration, or not, rests with the bootdev. +Each one can adopt its own approach. + +Going down a level, what does the bootdev do in its `get_bootflow()` method? +Let us consider the MMC bootdev. In that case the call to +`bootdev_get_bootflow()` ends up in `mmc_get_bootflow()`. It locates the parent +device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds the block +device associated with it. It then calls the helper function +`bootdev_find_in_blk()` to do all the work. This is common with just about any +bootdev that is based on a media device. + +The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It +names the bootflow and copies the partition number in from the iterator. Then it +calls the bootmeth device to check if it can support this device. This is +important since some bootmeths only work with network devices, for example. If +that check fails, it stops. + +Assuming the bootmeth is happy, or at least indicates that it is willing to try +(by returning 0 from its `check()` method), the next step is to try the +partition. If that works it tries to detect a file system. If that works then it +calls the bootmeth device once more, this time to read the bootflow. + +Note: At present a filesystem is needed for the bootmeth to be called on block +devices, simply because we don't have any examples where this is not the case. +This feature can be added as needed. + +If we take the example of the `bootmeth_distro` driver, this call ends up at +`distro_read_bootflow()`. It has the filesystem ready, so tries various +filenames to try to find the `extlinux.conf` file, reading it if possible. If +all goes well the bootflow ends up in the `BOOTFLOWST_READY` state. + +At this point, we fall back from the bootmeth driver, to +`bootdev_find_in_blk()`, then back to `mmc_get_bootflow()`, then to +`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller, +either `bootflow_scan_bootdev()` or `bootflow_scan_next()`. In either case, +the bootflow is returned as the result of this iteration, assuming it made it to +the `BOOTFLOWST_READY` state. + +That is the basic operation of scanning for bootflows. The process of booting a +bootflow is handled by the bootmeth driver for that bootflow. In the case of +distro boot, this parses and processes the `extlinux.conf` file that was read. +See `distro_boot()` for how that works. The processing may involve reading +additional files, which is handled by the `read_file()` method, which is +`distro_read_file()` in this case. All bootmethds should support reading files, +since the bootflow is typically only the basic instructions and does not include +the operating system itself, ramdisk, device tree, etc. + +The vast majority of the bootstd code is concerned with iterating through +partitions on bootdevs and using bootmethds to find bootflows. + +How about bootdevs which are not block devices? They are handled by the same +methods as above, but with a different implementation. For example, the bootmeth +for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`. +But other that that it is very similar. + + +Tests +----- + +Tests are located in `test/boot` and cover the core functionality as well as +the commands. All tests use sandbox so can be run on a standard Linux computer +and in U-Boot's CI. + +For testing, a DOS-formatted disk image is used with a single FAT partition on +it. This is created in `setup_bootflow_image()`, with a canned one from the +source tree used if it cannot be created (e.g. in CI). + + +Bootflow internals +------------------ + +The bootstd device holds a linked list of scanned bootflows as well as the +currently selected bootdev and bootflow (for use by commands). This is in +`struct bootstd_priv`. + +Each bootdev device has its own `struct bootdev_uc_plat` which holds a +list of scanned bootflows just for that device. + +The bootflow itself is documented in bootflow_h_. It includes various bits of +information about the bootflow and a buffer to hold the file. + + +Future +------ + +Apart from the to-do items below, different types of bootflow files may be +implemented in future, e.g. Chromium OS support which is currently only +available as a script in chromebook_coral. + + +To do +----- + +Some things that need to be done to completely replace the distro-boot scripts: + +- add bootdev drivers for dhcp, sata, scsi, ide, virtio +- PXE boot for EFI +- support for loading U-Boot scripts + +Other ideas: + +- `bootflow prep` to load everything preparing for boot, so that `bootflow boot` + can just do the boot. +- automatically load kernel, FDT, etc. to suitable addresses so the board does + not need to specify things like `pxefile_addr_r` + + +.. _disto_boodcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h +.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/ +.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c +.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h diff --git a/doc/develop/distro.rst b/doc/develop/distro.rst index c522be69349..7ea84b5793c 100644 --- a/doc/develop/distro.rst +++ b/doc/develop/distro.rst @@ -157,6 +157,9 @@ a line with "CONFIG_DISTRO_DEFAULTS=y". If you want to enable this from Kconfig itself, for e.g. all boards using a specific SoC then add a "imply DISTRO_DEFAULTS" to your SoC CONFIG option. + +TO BE UPDATED: + In your board configuration file, include the following:: #ifndef CONFIG_SPL_BUILD diff --git a/doc/develop/index.rst b/doc/develop/index.rst index 9592d193fca..7c41589fb92 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -10,6 +10,7 @@ Implementation :maxdepth: 1 bloblist + bootstd ci_testing commands config_binding diff --git a/doc/device-tree-bindings/bootdev.txt b/doc/device-tree-bindings/bootdev.txt index 95b7fec8212..4bb2345a0b9 100644 --- a/doc/device-tree-bindings/bootdev.txt +++ b/doc/device-tree-bindings/bootdev.txt @@ -6,3 +6,21 @@ child of the media device (UCLASS_MMC, UCLASS_SPI_FLASH, etc.) The bootdev driver is provided by the media devices. The bindings for each are described in this file (to come). + +Required properties: + +compatible: + "u-boot,bootdev-eth" - Ethernet bootdev + "u-boot,bootdev-mmc" - MMC bootdev + "u-boot,bootdev-usb" - USB bootdev + + +Example: + + mmc1 { + compatible = "sandbox,mmc"; + + mmc-bootdev { + compatible = "u-boot,bootdev-eth"; + }; + }; diff --git a/doc/device-tree-bindings/bootmeth.txt b/doc/device-tree-bindings/bootmeth.txt new file mode 100644 index 00000000000..cba2dbe871c --- /dev/null +++ b/doc/device-tree-bindings/bootmeth.txt @@ -0,0 +1,31 @@ +U-Boot standard boot methods (bootmeth) +====================================== + +This provides methods (called bootmeths) for locating bootflows on a boot +device (bootdev). These are normally created as children of the bootstd device. + +Required properties: + +compatible: + "u-boot,distro-syslinux" - distro boot from a block device + "u-boot,distro-pxe" - distro boot from a network device + "u-boot,distro-efi" - EFI boot from a .efi file + "u-boot,efi-bootmgr" - EFI boot using boot manager (bootmgr) + + +Example: + + bootstd { + compatible = "u-boot,boot-std"; + + filename-prefixes = "/", "/boot/"; + bootdev-order = "mmc2", "mmc1"; + + syslinux { + compatible = "u-boot,distro-syslinux"; + }; + + efi { + compatible = "u-boot,distro-efi"; + }; + }; diff --git a/doc/device-tree-bindings/bootstd.txt b/doc/device-tree-bindings/bootstd.txt index f048b9dd327..8706c5f4993 100644 --- a/doc/device-tree-bindings/bootstd.txt +++ b/doc/device-tree-bindings/bootstd.txt @@ -25,4 +25,12 @@ Example: filename-prefixes = "/", "/boot/"; bootdev-order = "mmc2", "mmc1"; + + syslinux { + compatible = "u-boot,distro-syslinux"; + }; + + efi { + compatible = "u-boot,distro-efi"; + }; }; diff --git a/doc/usage/bootdev.rst b/doc/usage/bootdev.rst new file mode 100644 index 00000000000..ca5671e6f74 --- /dev/null +++ b/doc/usage/bootdev.rst @@ -0,0 +1,135 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bootdev command +=============== + +Synopis +------- + +:: + + bootdev list [-p] - list all available bootdevs (-p to probe)\n" + bootdev select - select a bootdev by name\n" + bootdev info [-p] - show information about a bootdev"; + +Description +----------- + +The `bootdev` command is used to manage bootdevs. It can list available +bootdevs, select one and obtain information about it. + +See :doc:`../develop/bootstd` for more information about bootdevs in general. + + +bootdev list +~~~~~~~~~~~~ + +This lists available bootdevs + +Scanning with `-p` causes the bootdevs to be probed. This happens automatically +when they are used. + +The list looks something like this: + +=== ====== ====== ======== ========================= +Seq Probed Status Uclass Name +=== ====== ====== ======== ========================= + 0 [ + ] OK mmc mmc@7e202000.bootdev + 1 [ ] OK mmc sdhci@7e300000.bootdev + 2 [ ] OK ethernet smsc95xx_eth.bootdev +=== ====== ====== ======== ========================= + + +The fields are as follows: + +Seq: + Sequence number in the scan, used to reference the bootflow later + +Probed: + Shows a plus (+) if the device is probed, empty if not. + +Status: + Shows the status of the device. Typically this is `OK` meaning that there is + no error. If you use -p and an error occurs when probing, then this shows + the error number. You can look up Linux error codes to find the meaning of + the number. + +Uclass: + Name of the media device's Uclass. This indicates the type of the parent + device (e.g. MMC, Ethernet). + +Name: + Name of the bootdev. This is generated from the media device appended + with `.bootdev` + + +bootdev select +~~~~~~~~~~~~~~~~~ + +Use this to select a particular bootdev. You can select it by the sequence +number or name, as shown in `bootdev list`. + +Once a bootdev is selected, you can use `bootdev info` to look at it or +`bootflow scan` to scan it. + +If no bootdev name or number is provided, then any existing bootdev is +unselected. + + +bootdev info +~~~~~~~~~~~~~~~ + +This shows information on the current bootdev, with the format looking like +this: + +========= ======================= +Name mmc@7e202000.bootdev +Sequence 0 +Status Probed +Uclass mmc +Bootflows 1 (1 valid) +========= ======================= + +Most of the information is the same as `bootdev list` above. The new fields +are: + +Device + Name of the bootdev + +Status + Shows `Probed` if the device is probed, `OK` if not. If `-p` is used and the + device fails to probe, an error code is shown. + +Bootflows + Indicates the number of bootflows attached to the bootdev. This is 0 + unless you have used 'bootflow scan' on the bootflow, or on all bootflows. + + +Example +------- + +This example shows listing available bootdev and getting information about +one of them:: + + U-Boot> bootdev list + Seq Probed Status Uclass Name + --- ------ ------ -------- ------------------ + 0 [ + ] OK mmc mmc@7e202000.bootdev + 1 [ ] OK mmc sdhci@7e300000.bootdev + 2 [ ] OK ethernet smsc95xx_eth.bootdev + --- ------ ------ -------- ------------------ + (3 devices) + U-Boot> bootdev sel 0 + U-Boot> bootflow scan + U-Boot> bootdev info + Name: mmc@7e202000.bootdev + Sequence: 0 + Status: Probed + Uclass: mmc + Bootflows: 1 (1 valid) + + +Return value +------------ + +The return value $? is always 0 (true). diff --git a/doc/usage/bootflow.rst b/doc/usage/bootflow.rst new file mode 100644 index 00000000000..347cc181bc5 --- /dev/null +++ b/doc/usage/bootflow.rst @@ -0,0 +1,427 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bootflow command +================ + +Synopis +------- + +:: + + bootflow scan [-abel] [bootdev] + bootflow list [-e] + bootflow select [] + bootflow info [-d] + bootflow boot + + +Description +----------- + +The `bootflow` command is used to manage bootflows. It can scan bootdevs to +locate bootflows, list them and boot them. + +See :doc:`../develop/bootstd` for more information. + + +bootflow scan +~~~~~~~~~~~~~ + +Scans for available bootflows, optionally booting the first valid one it finds. +This operates in two modes: + +- If no bootdev is selected (see `bootdev select`) it scans bootflows one + by one, extracting all the bootdevs from each +- If a bootdev is selected, it just scans that one bootflow + +Flags are: + +-a + Collect all bootflows, even those that cannot be loaded. Normally if a file + is not where it is expected, then the bootflow fails and so is dropped + during the scan. With this option you can see why each bootflow would be + dropped. + +-b + Boot each valid bootflow as it is scanned. Typically only the first bootflow + matters, since by then the system boots in the OS and U-Boot is no-longer + running. `bootflow scan -b` is a quick way to boot the first available OS. + A valid bootflow is one that made it all the way to the `loaded` state. + +-e + Used with -l to also show errors for each bootflow. The shows detailed error + information for each bootflow that failed to make it to the `loaded` state. + +-l + List bootflows while scanning. This is helpful when you want to see what + is happening during scanning. Use it with the `-b` flag to see which + bootdev and bootflows are being tried. + +The optional argument specifies a particular bootdev to scan. This can either be +the name of a bootdev or its sequence number (both shown with `bootdev list`). +Alternatively a convenience label can be used, like `mmc0`, which is the type of +device and an optional sequence number. Specifically, the label is the uclass of +the bootdev's parent followed by the sequence number of that parent. Sequence +numbers are typically set by aliases, so if you have 'mmc0' in your devicetree +alias section, then `mmc0` refers to the bootdev attached to that device. + + +bootflow list +~~~~~~~~~~~~~ + +Lists the previously scanned bootflows. You must use `bootflow scan` before this +to see anything. + +If you scanned with -a and have bootflows with errors, -e can be used to show +those errors. + +The list looks something like this: + +=== ====== ====== ======== ==== =============================== ================ +Seq Method State Uclass Part Name Filename +=== ====== ====== ======== ==== =============================== ================ + 0 distro ready mmc 2 mmc\@7e202000.bootdev.part_2 /boot/extlinux/extlinux.conf + 1 pxe ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf +=== ====== ====== ======== ==== =============================== ================ + +The fields are as follows: + +Seq: + Sequence number in the scan, used to reference the bootflow later + +Method: + The boot method (bootmeth) used to find the bootflow. Several methods are + included in U-Boot. + +State: + Current state of the bootflow, indicating how far the bootdev got in + obtaining a valid one. See :ref:`BootflowStates` for a list of states. + +Uclass: + Name of the media device's Uclass. This indicates the type of the parent + device (e.g. MMC, Ethernet). + +Part: + Partition number being accesseed, numbered from 1. Normally a device will + have a partition table with a small number of partitions. For devices + without partition tables (e.g. network) this field is 0. + +Name: + Name of the bootflow. This is generated from the bootdev appended with + the partition information + +Filename: + Name of the bootflow file. This indicates where the file is on the + filesystem or network device. + + +bootflow select +~~~~~~~~~~~~~~~ + +Use this to select a particular bootflow. You can select it by the sequence +number or name, as shown in `bootflow list`. + +Once a bootflow is selected, you can use `bootflow info` and `bootflow boot`. + +If no bootflow name or number is provided, then any existing bootflow is +unselected. + + +bootflow info +~~~~~~~~~~~~~ + +This shows information on the current bootflow, with the format looking like +this: + +========= =============================== +Name mmc\@7e202000.bootdev.part_2 +Device mmc\@7e202000.bootdev +Block dev mmc\@7e202000.blk +Type distro +Method: syslinux +State ready +Partition 2 +Subdir (none) +Filename /extlinux/extlinux.conf +Buffer 3db7ad48 +Size 232 (562 bytes) +Error 0 +========= =============================== + +Most of the information is the same as `bootflow list` above. The new fields +are: + +Device + Name of the bootdev + +Block dev + Name of the block device, if any. Network devices don't have a block device. + +Subdir + Subdirectory used for retrieving files. For network bootdevs this is the + directory of the 'bootfile' parameter passed from DHCP. All file retrievals + when booting are relative to this. + +Buffer + Buffer containing the bootflow file. You can use the :doc:`md` to look at + it, or dump it with `bootflow info -d`. + +Size + Size of the bootflow file + +Error + Error number returned from scanning for the bootflow. This is 0 if the + bootflow is in the 'loaded' state, or a negative error value on error. You + can look up Linux error codes to find the meaning of the number. + +Use the `-d` flag to dump out the contents of the bootfile file. + + +bootflow boot +~~~~~~~~~~~~~ + +This boots the current bootflow. + + +Example +------- + +Here is an example of scanning for bootflows, then listing them:: + + U-Boot> bootflow scan -l + Scanning for bootflows in all bootdevs + Seq Type State Uclass Part Name Filename + --- ----------- ------ -------- ---- ------------------------ ---------------- + Scanning bootdev 'mmc@7e202000.bootdev': + 0 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + Scanning bootdev 'sdhci@7e300000.bootdev': + Card did not respond to voltage select! : -110 + Scanning bootdev 'smsc95xx_eth.bootdev': + Waiting for Ethernet connection... done. + BOOTP broadcast 1 + DHCP client bound to address 192.168.4.30 (4 ms) + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/'. + Load address: 0x200000 + Loading: * + TFTP error: 'Is a directory' (0) + Starting again + + missing environment variable: pxeuuid + Retrieving file: rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1 + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1'. + Load address: 0x2500000 + Loading: ################################################## 566 Bytes + 45.9 KiB/s + done + Bytes transferred = 566 (236 hex) + 1 distro ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf + No more bootdevs + --- ----------- ------ -------- ---- ------------------------ ---------------- + (2 bootflows, 2 valid) + U-Boot> bootflow l + Showing all bootflows + Seq Type State Uclass Part Name Filename + --- ----------- ------ -------- ---- ------------------------ ---------------- + 0 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + 1 pxe ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf + --- ----------- ------ -------- ---- ------------------------ ---------------- + (2 bootflows, 2 valid) + + +The second one is then selected by name (we could instead use `bootflow sel 0`), +displayed and booted:: + + U-Boot> bootflow info + No bootflow selected + U-Boot> bootflow sel mmc@7e202000.bootdev.part_2 + U-Boot> bootflow info + Name: mmc@7e202000.bootdev.part_2 + Device: mmc@7e202000.bootdev + Block dev: mmc@7e202000.blk + Sequence: 1 + Method: distro + State: ready + Partition: 2 + Subdir: (none) + Filename: extlinux/extlinux.conf + Buffer: 3db7ae88 + Size: 232 (562 bytes) + Error: 0 + U-Boot> bootflow boot + ** Booting bootflow 'smsc95xx_eth.bootdev.0' + Ignoring unknown command: ui + Ignoring malformed menu command: autoboot + Ignoring malformed menu command: hidden + Ignoring unknown command: totaltimeout + 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Retrieving file: rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img + get 2700000 rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img'. + Load address: 0x2700000 + Loading: ###################################T ############### 57.7 MiB + 1.9 MiB/s + done + Bytes transferred = 60498594 (39b22a2 hex) + Retrieving file: rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl + get 80000 rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl'. + Load address: 0x80000 + Loading: ################################################## 7.2 MiB + 2.3 MiB/s + done + Bytes transferred = 7508480 (729200 hex) + append: ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + Retrieving file: rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + get 2600000 rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb'. + Load address: 0x2600000 + Loading: ################################################## 13.8 KiB + 764.6 KiB/s + done + Bytes transferred = 14102 (3716 hex) + Kernel image @ 0x080000 [ 0x000000 - 0x729200 ] + ## Flattened Device Tree blob at 02600000 + Booting using the fdt blob at 0x2600000 + Using Device Tree in place at 02600000, end 02606715 + + Starting kernel ... + + [ OK ] Started Show Plymouth Boot Screen. + [ OK ] Started Forward Password R…s to Plymouth Directory Watch. + [ OK ] Reached target Local Encrypted Volumes. + [ OK ] Reached target Paths. + .... + + +Here we scan for bootflows and boot the first one found:: + + U-Boot> bootflow scan -bl + Scanning for bootflows in all bootdevs + Seq Method State Uclass Part Name Filename + --- ----------- ------ -------- ---- ---------------------- ---------------- + Scanning bootdev 'mmc@7e202000.bootdev': + 0 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + ** Booting bootflow 'mmc@7e202000.bootdev.part_2' + Ignoring unknown command: ui + Ignoring malformed menu command: autoboot + Ignoring malformed menu command: hidden + Ignoring unknown command: totaltimeout + 1: Fedora-KDE-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Retrieving file: /initramfs-5.3.7-301.fc31.armv7hl.img + getfile 2700000 /initramfs-5.3.7-301.fc31.armv7hl.img + Retrieving file: /vmlinuz-5.3.7-301.fc31.armv7hl + getfile 80000 /vmlinuz-5.3.7-301.fc31.armv7hl + append: ro root=UUID=b8781f09-e2dd-4cb8-979b-7df5eeaaabea rhgb LANG=en_US.UTF-8 cma=192MB console=tty0 console=ttyS1,115200 + Retrieving file: /dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + getfile 2600000 /dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + Kernel image @ 0x080000 [ 0x000000 - 0x729200 ] + ## Flattened Device Tree blob at 02600000 + Booting using the fdt blob at 0x2600000 + Using Device Tree in place at 02600000, end 02606715 + + Starting kernel ... + + [ 0.000000] Booting Linux on physical CPU 0x0 + + +Here is am example using the -e flag to see all errors:: + + U-Boot> bootflow scan -a + Card did not respond to voltage select! : -110 + Waiting for Ethernet connection... done. + BOOTP broadcast 1 + DHCP client bound to address 192.168.4.30 (4 ms) + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/'. + Load address: 0x200000 + Loading: * + TFTP error: 'Is a directory' (0) + Starting again + + missing environment variable: pxeuuid + Retrieving file: rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1 + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1'. + Load address: 0x2500000 + Loading: ################################################## 566 Bytes + 49.8 KiB/s + done + Bytes transferred = 566 (236 hex) + U-Boot> bootflow l -e + Showing all bootflows + Seq Type State Uclass Part Name Filename + --- ----------- ------ -------- ---- --------------------- ---------------- + 0 distro fs mmc 1 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + ** File not found, err=-2 + 1 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + 2 distro fs mmc 3 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + ** File not found, err=-1 + 3 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 4 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 5 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 6 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 7 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 8 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 9 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + a distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + b distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + c distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + d distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + e distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + f distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 10 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 11 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 12 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 13 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 14 distro ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf + --- ----------- ------ -------- ---- --------------------- ---------------- + (21 bootflows, 2 valid) + U-Boot> + + +Return value +------------ + +On success `bootflow boot` normally boots into the Operating System and does not +return to U-Boot. If something about the U-Boot processing fails, then the +return value $? is 1. If the boot succeeds but for some reason the Operating +System returns, then $? is 0, indicating success. + +For other subcommands, the return value $? is always 0 (true). + + +.. BootflowStates_: diff --git a/doc/usage/bootmeth.rst b/doc/usage/bootmeth.rst new file mode 100644 index 00000000000..1bb2b9d5c09 --- /dev/null +++ b/doc/usage/bootmeth.rst @@ -0,0 +1,108 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bootmeth command +================ + +Synopis +------- + +:: + + bootmeth list [-a] - list selected bootmeths (-a for all) + bootmeth order "[ ...]" - select the order of bootmeths\n" + + +Description +----------- + +The `bootmeth` command is used to manage bootmeths. It can list them and change +the order in which they are used. + +See :doc:`../develop/bootstd` for more information. + + +.. _bootmeth_order: + +bootmeth order +~~~~~~~~~~~~~~ + +Selects which bootmeths to use and the order in which they are invoked. When +scanning bootdevs, each bootmeth is tried in turn to see if it can find a valid +bootflow. You can use this command to adjust the order or even to omit some +boomeths. + +The argument is a quoted list of bootmeths to use, by name. + + +bootmeth list +~~~~~~~~~~~~~ + +This lists the selected bootmeths, or all of them, if the `-a` flag is used. +The format looks like this: + +===== === ================== ================================= +Order Seq Name Description +===== === ================== ================================= + 0 0 distro Syslinux boot from a block device + 1 1 efi EFI boot from a .efi file + 2 2 pxe PXE boot from a network device + 3 3 sandbox Sandbox boot for testing + 4 4 efi_mgr EFI bootmgr flow +===== === ================== ================================= + +The fields are as follows: + +Order: + The order in which these bootmeths are invoked for each bootdev. If this + shows as a hyphen, then the bootmeth is not in the current ordering. + +Seq: + The sequence number of the bootmeth, i.e. the normal ordering if none is set + +Name: + Name of the bootmeth + +Description: + A friendly description for the bootmeth + + +Example +------- + +This shows listing bootmeths. All are present and in the normal order:: + + => bootmeth list + Order Seq Name Description + ----- --- ------------------ ------------------ + 0 0 distro Syslinux boot from a block device + 1 1 efi EFI boot from a .efi file + 2 2 pxe PXE boot from a network device + 3 3 sandbox Sandbox boot for testing + 4 4 efi_mgr EFI bootmgr flow + ----- --- ------------------ ------------------ + (5 bootmeths) + +Now the order is changed, to include only two of them:: + + => bootmeth order "sandbox distro" + => bootmeth list + Order Seq Name Description + ----- --- ------------------ ------------------ + 0 3 sandbox Sandbox boot for testing + 1 0 distro Syslinux boot from a block device + ----- --- ------------------ ------------------ + (2 bootmeths) + +The -a flag shows all bootmeths so you can clearly see which ones are used and +which are not:: + + => bootmeth list -a + Order Seq Name Description + ----- --- ------------------ ------------------ + 1 0 distro Syslinux boot from a block device + - 1 efi EFI boot from a .efi file + - 2 pxe PXE boot from a network device + 0 3 sandbox Sandbox boot for testing + - 4 efi_mgr EFI bootmgr flow + ----- --- ------------------ ------------------ + (5 bootmeths) diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 33761af96af..3f6903ad76b 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -21,9 +21,12 @@ Shell commands addrmap askenv base + bootdev bootefi + bootflow booti bootmenu + bootmeth button x86/cbsysinfo conitrace From patchwork Wed Jan 19 01:43:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1581619 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Xff2Jeq3; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4JdpSn3tsQz9sPC for ; Wed, 19 Jan 2022 12:48:25 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 32706838B7; Wed, 19 Jan 2022 02:45:34 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Xff2Jeq3"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2BA10837CF; Wed, 19 Jan 2022 02:44:33 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-io1-xd36.google.com (mail-io1-xd36.google.com [IPv6:2607:f8b0:4864:20::d36]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 4318E837CA for ; Wed, 19 Jan 2022 02:44:11 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-io1-xd36.google.com with SMTP id n137so973061iod.4 for ; Tue, 18 Jan 2022 17:44:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=LBzMRiHgsHY66vC9J0dLxtyew2loEw8gODfnGL/ErC0=; b=Xff2Jeq3NKt2V0aOWZwT/XBJ3aO+gDKFQI/STm1pqTeCfEfSjdAvR/DIm2KKYfS4LZ suD55golrN68Rn3TdkLUaPFWiC4U61fI9X8f555G/2/94Hh3aKWjW9a2bcgGZYXHDcwX MOhTkg5z03FCcq2zi7N5koRhncrzPbw/jE+CU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=LBzMRiHgsHY66vC9J0dLxtyew2loEw8gODfnGL/ErC0=; b=BRnkF8xpeRYgvr8EtpZOVq0IEotZQFxCKgFa91quLTslFqXSw/uKdg4bnD2EeV3ywB 3ujc1POWDeuzEO/Xfxz4VArXky1C9/x6OJcf8+YyHXotWjaj4w98aGjxIuC2weG7r+sp /LzTTuRylO/Et3fAGVcNZM3kLEjf/ClerZvZQJsfohI4AYCRRRvzGPKQ8Ho4bBHXHAGK rvbXRCwZre9LLnQJJlcJ1AFXkwm8cdeC7YOy6SugmyWv4uteTwSiw/zmjnEYzTFtSMeW L53FJBnK9J6DGzUN+MHZBdu5BZLHZ5byzCEqmBrFLzwG9M8Ga9VDAgH+r5D8Sks1wwXc R6jA== X-Gm-Message-State: AOAM533dV4csQSnpunrKuLoM5RJ6+H5hcFZbcn+hfsdweEjiAeR+wv0+ ckIGISm3JzWNk5+6ipEh7XLESv3Gs1anzg== X-Google-Smtp-Source: ABdhPJzdC39Nc3WHcL5Jb1Ik1oTv+PdTFJDTcZYpCxRlxL1Lub95mdUm8SNez+36A6j4D+CVnTWu7g== X-Received: by 2002:a6b:4e10:: with SMTP id c16mr13375265iob.202.1642556649627; Tue, 18 Jan 2022 17:44:09 -0800 (PST) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id j18sm10546314ila.86.2022.01.18.17.44.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Jan 2022 17:44:09 -0800 (PST) From: Simon Glass To: U-Boot Mailing List Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , Heinrich Schuchardt , Simon Glass Subject: [PATCH v3 31/31] RFC: Switch rpi over to use bootstd Date: Tue, 18 Jan 2022 18:43:15 -0700 Message-Id: <20220119014315.1938157-21-sjg@chromium.org> X-Mailer: git-send-email 2.34.1.703.g22d0c6ccf7-goog In-Reply-To: <20220119014315.1938157-1-sjg@chromium.org> References: <20220119014315.1938157-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Switch this over, for testing purposes. Signed-off-by: Simon Glass --- (no changes since v1) boot/Kconfig | 3 ++- include/configs/rpi.h | 39 ++------------------------------------- 2 files changed, 4 insertions(+), 38 deletions(-) diff --git a/boot/Kconfig b/boot/Kconfig index 9cf1d013f20..eab3c0f3467 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1124,7 +1124,8 @@ config USE_BOOTCOMMAND config BOOTCOMMAND string "bootcmd value" depends on USE_BOOTCOMMAND && !USE_DEFAULT_ENV_FILE - default "run distro_bootcmd" if DISTRO_DEFAULTS + default "bootflow scan -lb" if BOOTSTD + default "run distro_bootcmd" if !BOOTSTD && DISTRO_DEFAULTS help This is the string of commands that will be used as bootcmd and if AUTOBOOT is set, automatically run. diff --git a/include/configs/rpi.h b/include/configs/rpi.h index d5e064fb379..ea373d0c221 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -133,47 +133,12 @@ "fdt_addr_r=0x02600000\0" \ "ramdisk_addr_r=0x02700000\0" -#if CONFIG_IS_ENABLED(CMD_MMC) - #define BOOT_TARGET_MMC(func) \ - func(MMC, mmc, 0) \ - func(MMC, mmc, 1) \ - func(MMC, mmc, 2) -#else - #define BOOT_TARGET_MMC(func) -#endif - -#if CONFIG_IS_ENABLED(CMD_USB) - #define BOOT_TARGET_USB(func) func(USB, usb, 0) -#else - #define BOOT_TARGET_USB(func) -#endif - -#if CONFIG_IS_ENABLED(CMD_PXE) - #define BOOT_TARGET_PXE(func) func(PXE, pxe, na) -#else - #define BOOT_TARGET_PXE(func) -#endif - -#if CONFIG_IS_ENABLED(CMD_DHCP) - #define BOOT_TARGET_DHCP(func) func(DHCP, dhcp, na) -#else - #define BOOT_TARGET_DHCP(func) -#endif - -#define BOOT_TARGET_DEVICES(func) \ - BOOT_TARGET_MMC(func) \ - BOOT_TARGET_USB(func) \ - BOOT_TARGET_PXE(func) \ - BOOT_TARGET_DHCP(func) - -#include - #define CONFIG_EXTRA_ENV_SETTINGS \ "dhcpuboot=usb start; dhcp u-boot.uimg; bootm\0" \ + "boot_targets=mmc0 mmc1 usb0 pxe dhcp\0" \ ENV_DEVICE_SETTINGS \ ENV_DFU_SETTINGS \ - ENV_MEM_LAYOUT_SETTINGS \ - BOOTENV + ENV_MEM_LAYOUT_SETTINGS #endif