From patchwork Thu Jun 9 12:30:10 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sughosh Ganu X-Patchwork-Id: 580315 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp736789max; Thu, 9 Jun 2022 05:35:28 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzhW71MmWRN3mLOVQEoNNfqTUXbxH26irkUgV+wgeKhs1zg68QP0BlCNLZcrLFYpCObZ4V3 X-Received: by 2002:a05:6638:1509:b0:331:baca:d2bc with SMTP id b9-20020a056638150900b00331bacad2bcmr9853108jat.299.1654778128239; Thu, 09 Jun 2022 05:35:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654778128; cv=none; d=google.com; s=arc-20160816; b=aH95M0UsXwyBBc6pZfPIave3tQxJPINV5DFZJnsbdW6opcZNsNR0ggvDueijV0XNic kYgxFH6z347K9igl5SAJ0dF2MxOEj6/H9rhsQS9N/DwYPXFSYgn/eYhEWO3doo1bu4Tq Lybwu3MuqNekPW2VHjfvQhpJBF0+tgiHw/grM+pqPdOg2aD738kGKVVRS/o7kZVQBaxA EPd0NkBSKcNvNbuZkobcR/am6PsLjCfvftpOvsAAjuNSPgH1yhi6umsMA/NiYgI3UAjW SSZGql+dpUC7gnabxWTBi3wBxq+vm23sEVIIi0Q1nuxTupSPUlQiODsJx9O0Cep5qalC SUow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from; bh=Xiix7pUMO1njL2LYwUJ8LvhQ+m0/qdFrm4V6A1cZgjw=; b=AgEgbHZ4t9+kPreVMKMtjHmzTDcK22BuqfLMb2+DtuTIYg6zStw/OwqprQZj/HA2Wb 2oguwMEhqWyVwQmk26oWreBZlrb04dK5tlMq6hdhyODaRteofQcpqQ715BJWOcj96Pao +jcxoO2MduFH+T241O5luHAXSGW2+PTs1uPRj/KoeOtDHtr5FhrfctUnthUwtncamXQ+ VlXKEdpE38vdxyzt7ULNXahewljnUt0T+3/TBU6X0liOUknn5ASvSmUyyWbiv/7Hsf4m mDa5jBmDUszkO+Bzi1WVSWCjj8sEhXjQPaO4WCWh6GxXuUCwDibX3yyzKp/eb2tdmKBy q8rg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id h8-20020a056638338800b00331fee6c7fbsi2311524jav.141.2022.06.09.05.35.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jun 2022 05:35:28 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6D1E88440A; Thu, 9 Jun 2022 14:33:09 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id BF88A8441B; Thu, 9 Jun 2022 14:32:49 +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.2 required=5.0 tests=BAYES_00,LOTS_OF_MONEY, SPF_HELO_NONE,SPF_SOFTFAIL,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by phobos.denx.de (Postfix) with ESMTP id B6341843D4 for ; Thu, 9 Jun 2022 14:32:27 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=fail smtp.mailfrom=sughosh.ganu@linaro.org Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 37FB8153B; Thu, 9 Jun 2022 05:32:27 -0700 (PDT) Received: from a076522.blr.arm.com (a076522.blr.arm.com [10.162.16.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 739933F766; Thu, 9 Jun 2022 05:32:22 -0700 (PDT) From: Sughosh Ganu To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Takahiro Akashi , Patrick Delaunay , Patrice Chotard , Simon Glass , Bin Meng , Tom Rini , Etienne Carriere , Michal Simek , Jassi Brar , Sughosh Ganu Subject: [PATCH v5 23/23] sandbox: fwu: Add support for testing FWU feature on sandbox Date: Thu, 9 Jun 2022 18:00:10 +0530 Message-Id: <20220609123010.1017463-24-sughosh.ganu@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220609123010.1017463-1-sughosh.ganu@linaro.org> References: <20220609123010.1017463-1-sughosh.ganu@linaro.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.5 at phobos.denx.de X-Virus-Status: Clean Add a python test script for testing the FWU Multi Bank Update functionality on the sandbox platform. The script has test cases for updation of the u-boot binary and the u-boot environment image to the non active bank. The FWU metadata is being stored on the SPI NOR flash, along with the updatable images, and the FWU metadata driver for MTD devices is being used for accessing the metadata. Certain FWU boottime checks are bypassed due to the unavailability of the EFI variable access very early in the boot on the sandbox platform -- the variable access is only available once the block disk image has been bound through the host interface. The FWU Multi Bank feature being enabled on the sandbox64 platform is enabling the RAW Firmware Management Protocol(FMP) instance, therefore the FIT FMP instance is being removed -- the FIT FMP is already being tested on the sandbox flattree variant. Signed-off-by: Sughosh Ganu --- arch/sandbox/Kconfig | 6 + arch/sandbox/dts/test.dts | 45 ++- board/sandbox/sandbox.c | 49 +++ configs/sandbox64_defconfig | 12 +- include/fwu.h | 2 + lib/fwu_updates/Kconfig | 2 +- lib/fwu_updates/fwu.c | 18 +- lib/fwu_updates/fwu_mtd.c | 10 +- .../test_capsule_firmware_fit.py | 1 - .../py/tests/test_fwu_updates/capsule_defs.py | 10 + test/py/tests/test_fwu_updates/conftest.py | 78 ++++ .../test_fwu_updates/test_fwu_updates.py | 367 ++++++++++++++++++ 12 files changed, 587 insertions(+), 13 deletions(-) create mode 100644 test/py/tests/test_fwu_updates/capsule_defs.py create mode 100644 test/py/tests/test_fwu_updates/conftest.py create mode 100644 test/py/tests/test_fwu_updates/test_fwu_updates.py diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 5f55c7f28e..2985572083 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -84,3 +84,9 @@ config SYS_FDT_LOAD_ADDR See `doc/arch/sandbox.rst` for more information. endmenu + +config FWU_NUM_BANKS + default 2 + +config FWU_NUM_IMAGES_PER_BANK + default 2 diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 8f93775ff4..f11fa8733f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1145,11 +1145,48 @@ pinctrl-names = "default"; pinctrl-0 = <&pinmux_spi0_pins>; - spi.bin@0 { + spi0: spi.bin@0 { reg = <0>; compatible = "spansion,m25p16", "jedec,spi-nor"; spi-max-frequency = <40000000>; sandbox,filename = "spi.bin"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + uuid = "af9e8c96-bec5-48be-9dab-3491c04b1366"; + + partition@0 { + label = "Metadata"; + reg = <0x0 0x20000>; + }; + + /* FWU Multi bank update partitions */ + partition@100000 { + label = "U-Boot-Bank0"; + reg = <0x100000 0x10000>; + uuid = "a8f61787-5d68-4c9d-9e4a-37bb0df99da7"; + }; + + partition@120000 { + label = "U-Boot-ENV-Bank0"; + reg = <0x120000 0x10000>; + uuid = "ea9d59af-e0e8-4ef5-9b16-4c80ff67524c"; + }; + + partition@140000 { + label = "U-Boot-Bank1"; + reg = <0x140000 0x10000>; + uuid = "52377abf-c4e4-4d0b-aafd-ba081a500847"; + }; + + partition@160000 { + label = "U-Boot-ENV-Bank1"; + reg = <0x160000 0x10000>; + uuid = "4e01d1fa-eebb-437e-9cfe-e7dfbcd04bb3"; + }; + }; }; spi.bin@1 { reg = <1>; @@ -1633,6 +1670,12 @@ compatible = "sandbox,regmap_test"; }; }; + + fwu-mdata { + compatible = "u-boot,fwu-mdata-mtd"; + fwu-mdata-store = <&spi0>; + mdata-offsets = <0x0 0x10000>; + }; }; #include "sandbox_pmic.dtsi" diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c index e054f300c4..222c36d301 100644 --- a/board/sandbox/sandbox.c +++ b/board/sandbox/sandbox.c @@ -6,13 +6,18 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include +#include #include +#include #include #include #include @@ -51,8 +56,15 @@ struct efi_fw_image fw_images[] = { }; struct efi_capsule_update_info update_info = { +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) + .dfu_string = "mtd nor0=u-boot-bin-a raw 0x100000 0x10000;" + "u-boot-env-a raw 0x120000 0x10000;" + "u-boot-bin-b raw 0x140000 0x10000;" + "u-boot-env-b raw 0x160000 0x10000", +#else .dfu_string = "sf 0:0=u-boot-bin raw 0x100000 0x50000;" "u-boot-env raw 0x150000 0x200000", +#endif .images = fw_images, }; @@ -155,3 +167,40 @@ int board_late_init(void) return 0; } #endif + +#if defined(CONFIG_FWU_MULTI_BANK_UPDATE) +int fwu_plat_get_alt_num(struct udevice __always_unused *dev, + efi_guid_t *image_id, int *alt_num) +{ + return fwu_get_mtd_alt_num(image_id, alt_num, "nor0", 1); +} + +int fwu_plat_get_update_index(u32 *update_idx) +{ + int ret; + u32 active_idx; + + ret = fwu_get_active_index(&active_idx); + + if (ret < 0) + return -1; + + *update_idx = active_idx ^= 0x1; + + return ret; +} + +void fwu_plat_get_bootidx(void *boot_idx) +{ + int ret; + u32 active_idx; + u32 *bootidx = boot_idx; + + ret = fwu_get_active_index(&active_idx); + + if (ret < 0) + *bootidx = -1; + + *bootidx = active_idx; +} +#endif /* CONFIG_FWU_MULTI_BANK_UPDATE */ diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index d7f22b39ae..7a813b46a5 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -244,9 +244,19 @@ CONFIG_LZ4=y CONFIG_ERRNO_STR=y CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y CONFIG_EFI_CAPSULE_ON_DISK=y -CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y CONFIG_EFI_SECURE_BOOT=y CONFIG_TEST_FDTDEC=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y +CONFIG_DM_FWU_MDATA=y +CONFIG_FWU_MULTI_BANK_UPDATE=y +CONFIG_FWU_MDATA_MTD=y +CONFIG_CMD_FWU_METADATA=y +CONFIG_TOOLS_MKFWUMDATA=y +CONFIG_DM_SPI_FLASH=y +CONFIG_CMD_MTD=y +CONFIG_DFU_MTD=y +CONFIG_DM_MTD=y +CONFIG_SPI_FLASH_MTD=y diff --git a/include/fwu.h b/include/fwu.h index fadbfedd07..9e550182eb 100644 --- a/include/fwu.h +++ b/include/fwu.h @@ -8,6 +8,8 @@ #include #include +#include +#include #include diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig index 6de28e0c9c..43bed7729c 100644 --- a/lib/fwu_updates/Kconfig +++ b/lib/fwu_updates/Kconfig @@ -2,7 +2,7 @@ config FWU_MULTI_BANK_UPDATE bool "Enable FWU Multi Bank Update Feature" depends on EFI_HAVE_CAPSULE_SUPPORT select PARTITION_TYPE_GUID - select EFI_SETUP_EARLY + select EFI_SETUP_EARLY if !SANDBOX help Feature for updating firmware images on platforms having multiple banks(copies) of the firmware images. One of the diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c index 422ef58661..f2c10d836b 100644 --- a/lib/fwu_updates/fwu.c +++ b/lib/fwu_updates/fwu.c @@ -185,12 +185,22 @@ int fwu_boottime_checks(void) return 0; } - if (efi_init_obj_list() != EFI_SUCCESS) - return 0; + /* + * On the sandbox platform, the EFI variable + * access is available only after binding the + * disk image with the host interface. Skip + * the Trial State check on sandbox. + */ + if (!IS_ENABLED(CONFIG_SANDBOX)) { + if (efi_init_obj_list() != EFI_SUCCESS) + return 0; - ret = fwu_trial_state_check(); - if (!ret) + ret = fwu_trial_state_check(); + if (!ret) + boottime_check = 1; + } else { boottime_check = 1; + } return 0; } diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index 3137f8635c..3a9ad70203 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -84,11 +84,11 @@ int fwu_get_mtd_alt_num(efi_guid_t *image_id, int *alt_num, int gen_image_alt_info(char *buf, size_t len, int sidx, struct fwu_image_entry *img, struct mtd_info *mtd) { - char *p = buf, *end = buf + len; - char uuidbuf[UUID_STR_LEN + 1]; - ofnode node, parts_node; - const char *suuid; int i; + const char *suuid; + ofnode node, parts_node; + char uuidbuf[UUID_STR_LEN + 1]; + char *p = buf, *end = buf + len; /* Find partition node under given MTD device. */ parts_node = ofnode_by_compatible(mtd_get_ofnode(mtd), @@ -145,7 +145,7 @@ int gen_image_alt_info(char *buf, size_t len, int sidx, int fwu_gen_alt_info_from_mtd(char *buf, size_t len, struct mtd_info *mtd) { - struct fwu_mdata *mdata; + struct fwu_mdata *mdata = NULL; int i, l, ret; ret = fwu_get_mdata(&mdata); diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py b/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py index 5bef84958b..93bc5ed44b 100644 --- a/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py @@ -13,7 +13,6 @@ import pytest from capsule_defs import * -@pytest.mark.boardspec('sandbox64') @pytest.mark.boardspec('sandbox_flattree') @pytest.mark.buildconfigspec('efi_capsule_firmware_fit') @pytest.mark.buildconfigspec('efi_capsule_on_disk') diff --git a/test/py/tests/test_fwu_updates/capsule_defs.py b/test/py/tests/test_fwu_updates/capsule_defs.py new file mode 100644 index 0000000000..59b40f11bd --- /dev/null +++ b/test/py/tests/test_fwu_updates/capsule_defs.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ + +# Directories +CAPSULE_DATA_DIR = '/EFI/CapsuleTestData' +CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule' + +# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and +# you need build a newer version on your own. +# The path must terminate with '/' if it is not null. +EFITOOLS_PATH = '' diff --git a/test/py/tests/test_fwu_updates/conftest.py b/test/py/tests/test_fwu_updates/conftest.py new file mode 100644 index 0000000000..cdf824c3be --- /dev/null +++ b/test/py/tests/test_fwu_updates/conftest.py @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2020, Linaro Limited +# Author: AKASHI Takahiro + +import os +import os.path +import re +from subprocess import call, check_call, check_output, CalledProcessError +import pytest +from capsule_defs import * + +# +# Fixture for UEFI capsule test +# + +@pytest.fixture(scope='session') +def efi_capsule_data(request, u_boot_config): + """Set up a file system to be used in UEFI capsule and + authentication test. + + Args: + request: Pytest request object. + u_boot_config: U-boot configuration. + + Return: + A path to disk image to be used for testing + """ + global CAPSULE_DATA_DIR, CAPSULE_INSTALL_DIR + + mnt_point = u_boot_config.persistent_data_dir + '/test_efi_capsule' + data_dir = mnt_point + CAPSULE_DATA_DIR + install_dir = mnt_point + CAPSULE_INSTALL_DIR + image_path = u_boot_config.persistent_data_dir + '/test_efi_capsule.img' + + try: + # Create a target device + check_call('dd if=/dev/zero of=./spi.bin bs=1MiB count=16', shell=True) + + check_call('rm -rf %s' % mnt_point, shell=True) + check_call('mkdir -p %s' % data_dir, shell=True) + check_call('mkdir -p %s' % install_dir, shell=True) + + # Create capsule files + # two regions: one for u-boot.bin and the other for u-boot.env + check_call('cd %s; echo -n u-boot-a:Old > u-boot-a.bin.old; echo -n u-boot-env-a:Old > u-boot-env-a.old; echo -n u-boot-a:New > u-boot-a.bin.new; echo -n u-boot-env-a:New > u-boot-env-a.new; echo -n u-boot-b:Old > u-boot-b.bin.old; echo -n u-boot-env-b:Old > u-boot-env-b.old; echo -n u-boot-b:New > u-boot-b.bin.new; echo -n u-boot-env-b:New > u-boot-env-b.new;' % data_dir, + shell=True) + check_call('cd %s; %s/tools/mkfwumdata -i 2 -b 2 -a 0 -g af9e8c96-bec5-48be-9dab-3491c04b1366,09D7CF52-0720-4710-91D1-08469B7FE9C8,a8f61787-5d68-4c9d-9e4a-37bb0df99da7,52377abf-c4e4-4d0b-aafd-ba081a500847 af9e8c96-bec5-48be-9dab-3491c04b1366,5A7021F5-FEF2-48B4-AABA-832E777418C0,ea9d59af-e0e8-4ef5-9b16-4c80ff67524c,4e01d1fa-eebb-437e-9cfe-e7dfbcd04bb3 metadata_bank0.bin' %(data_dir, u_boot_config.build_dir), shell=True) + check_call('cd %s; %s/tools/mkfwumdata -i 2 -b 2 -a 1 -g af9e8c96-bec5-48be-9dab-3491c04b1366,09D7CF52-0720-4710-91D1-08469B7FE9C8,a8f61787-5d68-4c9d-9e4a-37bb0df99da7,52377abf-c4e4-4d0b-aafd-ba081a500847 af9e8c96-bec5-48be-9dab-3491c04b1366,5A7021F5-FEF2-48B4-AABA-832E777418C0,ea9d59af-e0e8-4ef5-9b16-4c80ff67524c,4e01d1fa-eebb-437e-9cfe-e7dfbcd04bb3 metadata_bank1.bin' %(data_dir, u_boot_config.build_dir), shell=True) + + check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot-b.bin.new Test01' % + (data_dir, u_boot_config.build_dir), + shell=True) + check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot-env-b.new Test02' % + (data_dir, u_boot_config.build_dir), + shell=True) + + check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 09D7CF52-0720-4710-91D1-08469B7FE9C8 u-boot-a.bin.new Test03' % + (data_dir, u_boot_config.build_dir), + shell=True) + check_call('cd %s; %s/tools/mkeficapsule --index 1 --guid 5A7021F5-FEF2-48B4-AABA-832E777418C0 u-boot-env-a.new Test04' % + (data_dir, u_boot_config.build_dir), + shell=True) + + # Create a disk image with EFI system partition + check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' % + (mnt_point, image_path), shell=True) + check_call('sgdisk %s -A 1:set:0 -t 1:C12A7328-F81F-11D2-BA4B-00A0C93EC93B' % + image_path, shell=True) + + except CalledProcessError as exception: + pytest.skip('Setup failed: %s' % exception.cmd) + return + else: + yield image_path + finally: + call('rm -rf %s' % mnt_point, shell=True) + call('rm -f %s' % image_path, shell=True) + call('rm -f ./spi.bin', shell=True) diff --git a/test/py/tests/test_fwu_updates/test_fwu_updates.py b/test/py/tests/test_fwu_updates/test_fwu_updates.py new file mode 100644 index 0000000000..d9dff3afaf --- /dev/null +++ b/test/py/tests/test_fwu_updates/test_fwu_updates.py @@ -0,0 +1,367 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2022, Linaro Limited +# +# FWU Multi Bank Firmware Update Test + +""" +This test verifies FWU Multi Bank firmware update for raw images +""" + +from subprocess import check_call, check_output, CalledProcessError +import pytest +from capsule_defs import * + + +@pytest.mark.boardspec('sandbox64') +@pytest.mark.buildconfigspec('efi_capsule_firmware_raw') +@pytest.mark.buildconfigspec('efi_capsule_on_disk') +@pytest.mark.buildconfigspec('dfu') +@pytest.mark.buildconfigspec('dfu_sf') +@pytest.mark.buildconfigspec('cmd_efidebug') +@pytest.mark.buildconfigspec('cmd_fat') +@pytest.mark.buildconfigspec('cmd_memory') +@pytest.mark.buildconfigspec('cmd_nvedit_efi') +@pytest.mark.buildconfigspec('cmd_sf') +@pytest.mark.buildconfigspec('fwu_multi_bank_update') +@pytest.mark.buildconfigspec('dm_fwu_mdata') +@pytest.mark.buildconfigspec('fwu_mdata_mtd') +@pytest.mark.slow +class TestEfiCapsuleFirmwareRaw(object): + def test_fwu_updates_fw1( + self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 1 - Update U-Boot Bank 1 binary on SPI Flash + 0x100000-0x150000: U-Boot binary Bank 0 (but dummy) + 0x150000-0x200000: U-Boot binary Bank 1 (but dummy) + """ + + # other tests might have run and the + # system might not be in a clean state. + # Restart before starting the tests. + u_boot_console.restart_uboot() + + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 1-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi -s ""', + 'efidebug boot order 1', + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', + 'env save']) + + # initialize contents + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot-a.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 100000 10', + 'fatload host 0:1 4000000 %s/u-boot-b.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 140000 10']) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 100000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5100000 140000 10', + 'md.b 5100000 10' + ]) + assert 'u-boot-b:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/metadata_bank0.bin' % CAPSULE_DATA_DIR, + 'sf write 4000000 0 $filesize', + 'sf write 4000000 10000 $filesize']) + + output = u_boot_console.run_command( + 'fwu_mdata_read') + assert 'active_index: 0x0' in ''.join(output) + assert 'previous_active_index: 0x1' in ''.join(output) + + # place a capsule file + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + # reboot + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 1-b, after reboot'): + # make sure that dfu_alt_info exists even persistent variables + # are not available. + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + + # need to run uefi command to initiate capsule handling + output = u_boot_console.run_command( + 'efidebug capsule disk-update', wait_for_reboot = True) + + output = u_boot_console.run_command( + 'fwu_mdata_read') + assert 'active_index: 0x1' in ''.join(output) + assert 'previous_active_index: 0x0' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 100000 10', + 'md.b 4000000 10']) + assert 'u-boot-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 140000 10', + 'md.b 4000000 10']) + assert 'u-boot-b:New' in ''.join(output) + + def test_fwu_updates_fw2( + self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 2 - Update U-Boot and U-Boot Env Bank 1 binary on SPI Flash + 0x100000-0x110000: U-Boot binary Bank 0 (but dummy) + 0x120000-0x130000: U-Boot Env binary Bank 0 (but dummy) + 0x140000-0x150000: U-Boot binary Bank 1 (but dummy) + 0x160000-0x170000: U-Boot Env binary Bank 1 (but dummy) + """ + + # other tests might have run and the + # system might not be in a clean state. + # Restart before starting the tests. + u_boot_console.restart_uboot() + + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 2-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi -s ""', + 'efidebug boot order 1', + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', + 'env save']) + + # initialize contents + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot-a.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 100000 10', + 'fatload host 0:1 4000000 %s/u-boot-env-a.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 120000 10', + 'fatload host 0:1 4000000 %s/u-boot-b.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 140000 10', + 'fatload host 0:1 4000000 %s/u-boot-env-b.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 160000 10']) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 100000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 120000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-env-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5100000 140000 10', + 'md.b 5100000 10' + ]) + assert 'u-boot-b:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 160000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-env-b:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/metadata_bank0.bin' % CAPSULE_DATA_DIR, + 'sf write 4000000 0 100', + 'sf write 4000000 10000 100']) + + output = u_boot_console.run_command( + 'fwu_mdata_read') + assert 'active_index: 0x0' in ''.join(output) + assert 'previous_active_index: 0x1' in ''.join(output) + + # place a capsule file + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 %s/Test01' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test01 $filesize' % CAPSULE_INSTALL_DIR, + 'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + assert 'Test02' in ''.join(output) + + # reboot + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 2-b, after reboot'): + # make sure that dfu_alt_info exists even persistent variables + # are not available. + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test01' in ''.join(output) + assert 'Test02' in ''.join(output) + + # need to run uefi command to initiate capsule handling + output = u_boot_console.run_command( + 'efidebug capsule disk-update', wait_for_reboot = True) + + output = u_boot_console.run_command( + 'fwu_mdata_read') + assert 'active_index: 0x1' in ''.join(output) + assert 'previous_active_index: 0x0' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 100000 10', + 'md.b 4000000 10']) + assert 'u-boot-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 120000 10', + 'md.b 4000000 10']) + assert 'u-boot-env-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 140000 10', + 'md.b 4000000 10']) + assert 'u-boot-b:New' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 160000 10', + 'md.b 4000000 10']) + assert 'u-boot-env-b:New' in ''.join(output) + + def test_fwu_updates_fw3( + self, u_boot_config, u_boot_console, efi_capsule_data): + """ + Test Case 3 - Update U-Boot and U-Boot Env Bank 0 binary on SPI Flash + 0x100000-0x110000: U-Boot binary Bank 0 (but dummy) + 0x120000-0x130000: U-Boot Env binary Bank 0 (but dummy) + 0x140000-0x150000: U-Boot binary Bank 1 (but dummy) + 0x160000-0x170000: U-Boot Env binary Bank 1 (but dummy) + """ + + # other tests might have run and the + # system might not be in a clean state. + # Restart before starting the tests. + u_boot_console.restart_uboot() + + disk_img = efi_capsule_data + with u_boot_console.log.section('Test Case 3-a, before reboot'): + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi -s ""', + 'efidebug boot order 1', + 'env set -e -nv -bs -rt OsIndications =0x0000000000000004', + 'env save']) + + # initialize contents + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/u-boot-a.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 100000 10', + 'fatload host 0:1 4000000 %s/u-boot-env-a.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 120000 10', + 'fatload host 0:1 4000000 %s/u-boot-b.bin.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 140000 10', + 'fatload host 0:1 4000000 %s/u-boot-env-b.old' % CAPSULE_DATA_DIR, + 'sf write 4000000 160000 10']) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 100000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 120000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-env-a:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5100000 140000 10', + 'md.b 5100000 10' + ]) + assert 'u-boot-b:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 5000000 160000 10', + 'md.b 5000000 10' + ]) + assert 'u-boot-env-b:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'fatload host 0:1 4000000 %s/metadata_bank1.bin' % CAPSULE_DATA_DIR, + 'sf write 4000000 0 100', + 'sf write 4000000 10000 100']) + + output = u_boot_console.run_command( + 'fwu_mdata_read') + assert 'active_index: 0x1' in ''.join(output) + assert 'previous_active_index: 0x0' in ''.join(output) + + # place a capsule file + output = u_boot_console.run_command_list([ + 'fatload host 0:1 4000000 %s/Test03' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test03 $filesize' % CAPSULE_INSTALL_DIR, + 'fatload host 0:1 4000000 %s/Test04' % CAPSULE_DATA_DIR, + 'fatwrite host 0:1 4000000 %s/Test04 $filesize' % CAPSULE_INSTALL_DIR, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test03' in ''.join(output) + assert 'Test04' in ''.join(output) + + # reboot + u_boot_console.restart_uboot() + + with u_boot_console.log.section('Test Case 3-b, after reboot'): + # make sure that dfu_alt_info exists even persistent variables + # are not available. + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR]) + assert 'Test03' in ''.join(output) + assert 'Test04' in ''.join(output) + + # need to run uefi command to initiate capsule handling + output = u_boot_console.run_command( + 'efidebug capsule disk-update', wait_for_reboot = True) + + output = u_boot_console.run_command( + 'fwu_mdata_read') + assert 'active_index: 0x0' in ''.join(output) + assert 'previous_active_index: 0x1' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 100000 10', + 'md.b 4000000 10']) + assert 'u-boot-a:New' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf probe 0:0', + 'sf read 4000000 120000 10', + 'md.b 4000000 10']) + assert 'u-boot-env-a:New' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 140000 10', + 'md.b 4000000 10']) + assert 'u-boot-b:Old' in ''.join(output) + + output = u_boot_console.run_command_list([ + 'sf read 4000000 160000 10', + 'md.b 4000000 10']) + assert 'u-boot-env-b:Old' in ''.join(output)