From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBAE8C07E99 for ; Mon, 5 Jul 2021 22:36:58 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4B44061956 for ; Mon, 5 Jul 2021 22:36:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4B44061956 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8D0AE82C85; Tue, 6 Jul 2021 00:34:37 +0200 (CEST) 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="glWXpelB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id EC05282C1C; Tue, 6 Jul 2021 00:33:51 +0200 (CEST) Received: from mail-oo1-xc30.google.com (mail-oo1-xc30.google.com [IPv6:2607:f8b0:4864:20::c30]) (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 EC3A282BFF for ; Tue, 6 Jul 2021 00:33:31 +0200 (CEST) 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-oo1-xc30.google.com with SMTP id i26-20020a4ad39a0000b02902554d87361cso1518193oos.13 for ; Mon, 05 Jul 2021 15:33:31 -0700 (PDT) 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=A3ombogXF8UOOuHEaB9YJSW4jiogZkHYs7TpL94QWDs=; b=glWXpelBe8jGqPuR/Qt8774xgX7ZzEpB3sOaCz7jhCqD4lPRUwbME39+//m0YdZSZW uF7mvt5Awf4Gx3anJd4opH69J8QibM9KSxY4T3AzXD6nq00nOv6TA7AalTWVKq4jI1xQ 3GMhpck36X/ppfpXtQS+6GulMM7ry7+HEdVb8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=A3ombogXF8UOOuHEaB9YJSW4jiogZkHYs7TpL94QWDs=; b=HHc8QRuWKOrLDyU4WSlh+PMo2Op8TQ8Plkufy5y0aD/gXpsVZ+1s6byWv1YmqjV5uL oCQtfTxAhZU+wGtXgR1v0g2NoMCDvoIEXSstOX1AvWIlCMaaMEogP2mott4VE+OMFcpU dtKpCWtimlo5Pesyrz9+boDwu9UTlEnPXs/SGg3iejmcq4W5Lo+/PJSkJtY3L5TPrnxe 7tw7lTDUSzGkCWbPtxgY3e+h4OMfs5cyKXbJi0lyQpU+BxrzAz6ixvAudTYS/VO2prhC OFKK6UoRgJR+Qt1Rim0xv+GAV1aPUt5EV5sTBoNupDu477agdiLfvfaRiG3xM3w48wYA ychw== X-Gm-Message-State: AOAM5336DK9h5ZnVw1yWKMt9S+Wj4Ra6/1Ki9Aw4zv6NnMfQD80Bae0K ozSzE2gGIiq4l+K5ae2BlMsbQih9Q78oSg8k X-Google-Smtp-Source: ABdhPJy/mH29+QKOhHZGMDxHye2N8hzAwb1u413nQmxk/0/m7NtdFN/qwW5M19biibQ6D02Ed3rTxw== X-Received: by 2002:a05:6820:168:: with SMTP id k8mr11545529ood.76.1625524410132; Mon, 05 Jul 2021 15:33:30 -0700 (PDT) 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 u22sm1434938oie.26.2021.07.05.15.33.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Jul 2021 15:33:29 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Simon Glass , Anastasiia Lukianenko , Andrii Anisov , Oleksandr Andrushchenko , Ovidiu Panait , Patrick Delaunay Subject: [PATCH 21/22] blk: Support iteration Date: Mon, 5 Jul 2021 16:32:59 -0600 Message-Id: <20210705223300.2139971-20-sjg@chromium.org> X-Mailer: git-send-email 2.32.0.93.g670b81a890-goog In-Reply-To: <20210705223300.2139971-1-sjg@chromium.org> References: <20210705223300.2139971-1-sjg@chromium.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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 is useful to be able to iterate over block devices. Typically there are fixed and removable devices. For security reasons it is sometimes useful to ignore removable devices since they are under user control. Add iterators which support selecting the block-device type. Signed-off-by: Simon Glass --- drivers/block/blk-uclass.c | 49 +++++++++++++++++++++++++++++++++ include/blk.h | 56 ++++++++++++++++++++++++++++++++++++++ test/dm/blk.c | 55 +++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index dfc0d469702..83682dcc181 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -540,6 +540,55 @@ int blk_next_free_devnum(enum if_type if_type) return ret + 1; } +static int blk_flags_check(struct udevice *dev, enum blk_flag_t req_flags) +{ + const struct blk_desc *desc = dev_get_uclass_plat(dev); + enum blk_flag_t flags; + + flags = desc->removable ? BLKF_REMOVABLE : BLKF_FIXED; + + return flags & req_flags ? 0 : 1; +} + +int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp) +{ + int ret; + + for (ret = uclass_first_device_err(UCLASS_BLK, devp); + !ret; + ret = uclass_next_device_err(devp)) { + if (!blk_flags_check(*devp, flags)) + return 0; + } + + return -ENODEV; +} + +int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp) +{ + int ret; + + for (ret = uclass_next_device_err(devp); + !ret; + ret = uclass_next_device_err(devp)) { + if (!blk_flags_check(*devp, flags)) + return 0; + } + + return -ENODEV; +} + +int blk_count_devices(enum blk_flag_t flag) +{ + struct udevice *dev; + int count = 0; + + blk_foreach_probe(flag, dev) + count++; + + return count; +} + static int blk_claim_devnum(enum if_type if_type, int devnum) { struct udevice *dev; diff --git a/include/blk.h b/include/blk.h index c4401b00253..19bab081c2c 100644 --- a/include/blk.h +++ b/include/blk.h @@ -19,6 +19,8 @@ typedef ulong lbaint_t; #define LBAF "%" LBAFlength "x" #define LBAFU "%" LBAFlength "u" +struct udevice; + /* Interface types: */ enum if_type { IF_TYPE_UNKNOWN = 0, @@ -683,4 +685,58 @@ const char *blk_get_if_type_name(enum if_type if_type); int blk_common_cmd(int argc, char *const argv[], enum if_type if_type, int *cur_devnump); +enum blk_flag_t { + BLKF_FIXED = 1 << 0, + BLKF_REMOVABLE = 1 << 1, + BLKF_BOTH = BLKF_FIXED | BLKF_REMOVABLE, +}; + +/** + * blk_first_device_err() - Get the first block device + * + * The device returned is probed if necessary, and ready for use + * + * @flags: Indicates type of device to return + * @devp: Returns pointer to the first device in that uclass, or NULL if none + * @return 0 if found, -ENODEV if not found, other -ve on error + */ +int blk_first_device_err(enum blk_flag_t flags, struct udevice **devp); + +/** + * blk_next_device_err() - Get the next block device + * + * The device returned is probed if necessary, and ready for use + * + * @flags: Indicates type of device to return + * @devp: On entry, pointer to device to lookup. On exit, returns pointer + * to the next device in the uclass if no error occurred, or -ENODEV if + * there is no next device. + * @return 0 if found, -ENODEV if not found, other -ve on error + */ +int blk_next_device_err(enum blk_flag_t flags, struct udevice **devp); + +/** + * blk_foreach_probe() - Helper function to iteration through block devices + * + * This creates a for() loop which works through the available devices in + * a uclass in order from start to end. Devices are probed if necessary, + * and ready for use. + * + * @flags: Indicates type of device to return + * @dev: struct udevice * to hold the current device. Set to NULL when there + * are no more devices. + */ +#define blk_foreach_probe(flags, pos) \ + for (int _ret = blk_first_device_err(flags, &(pos)); \ + !_ret && pos; \ + _ret = blk_next_device_err(flags, &(pos))) + +/** + * blk_count_devices() - count the number of devices of a particular type + * + * @flags: Indicates type of device to find + * @return number of devices matching those flags + */ +int blk_count_devices(enum blk_flag_t flag); + #endif diff --git a/test/dm/blk.c b/test/dm/blk.c index b7f4304e9e9..deccf05289b 100644 --- a/test/dm/blk.c +++ b/test/dm/blk.c @@ -162,3 +162,58 @@ static int dm_test_blk_get_from_parent(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_blk_get_from_parent, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test iteration through block devices */ +static int dm_test_blk_iter(struct unit_test_state *uts) +{ + struct udevice *dev; + int i; + + /* + * See sandbox test.dts - it has: + * + * mmc0 - removable + * mmc1 - removable + * mmc2 - fixed + */ + ut_assertok(blk_first_device_err(BLKF_FIXED, &dev)); + ut_asserteq_str("mmc2.blk", dev->name); + ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev)); + + ut_assertok(blk_first_device_err(BLKF_REMOVABLE, &dev)); + ut_asserteq_str("mmc1.blk", dev->name); + ut_assertok(blk_next_device_err(BLKF_REMOVABLE, &dev)); + ut_asserteq_str("mmc0.blk", dev->name); + ut_asserteq(-ENODEV, blk_next_device_err(BLKF_REMOVABLE, &dev)); + + ut_assertok(blk_first_device_err(BLKF_BOTH, &dev)); + ut_asserteq_str("mmc2.blk", dev->name); + ut_assertok(blk_next_device_err(BLKF_BOTH, &dev)); + ut_asserteq_str("mmc1.blk", dev->name); + ut_assertok(blk_next_device_err(BLKF_BOTH, &dev)); + ut_asserteq_str("mmc0.blk", dev->name); + ut_asserteq(-ENODEV, blk_next_device_err(BLKF_FIXED, &dev)); + + ut_asserteq(1, blk_count_devices(BLKF_FIXED)); + ut_asserteq(2, blk_count_devices(BLKF_REMOVABLE)); + ut_asserteq(3, blk_count_devices(BLKF_BOTH)); + + i = 0; + blk_foreach_probe(BLKF_FIXED, dev) + ut_asserteq_str((i++, "mmc2.blk"), dev->name); + ut_asserteq(1, i); + + i = 0; + blk_foreach_probe(BLKF_REMOVABLE, dev) + ut_asserteq_str(i++ ? "mmc0.blk" : "mmc1.blk", dev->name); + ut_asserteq(2, i); + + i = 0; + blk_foreach_probe(BLKF_BOTH, dev) + ut_asserteq_str((++i == 1 ? "mmc2.blk" : i == 2 ? + "mmc1.blk" : "mmc0.blk"), dev->name); + ut_asserteq(3, i); + + return 0; +} +DM_TEST(dm_test_blk_iter, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); -- 2.32.0.93.g670b81a890-goog