From patchwork Mon Apr 10 09:07:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 1767122 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org 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=) Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=AKZxglh3; 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 ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Pw34y1jsrz1yZC for ; Mon, 10 Apr 2023 19:06:58 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 34A9F82160; Mon, 10 Apr 2023 11:06:47 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org 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=linaro.org header.i=@linaro.org header.b="AKZxglh3"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id D52DC850DB; Mon, 10 Apr 2023 11:06:36 +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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) (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 5A66F82160 for ; Mon, 10 Apr 2023 11:06:33 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=masahisa.kojima@linaro.org Received: by mail-pl1-x635.google.com with SMTP id o2so4152914plg.4 for ; Mon, 10 Apr 2023 02:06:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1681117591; x=1683709591; h=references:in-reply-to:message-id:date:subject:cc:to:from:from:to :cc:subject:date:message-id:reply-to; bh=nYK+0kicbkNfPxAK91H5Y4Ki7NxoPhVLEX+uFEt+/70=; b=AKZxglh3J3O8Ceh+WrofvsAUaMkVTZCs+VnTRfynI2yH0hvbOVTCtWiHAgFk5IZ8u5 yRCAmmiNrxvgM4KvfC0IvFnbHMuDl6VY+lEpS6KhZIqgzNplNGMNCotod3IUsl31bRJU B6A7X9vBQJ6fbXigRgf/ks2+U+61wsCTOvBHwtbIWkB/Iof4GAl16ztRTI6ibl3whhOS r7+oOf+hbzvdbngO1OujLnlsgUmUr4SAyA8yWagOUYrIGQSBY0KslSKa1mDrjZDBArDz 9GSD3hYgnj+vQPHxAG1ZtQYOvn/II5SI224RDWZWdxKe08Wal+rhrzO3vt2kZMKmjnno ifxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1681117591; x=1683709591; h=references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=nYK+0kicbkNfPxAK91H5Y4Ki7NxoPhVLEX+uFEt+/70=; b=l/AfCdwUU73x/dyfA32qvd0qqDgQNrkP6IgkFUZ8wHmVAWfPN/KlKmnr/YH9Oy5nY3 ECiNZplhe5p+pSselYMqzGht5x3SkmpOJgfbQXT3PH35PZwfx/pk68t7SiH4ItW3NK1C wljLGmp4VBt86dbQS+29dTG+jzaKy8zz7tLeuP5RNN2pHLP0f12rqBZ9TsH1vz7EXcUR 4oPh4GF6cVrL8aGT9+fP3FOXuKXrs6/AZ4VGp58zBtb+qfkiq5hR3iH1P5h6FM4K4UtF o+HXXEzCNwSOy24aodzu8vY6LvGlJ/AwOnp1amtr4ZmAgHNMXmF/McSC6Jam79OE5/cZ ShYw== X-Gm-Message-State: AAQBX9cECuZj9SKyUiXy/U4wit+adzzdU1IL/94OcxMDx86bBKbyUCTb y2mSz2Te2+fz+UUNmDn+Ls73LSuY42KWhAyjLUM= X-Google-Smtp-Source: AKy350ZogdWwJka60yldqXkziUdkylp+aNn9RYV2x1GVEmvTsKTm/5ZK+K1JX9lpzVqkYsjnvHKNZg== X-Received: by 2002:a17:90b:1bd1:b0:23c:fef0:d441 with SMTP id oa17-20020a17090b1bd100b0023cfef0d441mr12578430pjb.33.1681117591447; Mon, 10 Apr 2023 02:06:31 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id s15-20020a17090a5d0f00b0023f8bdc4a7fsm7189279pji.14.2023.04.10.02.06.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Apr 2023 02:06:30 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Takahiro Akashi , Masahisa Kojima Subject: [PATCH v5 2/4] efi_loader: check lowest supported version Date: Mon, 10 Apr 2023 18:07:30 +0900 Message-Id: <20230410090732.1676-3-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230410090732.1676-1-masahisa.kojima@linaro.org> References: <20230410090732.1676-1-masahisa.kojima@linaro.org> 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 The FMP Payload Header which EDK II capsule generation scripts insert has a firmware version. This commit reads the lowest supported version stored in the device tree, then check if the firmware version in FMP payload header of the ongoing capsule is equal or greater than the lowest supported version. If the firmware version is lower than lowest supported version, capsule update fails. Signed-off-by: Masahisa Kojima --- Changes in v5: - newly implement the device tree based versioning Changes in v4: - use log_err() instead of printf() Changes in v2: - add error message when the firmware version is lower than lowest supported version lib/efi_loader/efi_firmware.c | 124 ++++++++++++++++++++++++++++------ 1 file changed, 103 insertions(+), 21 deletions(-) diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 1c6ef468bf..c88c1bb364 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -33,7 +33,7 @@ struct fmp_payload_header { u32 signature; u32 header_size; u32 fw_version; - u32 lowest_supported_version; + u32 lowest_supported_version; /* not used */ }; __weak void set_dfu_alt_info(char *interface, char *devstr) @@ -250,8 +250,6 @@ efi_status_t efi_firmware_capsule_authenticate(const void **p_image, { const void *image = *p_image; efi_uintn_t image_size = *p_image_size; - u32 fmp_hdr_signature; - struct fmp_payload_header *header; void *capsule_payload; efi_status_t status; efi_uintn_t capsule_payload_size; @@ -264,7 +262,7 @@ efi_status_t efi_firmware_capsule_authenticate(const void **p_image, &capsule_payload_size); if (status == EFI_SECURITY_VIOLATION) { - printf("Capsule authentication check failed. Aborting update\n"); + log_err("Capsule authentication check failed. Aborting update\n"); return status; } else if (status != EFI_SUCCESS) { return status; @@ -278,21 +276,6 @@ efi_status_t efi_firmware_capsule_authenticate(const void **p_image, debug("Updating capsule without authenticating.\n"); } - fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE; - header = (void *)image; - - if (!memcmp(&header->signature, &fmp_hdr_signature, - sizeof(fmp_hdr_signature))) { - /* - * When building the capsule with the scripts in - * edk2, a FMP header is inserted above the capsule - * payload. Compensate for this header to get the - * actual payload that is to be updated. - */ - image += header->header_size; - image_size -= header->header_size; - } - *p_image = image; *p_image_size = image_size; return EFI_SUCCESS; @@ -349,6 +332,105 @@ efi_status_t EFIAPI efi_firmware_get_image_info( return EFI_EXIT(ret); } +/** + * efi_firmware_get_image_type_id - get image_type_id + * @image_index: image index + * + * Return the image_type_id identified by the image index. + * + * Return: pointer to the image_type_id, NULL if image_index is invalid + */ +static +efi_guid_t *efi_firmware_get_image_type_id(u8 image_index) +{ + int i; + struct efi_fw_image *fw_array; + + fw_array = update_info.images; + for (i = 0; i < num_image_type_guids; i++) { + if (fw_array[i].image_index == image_index) + return &fw_array[i].image_type_id; + } + + return NULL; +} + +/** + * efi_firmware_check_lowest_supported_version - check the lowest supported version + * @p_image: Pointer to new image + * @p_image_size: Pointer to size of new image + * @image_index: image_index + * + * Check the fw_version in FMP payload header is equal to or greather than the + * lowest_supported_version stored in the device tree + * + * Return: status code + */ +static +efi_status_t efi_firmware_check_lowest_supported_version(const void **p_image, + efi_uintn_t *p_image_size, + u8 image_index) +{ + const void *image = *p_image; + efi_uintn_t image_size = *p_image_size; + const struct fmp_payload_header *header; + u32 fmp_hdr_signature = FMP_PAYLOAD_HDR_SIGNATURE; + + /* FMP header is inserted above the capsule payload */ + header = image; + if (header->signature == fmp_hdr_signature) { + efi_guid_t *image_type_id; + u32 version = 0, lsv = 0; + + image_type_id = efi_firmware_get_image_type_id(image_index); + if (!image_type_id) + return EFI_INVALID_PARAMETER; + + efi_firmware_get_firmware_version(image_index, image_type_id, + &version, &lsv); + + if (header->fw_version >= lsv) { + image += header->header_size; + image_size -= header->header_size; + } else { + log_err("Firmware version %u too low. Expecting >= %u. Aborting update\n", + header->fw_version, lsv); + return EFI_INCOMPATIBLE_VERSION; + } + } + + *p_image = image; + *p_image_size = image_size; + + return EFI_SUCCESS; +} + +/** + * efi_firmware_verify_image - verify image + * @p_image: Pointer to new image + * @p_image_size: Pointer to size of new image + * @image_index Image index + * + * Verify the capsule file + * + * Return: status code + */ +static +efi_status_t efi_firmware_verify_image(const void **p_image, + efi_uintn_t *p_image_size, + u8 image_index) +{ + efi_status_t ret; + + ret = efi_firmware_capsule_authenticate(p_image, p_image_size); + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_firmware_check_lowest_supported_version(p_image, p_image_size, image_index); + + return ret; +} + #ifdef CONFIG_EFI_CAPSULE_FIRMWARE_FIT /* * This FIRMWARE_MANAGEMENT_PROTOCOL driver provides a firmware update @@ -393,7 +475,7 @@ efi_status_t EFIAPI efi_firmware_fit_set_image( if (!image || image_index != 1) return EFI_EXIT(EFI_INVALID_PARAMETER); - status = efi_firmware_capsule_authenticate(&image, &image_size); + status = efi_firmware_verify_image(&image, &image_size, image_index); if (status != EFI_SUCCESS) return EFI_EXIT(status); @@ -454,7 +536,7 @@ efi_status_t EFIAPI efi_firmware_raw_set_image( if (!image) return EFI_EXIT(EFI_INVALID_PARAMETER); - status = efi_firmware_capsule_authenticate(&image, &image_size); + status = efi_firmware_verify_image(&image, &image_size, image_index); if (status != EFI_SUCCESS) return EFI_EXIT(status);