From patchwork Sat Mar 3 14:29:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 881043 X-Patchwork-Delegate: agraf@suse.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gmx.de Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3ztpdz41MCz9sWm for ; Sun, 4 Mar 2018 01:36:55 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 49AECC2207A; Sat, 3 Mar 2018 14:33:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_BLOCKED,RCVD_IN_MSPIKE_H2 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 091BBC2208B; Sat, 3 Mar 2018 14:30:10 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 63356C22079; Sat, 3 Mar 2018 14:29:52 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.15.15]) by lists.denx.de (Postfix) with ESMTPS id 268C2C21FB9 for ; Sat, 3 Mar 2018 14:29:48 +0000 (UTC) Received: from workstation4.fritz.box ([84.118.156.34]) by mail.gmx.com (mrgmx002 [212.227.17.184]) with ESMTPSA (Nemesis) id 0M0y47-1eZ6Pd0iH1-00vBAN; Sat, 03 Mar 2018 15:29:46 +0100 From: Heinrich Schuchardt To: Alexander Graf Date: Sat, 3 Mar 2018 15:29:04 +0100 Message-Id: <20180303142904.24332-12-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.14.2 In-Reply-To: <20180303142904.24332-1-xypron.glpk@gmx.de> References: <20180303142904.24332-1-xypron.glpk@gmx.de> X-Provags-ID: V03:K0:d+3oB96ZXf/42/lZmTF8DAmqxtCqUgj4F1IiFKePuhYTzIH5TMy DYGBovwO1zPL63Xq4mPUT7VsUmZXwVi67NxqMJuyhLWZbS1lm+9IpmeKGTLYFfvjsznFqAi dQBU5GfWWc5hOL5YaR6j0hdpCSVSWjRl2WScTjFuKxIbWKTI0YxueyWv/CukEomQ/s+LyTs D9iJYly12TNfXHHMSjt3w== X-UI-Out-Filterresults: notjunk:1; V01:K0:/jZUaFekpwc=:5CLv1KxypxpzNG9C0eZB+A 7hlNOj+6J+Y90a+Us72Tf7TDEUYdfcuhL9m3zggXxzYAbMFlCZ8d3bMfmOPGNEK+yLfE9+PZN FgjHFylCyj+8pR0AafyIxF0uuZ2xQQ/gqkUZ38alrED4Nb3dHcXd+iIIcdJSBodUazfzEH7o2 Q57mwfvb9v2biMnK6f4mRL6xlPfCRg3h2jGAUBfDdXTbK/+jzB2JyzXtxG41+deiGdhd7DT35 Y3SSsKwcUybNIYmoDy8pwl0f7jRG1StDFcU0cudHp+AhF8i4y60RQq/Dsa8BmrM1HCYbNuqsE SH3UuOb5dGVslcWXPb0NZUCfpm/l+pxVJFU314JZOUVYl4XrCiKSZI1kE2d1SommWrjSA/yVa 74i3lnfV5NKLio2BCfw3aHD7ojJqVhpAkul+pAw57W7/VQji4HmTuHEbn30nHSOof/v0g3l0K Gocv9JGkPlBCaQZWn/lZHr142ROAD5B5EEPiqeT4EKvZ3kXkJ6rjtkwbEvcBbtbYUN0aFDIl/ kc3C9NHbWl2LbqtgaQ9CmrVTjp/jOjccQac/kevB1QMXRsPAt/j6PS6ZS4nDWnxTbOnzC/TaO byCXIh+OXN5jZmNet/bV3FJFGCf7RpNE35HN7V35vL5fG6xByfbqNbdzY5Pa3ytijbJlFWM+Z 2X261ZKgVKMTMTjSpmZqH5InMv/pJy6ZlDSZRCb2aUWvy6AIAxPvzXNmPCwxywtoAp7NL+XV2 qcDVDa3MphgvGFLxBVZcgy/FUPf6/0S5kg4ULSfL8ylHOIz0K+JZKB/scu0QZnoTSh+X7Dim9 jMnk8OzBKIe/aeErIRhhImeeKgnBw== Cc: Yuantian Tang , Priyanka Jain , u-boot@lists.denx.de, Heinrich Schuchardt , Stefan Roese , Hou Zhiqiang Subject: [U-Boot] [PATCH v3 11/11] efi_selftest: check installation of the device tree X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The unit test checks if a device tree is installed. It requires that the 'compatible' property of the root node exists. If available it prints the 'serial-number' property. The serial-number property is derived from the environment variable 'serial#'. This can be used to check if the image_setup_libfdt() function is executed. A Python test is supplied. It sets a value for serial# and checks that the selftest shows this as serial-number. Signed-off-by: Heinrich Schuchardt --- v3 no change v2 new patch --- lib/efi_selftest/Makefile | 1 + lib/efi_selftest/efi_selftest_fdt.c | 188 ++++++++++++++++++++++++++++++++++++ test/py/tests/test_efi_selftest.py | 14 +++ 3 files changed, 203 insertions(+) create mode 100644 lib/efi_selftest/efi_selftest_fdt.c diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index c4bdbdf6c0..88c44840d5 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -19,6 +19,7 @@ efi_selftest_console.o \ efi_selftest_devicepath.o \ efi_selftest_events.o \ efi_selftest_exitbootservices.o \ +efi_selftest_fdt.o \ efi_selftest_gop.o \ efi_selftest_manageprotocols.o \ efi_selftest_snp.o \ diff --git a/lib/efi_selftest/efi_selftest_fdt.c b/lib/efi_selftest/efi_selftest_fdt.c new file mode 100644 index 0000000000..24db0dcf7d --- /dev/null +++ b/lib/efi_selftest/efi_selftest_fdt.c @@ -0,0 +1,188 @@ +/* + * efi_selftest_pos + * + * Copyright (c) 2018 Heinrich Schuchardt + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. + * + * The following services are tested: + * OutputString, TestString, SetAttribute. + */ + +#include +#include + +static struct efi_boot_services *boottime; +static const char *fdt; + +/* This should be sufficent for */ +#define BUFFERSIZE 0x100000 + +static efi_guid_t fdt_guid = EFI_FDT_GUID; + +/* + * Convert FDT value to host endianness. + * + * @val FDT value + * @return converted value + */ +static uint32_t f2h(fdt32_t val) +{ + char *buf = (char *)&val; + char i; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* Swap the bytes */ + i = buf[0]; buf[0] = buf[3]; buf[3] = i; + i = buf[1]; buf[1] = buf[2]; buf[2] = i; +#endif + return *(uint32_t *)buf; +} + +/* + * Return the value of a property of the FDT root node. + * + * @name name of the property + * @return value of the property + */ +static char *get_property(const u16 *property) +{ + struct fdt_header *header = (struct fdt_header *)fdt; + const fdt32_t *pos; + const char *strings; + + if (!header) + return NULL; + + if (f2h(header->magic) != FDT_MAGIC) { + printf("Wrong magic\n"); + return NULL; + } + + pos = (fdt32_t *)(fdt + f2h(header->off_dt_struct)); + strings = fdt + f2h(header->off_dt_strings); + + for (;;) { + switch (f2h(pos[0])) { + case FDT_BEGIN_NODE: { + char *c = (char *)&pos[1]; + size_t i; + + for (i = 0; c[i]; ++i) + ; + pos = &pos[2 + (i >> 2)]; + break; + } + case FDT_PROP: { + struct fdt_property *prop = (struct fdt_property *)pos; + const char *label = &strings[f2h(prop->nameoff)]; + efi_status_t ret; + + /* Check if this is the property to be returned */ + if (!efi_st_strcmp_16_8(property, label)) { + char *str; + efi_uintn_t len = f2h(prop->len); + + if (!len) + return NULL; + /* + * The string might not be 0 terminated. + * It is safer to make a copy. + */ + ret = boottime->allocate_pool( + EFI_LOADER_DATA, len + 1, + (void **)&str); + if (ret != EFI_SUCCESS) { + efi_st_printf("AllocatePool failed\n"); + return NULL; + } + boottime->copy_mem(str, &pos[3], len); + str[len] = 0; + + return str; + } + + pos = &pos[3 + ((f2h(prop->len) + 3) >> 2)]; + break; + } + case FDT_NOP: + pos = &pos[1]; + break; + default: + return NULL; + } + } +} + +/* + * Setup unit test. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + efi_uintn_t i; + + boottime = systable->boottime; + + /* Find configuration tables */ + for (i = 0; i < systable->nr_tables; ++i) { + if (!efi_st_memcmp(&systable->tables[i].guid, &fdt_guid, + sizeof(efi_guid_t))) + fdt = systable->tables[i].table; + } + if (!fdt) { + efi_st_error("Missing device tree\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + char *str; + efi_status_t ret; + + str = get_property(L"compatible"); + if (str) { + efi_st_printf("compatible: %s\n", str); + ret = boottime->free_pool(str); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } else { + efi_st_printf("Missing property 'compatible'\n"); + return EFI_ST_FAILURE; + } + str = get_property(L"serial-number"); + if (str) { + efi_st_printf("serial-number: %s\n", str); + ret = boottime->free_pool(str); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(fdt) = { + .name = "device tree", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .on_request = true, +}; diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py index 66b799bed6..b1ef6bd581 100644 --- a/test/py/tests/test_efi_selftest.py +++ b/test/py/tests/test_efi_selftest.py @@ -24,6 +24,20 @@ def test_efi_selftest(u_boot_console): raise Exception('Reset failed during the EFI selftest') u_boot_console.restart_uboot(); +@pytest.mark.buildconfigspec('cmd_bootefi_selftest') +@pytest.mark.buildconfigspec('of_control') +def test_efi_selftest_device_tree(u_boot_console): + u_boot_console.run_command(cmd='setenv efi_selftest list') + output = u_boot_console.run_command('bootefi selftest') + assert '\'device tree\'' in output + u_boot_console.run_command(cmd='setenv efi_selftest device tree') + u_boot_console.run_command(cmd='setenv -f serial# Testing DT') + u_boot_console.run_command(cmd='bootefi selftest ${fdtcontroladdr}', wait_for_prompt=False) + m = u_boot_console.p.expect(['serial-number: Testing DT', 'U-Boot']) + if m != 0: + raise Exception('Reset failed in \'device tree\' test') + u_boot_console.restart_uboot(); + @pytest.mark.buildconfigspec('cmd_bootefi_selftest') def test_efi_selftest_watchdog_reboot(u_boot_console): u_boot_console.run_command(cmd='setenv efi_selftest list')