From patchwork Thu Jun 6 12:23:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattijs Korpershoek X-Patchwork-Id: 1944621 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=W/spsE5R; dkim-atps=neutral Authentication-Results: legolas.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=patchwork.ozlabs.org) 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 ECDSA (secp384r1)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Vw3SZ6ZzRz20Q5 for ; Thu, 6 Jun 2024 22:25:18 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 491B888489; Thu, 6 Jun 2024 14:24:26 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="W/spsE5R"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CD9568842C; Thu, 6 Jun 2024 14:24:23 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lj1-x233.google.com (mail-lj1-x233.google.com [IPv6:2a00:1450:4864:20::233]) (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 A282B883F4 for ; Thu, 6 Jun 2024 14:24:21 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=mkorpershoek@baylibre.com Received: by mail-lj1-x233.google.com with SMTP id 38308e7fff4ca-2eabd22d404so9726131fa.2 for ; Thu, 06 Jun 2024 05:24:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1717676661; x=1718281461; darn=lists.denx.de; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=eVIHF5iS3zLS6NXvp2oJCFGbfbbDAdd8wrvYCmR32JI=; b=W/spsE5R7j7OuCTeZv3IyMpY+5zUYhSnUwNKcaTGjHE7jYEFxIFu5o1OKpDijmmsX6 M0XCWE1FDZKMFQQ+3YZ/Y5i7FW3iNhbmtFHFxxplCaCRGYc+/vGLtrgrUfkZ42L2a8jl dBUx0AysxeTBlBcFDV6NrI1Ns1ANK6R5FIn48sLE4Y8OsjP7MX9JpAiwnhPnZCxL1K71 dq5945HiaU+LqIqUHC1EkpMG7kRd9IKEeoRqsL/J9+1PGyMWPBYAST2eMZlZU5zuDbcb 3YdBPruQvvY5/SUbQD62bSYA1DP6P4rUMG9aLlOnRcXV8AdeHZUpWcfkCBMtoODde1qH eHyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717676661; x=1718281461; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=eVIHF5iS3zLS6NXvp2oJCFGbfbbDAdd8wrvYCmR32JI=; b=S1FfD1kg+ivZokQAQrRaIZPs2DVQElVzhCZc8Lysyrh0kEViNIU7/JvNFcIE+NGbhZ ZXjLpCsopKgjxJkI4Iy9kT85ch7/YguXuOBL7aHbvBvFEcOBnQ92EQtLrI6VHkYD53JP kyyRvCyOQZwY2lifW1LJpZ+l0AjE5byYwXWLrV1EKZoZdJ4FbCh+8ZzBTDhsdYAGjob2 zS17qS0yz2LanRNnHbybvrmglXy95oaYa0E1mH5aXqvaHzMJJBOzCpyh/z8PamM6NiGA 2l+XXOBIEh1nYd/4cJ7ARBAYiwy+kcp0sNxGM66BFuIIbX8h3gxREydaErEqaIYbssXc XtgA== X-Forwarded-Encrypted: i=1; AJvYcCWePPwhSJQGfQUaozti47apZpSxmJcv1TbGeIlQ1sOpE6Rh8V7iwTNBSwYP9Ntru+gxHDW5q6GrXsWQk8c2URS6phyu6A== X-Gm-Message-State: AOJu0YyPW5/u2B6OzxIIOiQ6PH78hY4OmUeDaqthyOk9FzRPi6uZU5Zk wcNF7A0HEtkX7tlFSxU/AUU6yDvS8vE+QVAHwxIjq1IZtRDp0EWVDcZT1BmjQhE= X-Google-Smtp-Source: AGHT+IEBgRLTZNI8SK62D1WxEsK+h6PHAFmaAs7nU+oGjUT/HZhOAsXcNRR28HImRS/hDnQtQaWcdg== X-Received: by 2002:a2e:7302:0:b0:2e5:8685:8b13 with SMTP id 38308e7fff4ca-2eac79e9d80mr32625151fa.25.1717676660925; Thu, 06 Jun 2024 05:24:20 -0700 (PDT) Received: from groot.home ([2a01:cb19:95ba:5000:d6dd:417f:52ac:335b]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-35ef5d66d01sm1432828f8f.50.2024.06.06.05.24.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Jun 2024 05:24:20 -0700 (PDT) From: Mattijs Korpershoek Date: Thu, 06 Jun 2024 14:23:58 +0200 Subject: [PATCH 6/6] bootstd: Add test for bootmeth_android MIME-Version: 1.0 Message-Id: <20240606-bootmeth-android-v1-6-0c69d4457cc5@baylibre.com> References: <20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com> In-Reply-To: <20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com> To: Simon Glass Cc: Julien Masson , Guillaume La Roque , Dmitrii Merkurev , Roman Stratiienko , Igor Opaniuk , u-boot@lists.denx.de, Mattijs Korpershoek X-Mailer: b4 0.14-dev-d4707 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.8 at phobos.denx.de X-Virus-Status: Clean Add a unit test for testing the Android bootmethod. This requires another mmc image (mmc7) to contain the following partitions: - misc: contains the Bootloader Control Block (BCB) - boot_a: contains a fake generic kernel image - vendor_boot_a: contains a fake vendor_boot image Also add BOOTMETH_ANDROID as a dependency on sandbox so that we can test this with: $ ./test/py/test.py --bd sandbox --build -k test_ut # to build the mmc7.img $ ./test/py/test.py --bd sandbox --build -k bootflow_android Signed-off-by: Mattijs Korpershoek Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 8 +++++ configs/sandbox_defconfig | 2 +- test/boot/bootflow.c | 65 ++++++++++++++++++++++++++++++++++++++-- test/py/tests/test_ut.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 4 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index a012f5c4c9ba..5fb5eac862ec 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -43,6 +43,7 @@ mmc4 = "/mmc4"; mmc5 = "/mmc5"; mmc6 = "/mmc6"; + mmc7 = "/mmc7"; pci0 = &pci0; pci1 = &pci1; pci2 = &pci2; @@ -1129,6 +1130,13 @@ filename = "mmc6.img"; }; + /* This is used for Android tests */ + mmc7 { + status = "disabled"; + compatible = "sandbox,mmc"; + filename = "mmc7.img"; + }; + pch { compatible = "sandbox,pch"; }; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 93b52f2de5cf..bc4398f101a7 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -15,6 +15,7 @@ CONFIG_FIT=y CONFIG_FIT_RSASSA_PSS=y CONFIG_FIT_CIPHER=y CONFIG_FIT_VERBOSE=y +CONFIG_BOOTMETH_ANDROID=y CONFIG_LEGACY_IMAGE_FORMAT=y CONFIG_MEASURED_BOOT=y CONFIG_BOOTSTAGE=y @@ -40,7 +41,6 @@ CONFIG_LOG_MAX_LEVEL=9 CONFIG_LOG_DEFAULT_LEVEL=6 CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_STACKPROTECTOR=y -CONFIG_ANDROID_AB=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y CONFIG_CMD_SMBIOS=y diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 4511cfa7f9bf..934c4dcbad2b 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -27,6 +27,7 @@ DECLARE_GLOBAL_DATA_PTR; +extern U_BOOT_DRIVER(bootmeth_android); extern U_BOOT_DRIVER(bootmeth_cros); extern U_BOOT_DRIVER(bootmeth_2script); @@ -518,12 +519,12 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); * @uts: Unit test state * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid * in the caller until - * @bind_cros: true to bind the ChromiumOS bootmeth + * @bind_cros: true to bind the ChromiumOS and Android bootmeths * @old_orderp: Returns the original bootdev order, which must be restored * Returns 0 on success, -ve on failure */ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, - bool bind_cros, const char ***old_orderp) + bool bind_cros_android, const char ***old_orderp) { static const char *order[] = {"mmc2", "mmc1", NULL, NULL}; struct udevice *dev, *bootstd; @@ -545,12 +546,19 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, "bootmeth_script", 0, ofnode_null(), &dev)); /* Enable the cros bootmeth if needed */ - if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) { + if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) { ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros), "cros", 0, ofnode_null(), &dev)); } + /* Enable the android bootmeths if needed */ + if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) { + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android), + "android", 0, ofnode_null(), &dev)); + } + /* Change the order to include the device */ std = dev_get_priv(bootstd); old_order = std->bootdev_order; @@ -589,6 +597,37 @@ static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, return 0; } +/** + * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other + * distros. Android bootflow might print "ANDROID:*" while scanning + * + * @uts: Unit test state + * @mmc_dev: MMC device to use, e.g. "mmc4" + * Returns 0 on success, -ve on failure + */ +static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev) +{ + struct bootstd_priv *std; + struct udevice *bootstd; + const char **old_order; + + ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan", 0)); + /* Android bootflow might print one or two 'ANDROID:*' logs */ + ut_check_skipline(uts); + ut_check_skipline(uts); + ut_assert_console_end(); + + /* Restore the order used by the device tree */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + std = dev_get_priv(bootstd); + std->bootdev_order = old_order; + + return 0; +} + /** * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian * @@ -1160,3 +1199,23 @@ static int bootflow_cros(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_cros, 0); + +/* Test Android bootmeth */ +static int bootflow_android(struct unit_test_state *uts) +{ + ut_assertok(scan_mmc_android_bootdev(uts, "mmc7")); + ut_assertok(run_command("bootflow list", 0)); + + ut_assert_nextlinen("Showing all"); + ut_assert_nextlinen("Seq"); + ut_assert_nextlinen("---"); + ut_assert_nextlinen(" 0 extlinux"); + ut_assert_nextlinen(" 1 android ready mmc 0 mmc7.bootdev.whole "); + ut_assert_nextlinen("---"); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_android, 0); diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index c169c835e38a..39e1abe02a68 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -423,6 +423,81 @@ def setup_cros_image(cons): return fname +def setup_android_image(cons): + """Create a 20MB disk image with Android partitions""" + Partition = collections.namedtuple('part', 'start,size,name') + parts = {} + disk_data = None + + def set_part_data(partnum, data): + """Set the contents of a disk partition + + This updates disk_data by putting data in the right place + + Args: + partnum (int): Partition number to set + data (bytes): Data for that partition + """ + nonlocal disk_data + + start = parts[partnum].start * sect_size + disk_data = disk_data[:start] + data + disk_data[start + len(data):] + + mmc_dev = 7 + fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) + u_boot_utils.run_and_log(cons, f'cgpt create {fname}') + + ptr = 40 + + # Number of sectors in 1MB + sect_size = 512 + sect_1mb = (1 << 20) // sect_size + + required_parts = [ + {'num': 1, 'label':'misc', 'size': '1M'}, + {'num': 2, 'label':'boot_a', 'size': '4M'}, + {'num': 3, 'label':'boot_b', 'size': '4M'}, + {'num': 4, 'label':'vendor_boot_a', 'size': '4M'}, + {'num': 5, 'label':'vendor_boot_b', 'size': '4M'}, + ] + + for part in required_parts: + size_str = part['size'] + if 'M' in size_str: + size = int(size_str[:-1]) * sect_1mb + else: + size = int(size_str) + u_boot_utils.run_and_log( + cons, + f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}") + ptr += size + + u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}') + out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}') + + # Create a dict (indexed by partition number) containing the above info + for line in out.splitlines(): + start, size, num, name = line.split(maxsplit=3) + parts[int(num)] = Partition(int(start), int(size), name) + + with open(fname, 'rb') as inf: + disk_data = inf.read() + + boot_img = os.path.join(cons.config.result_dir, 'bootv4.img') + with open(boot_img, 'rb') as inf: + set_part_data(2, inf.read()) + + vendor_boot_img = os.path.join(cons.config.result_dir, 'vendor_boot.img') + with open(vendor_boot_img, 'rb') as inf: + set_part_data(4, inf.read()) + + with open(fname, 'wb') as outf: + outf.write(disk_data) + + print('wrote to {}'.format(fname)) + + return fname def setup_cedit_file(cons): infname = os.path.join(cons.config.source_dir, @@ -477,6 +552,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_bootmenu_image(u_boot_console) setup_cedit_file(u_boot_console) setup_cros_image(u_boot_console) + setup_android_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot()