From patchwork Fri Jan 24 15:53:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sam Protsenko X-Patchwork-Id: 1228879 X-Patchwork-Delegate: lokeshvutla@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=mnQcwKYb; dkim-atps=neutral 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 ozlabs.org (Postfix) with ESMTPS id 4843cl2YVlz9sRW for ; Sat, 25 Jan 2020 02:55:03 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 49C6081853; Fri, 24 Jan 2020 16:54:24 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="mnQcwKYb"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9A82C81812; Fri, 24 Jan 2020 16:54:05 +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=-0.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-lj1-x244.google.com (mail-lj1-x244.google.com [IPv6:2a00:1450:4864:20::244]) (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 EA45381813 for ; Fri, 24 Jan 2020 16:54:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=joe.skb7@gmail.com Received: by mail-lj1-x244.google.com with SMTP id a13so2987193ljm.10 for ; Fri, 24 Jan 2020 07:54:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Vl5EUJ7acGy7+YheOX1vs+T2L9itJiIJt/fCLAC5ttk=; b=mnQcwKYbZWMI+spcBJp+DD6GFgg8PjCPhCvR0cSI0m6Yh+HR7q6ujsrCT5rluLITTT O4YeDVENhYMondrglb7mbhnUnPOfa6lcsgPZRsfpdbig41tEJ7wxTg3xZbil8QDTg6pB 5oudXhDWIpFS86v0H5fL8y78pQcniOb/mrlSmk8k+QFEH2sF3DbrkgmHty6wfwnMYNiM OBUJbMOU39sNxIy6fAUteTKkUMjUeXbQb7vKJuMPnbi1y8XU8q5WfOq5UlVrgKi9SwWm NtDzJrrLz7g7+0q7N05UhPXMQ35jfPd32scGlzY92CbjiyA3WLMAmDmhuiFw5oVhRtl0 WuHA== 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=Vl5EUJ7acGy7+YheOX1vs+T2L9itJiIJt/fCLAC5ttk=; b=PVDv+MZiJPsocUdHwOaGE62JaVElk04rsdh2RJdv141ATlgVe7RIzF6YIUhyGVP6sC igRqMpzjzg4AoOTQvPzGH0HY5Uf4w7EunPxtHHUbmMUGfX4dSTPgzeyY3lZTRjZaFqJK lrVf7gckNa9T31HpXx4jBAI/WLZiC9KXJJDE1zY6sZTkUdHGW18ymoPa2y+cFo8Hmwac rtfnRtZHr+k49VeM/GQNjJ2/GlN7nO051HF4e0Ybsr6UK6Ck+v7XZZCb3vG5+tJF1JOe oBZMq7tE32CLaCatYUx7d0pn/laOgTWbRaOk8Tq27I5TqcCW7gplAYfaopmyyCj5IH1P kkMg== X-Gm-Message-State: APjAAAWKpieXhz9YG3VoaVqtURcjqoSJYWIkGaEW3TALE58zKd17dUA6 mHG/f8d18gen+AToZsLmAVb3ySNn03w= X-Google-Smtp-Source: APXvYqx8gS0HPPEVAohpColNhffHF0TZDUZ/rSFLh9Cdhud1ZVaCkCxDYBRUyU3DpskDPnk9Xe2Zag== X-Received: by 2002:a2e:b4f6:: with SMTP id s22mr2503358ljm.218.1579881239976; Fri, 24 Jan 2020 07:53:59 -0800 (PST) Received: from localhost ([2001:67c:2e5c:2011:2e0:4cff:fe68:2882]) by smtp.gmail.com with ESMTPSA id a28sm2933696lfg.86.2020.01.24.07.53.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jan 2020 07:53:59 -0800 (PST) From: Sam Protsenko To: u-boot@lists.denx.de Subject: [PATCH v4 06/10] test/py: android: Add test for abootimg Date: Fri, 24 Jan 2020 17:53:45 +0200 Message-Id: <20200124155349.12927-7-joe.skb7@gmail.com> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20200124155349.12927-1-joe.skb7@gmail.com> References: <20200124155349.12927-1-joe.skb7@gmail.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.26 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tom Rini , Roman Stratiienko , Eugeniu Rosca , Praneeth Bajjuri , Heinrich Schuchardt , Alistair Strachan Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.101.4 at phobos.denx.de X-Virus-Status: Clean Unit test for 'abootimg' command. Right now it covers dtb/dtbo functionality in Android Boot Image v2, which was added recently. Running test: $ ./test/py/test.py --bd sandbox --build -k test_abootimg shows that 1/1 tests passes successfully. Signed-off-by: Sam Protsenko --- configs/sandbox_defconfig | 1 + test/py/tests/test_android/test_abootimg.py | 159 ++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 test/py/tests/test_android/test_abootimg.py diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index fc018bdd2c..790dcb0592 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -25,6 +25,7 @@ CONFIG_ANDROID_AB=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y CONFIG_CMD_BOOTZ=y +CONFIG_CMD_ABOOTIMG=y # CONFIG_CMD_ELF is not set CONFIG_CMD_ASKENV=y CONFIG_CMD_GREPENV=y diff --git a/test/py/tests/test_android/test_abootimg.py b/test/py/tests/test_android/test_abootimg.py new file mode 100644 index 0000000000..43a7099c46 --- /dev/null +++ b/test/py/tests/test_android/test_abootimg.py @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020 +# Author: Sam Protsenko + +# Test U-Boot's "abootimg" commands. + +import os +import pytest +import u_boot_utils + +""" +These tests rely on disk image (boot.img), which is automatically created by +the test from the stored hex dump. This is done to avoid the dependency on the +most recent mkbootimg tool from AOSP/master. Here is the list of commands which +was used to generate the boot.img and obtain compressed hex dump from it: + + $ echo '/dts-v1/; / { model = "x1"; compatible = "y1,z1"; };' > test1.dts + $ echo '/dts-v1/; / { model = "x2"; compatible = "y2,z2"; };' > test2.dts + $ dtc test1.dts > dt1.dtb + $ dtc test2.dts > dt2.dtb + $ cat dt1.dtb dt2.dtb > dtb.img + $ echo 'kernel payload' > kernel + $ echo 'ramdisk payload' > ramdisk.img + $ mkbootimg --kernel ./kernel --ramdisk ./ramdisk.img \ + --cmdline "cmdline test" --dtb ./dtb.img \ + --os_version R --os_patch_level 2019-06-05 \ + --header_version 2 --output boot.img + $ gzip -9 boot.img + $ xxd -p boot.img.gz > boot.img.gz.hex + +Now one can obtain original boot.img from this hex dump like this: + + $ xxd -r -p boot.img.gz.hex boot.img.gz + $ gunzip -9 boot.img.gz +""" + +# boot.img.gz hex dump +img_hex = """1f8b08084844af5d0203626f6f742e696d670073f47309f2f77451e46700 +820606010106301084501f04181819041838181898803c3346060c909c9b +92939997aa50925a5cc2300a461c3078b2e1793c4b876fd92db97939fb6c +b7762ffff07d345446c1281805e8a0868d81e117a45e111c0d8dc101b253 +8bf25273140a122b73f21353b8460364148c8251300a46c1281801a02831 +3725b3387bb401300a46c1281805a360148c207081f7df5b20550bc41640 +9c03c41a0c90f17fe85400986d82452b6c3680198a192a0ce17c3610ae34 +d4a9820881a70f3873f35352731892f3730b124b32937252a96bb9119ae5 +463a5546f82c1f05a360148c8251300a462e000085bf67f200200000""" +# Expected response for "abootimg dtb_dump" command +dtb_dump_resp="""## DTB area contents (concat format): + - DTB #0: + (DTB)size = 125 + (DTB)model = x1 + (DTB)compatible = y1,z1 + - DTB #1: + (DTB)size = 125 + (DTB)model = x2 + (DTB)compatible = y2,z2""" +# Address in RAM where to load the boot image ('abootimg' looks in $loadaddr) +loadaddr = 0x1000 +# Expected DTB #1 offset from the boot image start address +dtb1_offset = 0x187d +# DTB #1 start address in RAM +dtb1_addr = loadaddr + dtb1_offset + +class AbootimgTestDiskImage(object): + """Disk image used by abootimg tests.""" + + def __init__(self, u_boot_console): + """Initialize a new AbootimgDiskImage object. + + Args: + u_boot_console: A U-Boot console. + + Returns: + Nothing. + """ + + gz_hex = u_boot_console.config.persistent_data_dir + '/boot.img.gz.hex' + gz = u_boot_console.config.persistent_data_dir + '/boot.img.gz' + + filename = 'boot.img' + persistent = u_boot_console.config.persistent_data_dir + '/' + filename + self.path = u_boot_console.config.result_dir + '/' + filename + + with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent): + if os.path.exists(persistent): + u_boot_console.log.action('Disk image file ' + persistent + + ' already exists') + else: + u_boot_console.log.action('Generating ' + persistent) + + f = open(gz_hex, "w") + f.write(img_hex) + f.close() + + cmd = ('xxd', '-r', '-p', gz_hex, gz) + u_boot_utils.run_and_log(u_boot_console, cmd) + + cmd = ('gunzip', '-9', gz) + u_boot_utils.run_and_log(u_boot_console, cmd) + + cmd = ('cp', persistent, self.path) + u_boot_utils.run_and_log(u_boot_console, cmd) + +gtdi = None +@pytest.fixture(scope='function') +def abootimg_disk_image(u_boot_console): + """pytest fixture to provide a AbootimgTestDiskImage object to tests. + This is function-scoped because it uses u_boot_console, which is also + function-scoped. However, we don't need to actually do any function-scope + work, so this simply returns the same object over and over each time.""" + + global gtdi + if not gtdi: + gtdi = AbootimgTestDiskImage(u_boot_console) + return gtdi + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('android_boot_image') +@pytest.mark.buildconfigspec('cmd_abootimg') +@pytest.mark.buildconfigspec('cmd_fdt') +@pytest.mark.requiredtool('xxd') +@pytest.mark.requiredtool('gunzip') +def test_abootimg(abootimg_disk_image, u_boot_console): + """Test the 'abootimg' command.""" + + u_boot_console.log.action('Loading disk image to RAM...') + u_boot_console.run_command('setenv loadaddr 0x%x' % (loadaddr)) + u_boot_console.run_command('host load hostfs - 0x%x %s' % (loadaddr, + abootimg_disk_image.path)) + + u_boot_console.log.action('Testing \'abootimg get ver\'...') + response = u_boot_console.run_command('abootimg get ver') + assert response == "2" + u_boot_console.run_command('abootimg get ver v') + response = u_boot_console.run_command('env print v') + assert response == 'v=2' + + u_boot_console.log.action('Testing \'abootimg get recovery_dtbo\'...') + response = u_boot_console.run_command('abootimg get recovery_dtbo a') + assert response == 'Error: recovery_dtbo_size is 0' + + u_boot_console.log.action('Testing \'abootimg dump dtb\'...') + response = u_boot_console.run_command('abootimg dump dtb').replace('\r', '') + assert response == dtb_dump_resp + + u_boot_console.log.action('Testing \'abootimg get dtb_load_addr\'...') + u_boot_console.run_command('abootimg get dtb_load_addr a') + response = u_boot_console.run_command('env print a') + assert response == 'a=11f00000' + + u_boot_console.log.action('Testing \'abootimg get dtb --index\'...') + u_boot_console.run_command('abootimg get dtb --index=1 dtb1_start') + response = u_boot_console.run_command('env print dtb1_start') + correct_str = "dtb1_start=%x" % (dtb1_addr) + assert response == correct_str + u_boot_console.run_command('fdt addr $dtb1_start') + u_boot_console.run_command('fdt get value v / model') + response = u_boot_console.run_command('env print v') + assert response == 'v=x2'