From patchwork Fri Oct 31 06:54:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 656 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1761893727; bh=wqPhogXh5SRR60idczNI8OqphwVZ0NXCVyDjq3JMfaM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=HCoe2jFEbKaE3aroSnSI/4gVX9HZ7oYGiXS6KfUbsTUoYugYYPSJep1Yg3hbtIUds t7w9ra+mBZYxuDZLT/VmpdZ05B4GaUto503t4TZIm6t56i8wszhtuvFGLxOBxRgvhf dP6uYToa2KoiriUeI95zbDFhOREbB0e0R8yLnvPfxQ/yIoF8yhzqO0fgTHC9fkuVoj Xj/TnSZBZOEmW08h0SOP9WMp3F5JiUGyeasmBL72IxJkTK/S/AnvqWDC5DE10oUWiq KdbL4DKP2k9WC/R3BwXiRz7JMQP575B+PUhage/WzN7lmpQD8Jph89+HTv5V1KfKNJ uV3tIBlUqyVVg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 4152268356 for ; Fri, 31 Oct 2025 00:55:27 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 5SaLcmEmxBS0 for ; Fri, 31 Oct 2025 00:55:27 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1761893727; bh=wqPhogXh5SRR60idczNI8OqphwVZ0NXCVyDjq3JMfaM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=HCoe2jFEbKaE3aroSnSI/4gVX9HZ7oYGiXS6KfUbsTUoYugYYPSJep1Yg3hbtIUds t7w9ra+mBZYxuDZLT/VmpdZ05B4GaUto503t4TZIm6t56i8wszhtuvFGLxOBxRgvhf dP6uYToa2KoiriUeI95zbDFhOREbB0e0R8yLnvPfxQ/yIoF8yhzqO0fgTHC9fkuVoj Xj/TnSZBZOEmW08h0SOP9WMp3F5JiUGyeasmBL72IxJkTK/S/AnvqWDC5DE10oUWiq KdbL4DKP2k9WC/R3BwXiRz7JMQP575B+PUhage/WzN7lmpQD8Jph89+HTv5V1KfKNJ uV3tIBlUqyVVg== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2F067682E9 for ; Fri, 31 Oct 2025 00:55:27 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1761893725; bh=dZ4s4pm7vh68RxxcVSpU7BXphcnpA/PLmw2Te24H3Rg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lxKG2fYU6CdEtVf4HDKeESr/oGbxw8daeL7chICk9pkk23ukhYZBor/E4bzx5RIzf V2hiLYQrIarSSrRjUULC5sjB3L4Rog9W0Bg2SvGyQjN71/fhMC4SVqI2IMkH+hIZXB f+8Hlvn8TDRKbcxyli664+J+WsyZp7v2gn/H1fFtP1f/faLuylEM5w5cCGrpbv2BKy 43fhB9FqcsfYXM4CJZKQECw1GmMgdFfRwCm+zKqpUakfvKj3TUroxE9ixYt0SZRB3e dTJObMPru4Ack3dFWN2GSPI/bQmk5wPY5Bhh/Qq0A5bMkbYucxm71dEEFc/nJQTDwk 0tku3+pOhQ62w== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id DEE916827C; Fri, 31 Oct 2025 00:55:25 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 8gQEuuAY5Tmd; Fri, 31 Oct 2025 00:55:25 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1761893721; bh=pri76NJxHvalPL8FW8RUF30kYlE1jDJ2JSNoZrtt85s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aAYADB66hPApJcU04CpK57857Wp4MXrAGCvo95MCRBfpYCcgyIeSaqGtD5SOpTaaJ KCcz+8oKz74oqS8kwr3U32MvlwSv2T4mmrZz4DLRVnGQWhk3wrApCrgLbhXsIMveGS bhoqDQnOTo9rFAbSktYy2eQTgRbEL7toD5vuAB2romOqvLJxwr9X+UjOIUHA6pB0eP eGeT6VZ0TSHgaiS/W/BcLbaOewrsT6EF65ubmchkguN4CwFABGuoyPi3ubjmow3Yon 2AV2Zl5E8okAMvaIeCnjCoirrIeNNJWrMDfldHSnCNxmzxvVhS2foGsRNWxaAPCvsc 1n2WTvyFL6Q6g== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 5823668321; Fri, 31 Oct 2025 00:55:21 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Fri, 31 Oct 2025 00:54:02 -0600 Message-ID: <20251031065439.3251464-7-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251031065439.3251464-1-sjg@u-boot.org> References: <20251031065439.3251464-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: TOY2C73EINP7ZHG2H7GPSRZQE36PVDEM X-Message-ID-Hash: TOY2C73EINP7ZHG2H7GPSRZQE36PVDEM X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 06/24] sandbox: Add devon and devoff subcommands to sb command List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass There are quite a few media devices in test.dts which are not enabled by default, so are not bound on startup. Sometimes it is useful to be able to use these from the command line. Add 'sb devon' and 'sb devoff' subcommands to enable and disable devices from the device tree. For example, running sandbox with -T, then 'sb devon mmc11' enables the mmc11 device mentioned in test.dts Co-developed-by: Claude Signed-off-by: Simon Glass --- cmd/sb.c | 107 +++++++++++++++++++++++++++++++++++-- doc/usage/cmd/sb.rst | 40 +++++++++++++- test/cmd/Makefile | 1 + test/cmd/sb.c | 123 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+), 4 deletions(-) create mode 100644 test/cmd/sb.c diff --git a/cmd/sb.c b/cmd/sb.c index 79f3fb0aacd..7de43e7edc3 100644 --- a/cmd/sb.c +++ b/cmd/sb.c @@ -10,6 +10,10 @@ #include #include #include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; static int do_sb_handoff(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -47,12 +51,109 @@ static int do_sb_state(struct cmd_tbl *cmdtp, int flag, int argc, return 0; } +static int do_sb_devon(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + ofnode root, node; + int ret; + + if (argc != 2) + return CMD_RET_USAGE; + + /* Find the specified device tree node */ + root = oftree_root(oftree_default()); + node = ofnode_find_subnode(root, argv[1]); + if (!ofnode_valid(node)) { + printf("Device tree node '%s' not found\n", argv[1]); + return CMD_RET_FAILURE; + } + + /* Check if device is already bound */ + ret = device_find_global_by_ofnode(node, &dev); + if (!ret) { + printf("Device '%s' is already enabled\n", argv[1]); + return CMD_RET_FAILURE; + } + + /* Bind the device from device tree */ + ret = lists_bind_fdt(gd->dm_root, node, &dev, NULL, false); + if (ret) { + printf("Failed to bind device '%s' (err %dE)\n", argv[1], + ret); + return CMD_RET_FAILURE; + } + + /* Probe the device */ + ret = device_probe(dev); + if (ret) { + printf("Failed to probe device '%s' (err %dE)\n", argv[1], + ret); + return CMD_RET_FAILURE; + } + + printf("Device '%s' enabled\n", dev->name); + + return CMD_RET_SUCCESS; +} + +static int do_sb_devoff(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct udevice *dev; + ofnode root, node; + int ret; + + if (argc != 2) + return CMD_RET_USAGE; + + /* Find the specified device tree node */ + root = oftree_root(oftree_default()); + node = ofnode_find_subnode(root, argv[1]); + if (!ofnode_valid(node)) { + printf("Device tree node '%s' not found\n", argv[1]); + return CMD_RET_FAILURE; + } + + /* Find the device bound to this node */ + ret = device_find_global_by_ofnode(node, &dev); + if (ret) { + printf("Device '%s' not found or not bound (err %dE)\n", + argv[1], ret); + return CMD_RET_FAILURE; + } + + /* Remove the device (deactivate it) */ + ret = device_remove(dev, DM_REMOVE_NORMAL); + if (ret) { + printf("Failed to remove device '%s' (err %dE)\n", argv[1], + ret); + return CMD_RET_FAILURE; + } + + /* Unbind the device */ + ret = device_unbind(dev); + if (ret) { + printf("Failed to unbind device '%s' (err %dE)\n", argv[1], + ret); + return CMD_RET_FAILURE; + } + + printf("Device '%s' disabled\n", argv[1]); + + return CMD_RET_SUCCESS; +} + U_BOOT_LONGHELP(sb, - "handoff - Show handoff data received from SPL\n" - "sb map - Show mapped memory\n" - "sb state - Show sandbox state"); + "devoff - Disable device from device tree node\n" + "sb devon - Enable device from device tree node\n" + "sb handoff - Show handoff data received from SPL\n" + "sb map - Show mapped memory\n" + "sb state - Show sandbox state"); U_BOOT_CMD_WITH_SUBCMDS(sb, "Sandbox status commands", sb_help_text, + U_BOOT_SUBCMD_MKENT(devoff, 2, 1, do_sb_devoff), + U_BOOT_SUBCMD_MKENT(devon, 2, 1, do_sb_devon), U_BOOT_SUBCMD_MKENT(handoff, 1, 1, do_sb_handoff), U_BOOT_SUBCMD_MKENT(map, 1, 1, do_sb_map), U_BOOT_SUBCMD_MKENT(state, 1, 1, do_sb_state)); diff --git a/doc/usage/cmd/sb.rst b/doc/usage/cmd/sb.rst index 37431aff7c8..ee9b3d80767 100644 --- a/doc/usage/cmd/sb.rst +++ b/doc/usage/cmd/sb.rst @@ -11,6 +11,8 @@ Synopsis :: + sb devoff + sb devon sb handoff sb map sb state @@ -19,7 +21,24 @@ Description ----------- The *sb* command is used to display information about sandbox's internal -operation. See :doc:`/arch/sandbox/index` for more information. +operation and to manage devices. See :doc:`/arch/sandbox/index` for more +information. + +sb devoff +~~~~~~~~~ + +This disables a device that was previously enabled with *sb devon*. The device +is removed (deactivated) and unbound from the driver model. The parameter is +the name of a device tree node. + +sb devon +~~~~~~~~ + +This enables a device from the device tree. The device tree node is located, +bound to the driver model, and probed (activated). This is useful for testing +devices that are not automatically bound at startup, i.e. those marked as +status = "disabled" in the device tree. The parameter is the name of a root +devicetree node. sb handoff ~~~~~~~~~~ @@ -54,6 +73,25 @@ command-line with which sandbox was started. Example ------- +This shows enabling a device from the `test.dts` device tree. Note that sandbox +must be run with the -T flag to use the test device tree:: + + => sb devon mmc11 + Device 'mmc11' enabled + => ls mmc b + extlinux/ + 7 initrd.img-6.8.0-53-generic + 1616 vmlinuz-6.8.0-53-generic + + 2 file(s), 1 dir(s) + + => sb devoff mmc11 + Device 'mmc11' disabled + => ls mmc b + ** Bad device specification mmc b ** + Couldn't find partition mmc b + => + This shows checking for the presence of SPL-handoff information. For this to work, ``u-boot-spl`` must be run, with build that enables ``CONFIG_SPL``, such as ``sandbox_spl``:: diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 9cd8ea3aaf0..4d8f93e2551 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_CMD_MBR) += mbr.o obj-$(CONFIG_CMD_PINMUX) += pinmux.o obj-$(CONFIG_CMD_PWM) += pwm.o obj-$(CONFIG_CMD_READ) += rw.o +obj-y += sb.o obj-$(CONFIG_CMD_SETEXPR) += setexpr.o obj-$(CONFIG_CMD_SMBIOS) += smbios.o obj-$(CONFIG_CMD_TEMPERATURE) += temperature.o diff --git a/test/cmd/sb.c b/test/cmd/sb.c new file mode 100644 index 00000000000..cb871dffd57 --- /dev/null +++ b/test/cmd/sb.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for sb command + * + * Copyright (C) 2025 Canonical Ltd + */ + +#include +#include +#include +#include + +/* Basic test of 'sb devon' and 'sb devoff' commands */ +static int dm_test_sb_devon_devoff(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode root, node; + + /* Find the mmc11 device tree node */ + root = oftree_root(oftree_default()); + node = ofnode_find_subnode(root, "mmc11"); + ut_assert(ofnode_valid(node)); + + /* Verify device is not initially bound */ + ut_assert(device_find_global_by_ofnode(node, &dev)); + + /* Enable the device using 'sb devon' */ + ut_assertok(run_command("sb devon mmc11", 0)); + ut_assert_nextline("Device 'mmc11' enabled"); + ut_assert_console_end(); + + /* Verify device is now bound and probed */ + ut_assertok(device_find_global_by_ofnode(node, &dev)); + ut_assertnonnull(dev); + ut_assert(device_active(dev)); + + /* Disable the device using 'sb devoff' */ + ut_assertok(run_command("sb devoff mmc11", 0)); + ut_assert_nextline("Device 'mmc11' disabled"); + ut_assert_console_end(); + + /* Verify device is no longer bound */ + ut_assert(device_find_global_by_ofnode(node, &dev)); + + return 0; +} +DM_TEST(dm_test_sb_devon_devoff, UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test 'sb devon' with invalid node */ +static int dm_test_sb_devon_invalid(struct unit_test_state *uts) +{ + /* Try to enable non-existent device */ + ut_asserteq(1, run_command("sb devon nonexistent", 0)); + ut_assert_nextline("Device tree node 'nonexistent' not found"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_sb_devon_invalid, UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test 'sb devoff' with invalid node */ +static int dm_test_sb_devoff_invalid(struct unit_test_state *uts) +{ + /* Try to disable non-existent device */ + ut_asserteq(1, run_command("sb devoff nonexistent", 0)); + ut_assert_nextline("Device tree node 'nonexistent' not found"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_sb_devoff_invalid, UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test 'sb devon' on device that's already enabled */ +static int dm_test_sb_devon_already_enabled(struct unit_test_state *uts) +{ + /* Enable the device first */ + ut_assertok(run_command("sb devon mmc11", 0)); + ut_assert_nextline("Device 'mmc11' enabled"); + ut_assert_console_end(); + + /* Try to enable it again - should fail */ + ut_asserteq(1, run_command("sb devon mmc11", 0)); + ut_assert_nextline("Device 'mmc11' is already enabled"); + ut_assert_console_end(); + + /* Clean up - disable the device */ + ut_assertok(run_command("sb devoff mmc11", 0)); + ut_assert_nextline("Device 'mmc11' disabled"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_sb_devon_already_enabled, UTF_SCAN_FDT | UTF_CONSOLE); + +/* Test 'sb devoff' on device that's not bound */ +static int dm_test_sb_devoff_not_bound(struct unit_test_state *uts) +{ + struct udevice *dev; + ofnode root, node; + + /* Find the mmc11 device tree node */ + root = oftree_root(oftree_default()); + node = ofnode_find_subnode(root, "mmc11"); + ut_assert(ofnode_valid(node)); + + /* Ensure device is not bound (clean up from any previous test) */ + if (!device_find_global_by_ofnode(node, &dev)) { + ut_assertok(run_command("sb devoff mmc11", 0)); + ut_assert_nextlinen("Device 'mmc11' disabled"); + ut_assert_console_end(); + } + + /* Verify device is not bound */ + ut_assert(device_find_global_by_ofnode(node, &dev)); + + /* Try to disable a device that's not bound */ + ut_asserteq(1, run_command("sb devoff mmc11", 0)); + ut_assert_nextlinen("Device 'mmc11' not found or not bound"); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_sb_devoff_not_bound, UTF_SCAN_FDT | UTF_CONSOLE);