From patchwork Wed Oct 4 11:27:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sughosh Ganu X-Patchwork-Id: 729282 Delivered-To: patch@linaro.org Received: by 2002:a5d:4a4e:0:b0:31d:da82:a3b4 with SMTP id v14csp287546wrs; Wed, 4 Oct 2023 04:28:14 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGbmnlolVCf9BAmpStp23HlBiAPVVRSlwDrNajVk0e1R1PP000GzpdsmKgOEuHxhAUys5Y6 X-Received: by 2002:adf:edce:0:b0:317:58e4:e941 with SMTP id v14-20020adfedce000000b0031758e4e941mr1799373wro.33.1696418894067; Wed, 04 Oct 2023 04:28:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696418894; cv=none; d=google.com; s=arc-20160816; b=BxghFEA/vJ74BIqR+brGiyAQMPiVhRn9mssgKzRjCiGjG1klgSaSdbo4UmBIGvjAnp NfHbfkn8CffEoCaLBV0mAYm+K7dZw8RX1+5rLE8LklGmnxXr5HR2SB/ywszzLYSMgN4n I7F1uHmLP5v7VFr5lKNwXFNe5i9SRYTwwhVEx0Cl19Xz8OO0lXVPQ3prOJfq4zODjRmu bSUGAgqj2gVZEITZtH5LNTgr87qVum+XjKDKO1i1BlnWnsiZz4qz/4ok33EJW7XEcK/T Gf2FJ6yVwYeICF5vefp5GaG2xwpxeG5zzOXQuSq+PoWUk8Yw8NsQghCxTImGnVeu5NXa bLbQ== 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=tvZ6SER34TCdNuQ+6gvylOQ/rzG4hYuuNVJ/5/wR63E=; fh=GFi6yKGMx/0zdTg+7jHYbY+NaEzlEBFVO9Bq4SjQnp0=; b=c11r81XIH+25vhA/JXDbA+NEvAuWuuc2+lnsiPi/000yTN2iZDtteRB6NGYfPvXSKE S375BiG9kPiASqN0GoysxlnkbUnwxN/Rk1rXsIzAkqfx3JKHRkTWCiNYJIaDGmUQmJZQ k/3ZXTLXnXr9bCEDYIAkrR0Xt+eqnXQgV7gXdkGO59oU/qkgebnVdxacCXJh2voxa4NE uQAzlyzvXV0Qj1Lin1P4pnADbFkgRyU6cPkSwPcP1Ncncwl3wv6iUyjE8LA4OZFxEkG4 p1E9JgouSn9VJARD+w05GGxtzMFLouHMXITtmOYIHTdDa0/dzTVAv28N2kjMBPceBl64 vc9g== 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 t1-20020adfe441000000b0032610479700si1819645wrm.853.2023.10.04.04.28.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Oct 2023 04:28:14 -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 ABA7F874BD; Wed, 4 Oct 2023 13:27:53 +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 CDE12874C8; Wed, 4 Oct 2023 13:27:46 +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,SPF_HELO_NONE, SPF_SOFTFAIL 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 CC283874D4 for ; Wed, 4 Oct 2023 13:27:43 +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 C7564DA7; Wed, 4 Oct 2023 04:28:21 -0700 (PDT) Received: from a079122.blr.arm.com (a079122.arm.com [10.162.17.48]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 930B33F762; Wed, 4 Oct 2023 04:27:40 -0700 (PDT) From: Sughosh Ganu To: u-boot@lists.denx.de Cc: Simon Glass , Heinrich Schuchardt , Ilias Apalodimas , Takahiro Akashi , Tom Rini , Sughosh Ganu Subject: [PATCH 1/5] tools: mkeficapsule: Add support to print capsule headers Date: Wed, 4 Oct 2023 16:57:18 +0530 Message-Id: <20231004112722.416877-2-sughosh.ganu@linaro.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231004112722.416877-1-sughosh.ganu@linaro.org> References: <20231004112722.416877-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.8 at phobos.denx.de X-Virus-Status: Clean Add support to dump the contents of capsule headers. This is useful as a debug feature for checking the contents of the capsule headers, and can also be used in capsule verification. Signed-off-by: Sughosh Ganu Reviewed-by: Simon Glass --- tools/eficapsule.h | 2 + tools/mkeficapsule.c | 229 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 230 insertions(+), 1 deletion(-) diff --git a/tools/eficapsule.h b/tools/eficapsule.h index 2099a2e9b8..6efd07d2eb 100644 --- a/tools/eficapsule.h +++ b/tools/eficapsule.h @@ -22,6 +22,8 @@ #define __aligned(x) __attribute__((__aligned__(x))) #endif +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + typedef struct { uint8_t b[16]; } efi_guid_t __aligned(8); diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 52be1f122e..28126e018b 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -29,7 +29,7 @@ static const char *tool_name = "mkeficapsule"; efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; -static const char *opts_short = "g:i:I:v:p:c:m:o:dhAR"; +static const char *opts_short = "g:i:I:v:p:c:m:o:dhARD"; enum { CAPSULE_NORMAL_BLOB = 0, @@ -49,6 +49,7 @@ static struct option options[] = { {"fw-accept", no_argument, NULL, 'A'}, {"fw-revert", no_argument, NULL, 'R'}, {"capoemflag", required_argument, NULL, 'o'}, + {"dump-capsule", no_argument, NULL, 'D'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0}, }; @@ -69,6 +70,7 @@ static void print_usage(void) "\t-A, --fw-accept firmware accept capsule, requires GUID, no image blob\n" "\t-R, --fw-revert firmware revert capsule, takes no GUID, no image blob\n" "\t-o, --capoemflag Capsule OEM Flag, an integer between 0x0000 and 0xffff\n" + "\t-D, --dump-capsule dump the contents of the capsule headers\n" "\t-h, --help print a help message\n", tool_name); } @@ -647,6 +649,217 @@ err: return ret; } +static void print_guid(void *ptr) +{ + int i; + efi_guid_t *guid = ptr; + const uint8_t seq[] = { + 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, + '-', 8, 9, '-', 10, 11, 12, 13, 14, 15 }; + + for (i = 0; i < ARRAY_SIZE(seq); i++) { + if (seq[i] == '-') + putchar(seq[i]); + else + printf("%02X", guid->b[seq[i]]); + } + + printf("\n"); +} + +static uint32_t dump_fmp_payload_header( + struct fmp_payload_header *fmp_payload_hdr) +{ + uint32_t hdr_size = 0; + + if (fmp_payload_hdr->signature == FMP_PAYLOAD_HDR_SIGNATURE) { + printf("--------\n"); + printf("FMP_PAYLOAD_HDR.SIGNATURE\t\t\t: %08X\n", + FMP_PAYLOAD_HDR_SIGNATURE); + printf("FMP_PAYLOAD_HDR.HEADER_SIZE\t\t\t: %08X\n", + fmp_payload_hdr->header_size); + printf("FMP_PAYLOAD_HDR.FW_VERSION\t\t\t: %08X\n", + fmp_payload_hdr->fw_version); + printf("FMP_PAYLOAD_HDR.LOWEST_SUPPORTED_VERSION\t: %08X\n", + fmp_payload_hdr->lowest_supported_version); + hdr_size = fmp_payload_hdr->header_size; + } + + return hdr_size; +} + +static void dump_capsule_auth_header( + struct efi_firmware_image_authentication *capsule_auth_hdr) +{ + printf("EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT\t\t: %08lX\n", + capsule_auth_hdr->monotonic_count); + printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.dwLENGTH\t: %08X\n", + capsule_auth_hdr->auth_info.hdr.dwLength); + printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wREVISION\t: %08X\n", + capsule_auth_hdr->auth_info.hdr.wRevision); + printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.HDR.wCERTTYPE\t: %08X\n", + capsule_auth_hdr->auth_info.hdr.wCertificateType); + printf("EFI_FIRMWARE_IMAGE_AUTH.AUTH_INFO.CERT_TYPE\t: "); + print_guid(&capsule_auth_hdr->auth_info.cert_type); +} + +static void dump_fmp_capsule_image_header( + struct efi_firmware_management_capsule_image_header *image_hdr) +{ + void *capsule_auth_hdr; + void *fmp_payload_hdr; + uint64_t signature_size = 0; + uint32_t payload_size = 0; + uint32_t fmp_payload_hdr_size = 0; + struct efi_firmware_image_authentication *auth_hdr; + + printf("--------\n"); + printf("FMP_CAPSULE_IMAGE_HDR.VERSION\t\t\t: %08X\n", + image_hdr->version); + printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID\t: "); + print_guid(&image_hdr->update_image_type_id); + printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_INDEX\t: %08X\n", + image_hdr->update_image_index); + printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_SIZE\t\t: %08X\n", + image_hdr->update_image_size); + printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_VENDOR_CODE_SIZE\t: %08X\n", + image_hdr->update_vendor_code_size); + printf("FMP_CAPSULE_IMAGE_HDR.UPDATE_HARDWARE_INSTANCE\t: %08lX\n", + image_hdr->update_hardware_instance); + printf("FMP_CAPSULE_IMAGE_HDR.IMAGE_CAPSULE_SUPPORT\t: %08lX\n", + image_hdr->image_capsule_support); + + printf("--------\n"); + if (image_hdr->image_capsule_support & CAPSULE_SUPPORT_AUTHENTICATION) { + capsule_auth_hdr = (char *)image_hdr + sizeof(*image_hdr); + dump_capsule_auth_header(capsule_auth_hdr); + + auth_hdr = capsule_auth_hdr; + signature_size = sizeof(auth_hdr->monotonic_count) + + auth_hdr->auth_info.hdr.dwLength; + fmp_payload_hdr = (char *)capsule_auth_hdr + signature_size; + } else { + printf("Capsule Authentication Not Enabled\n"); + fmp_payload_hdr = (char *)image_hdr + sizeof(*image_hdr); + } + + fmp_payload_hdr_size = dump_fmp_payload_header(fmp_payload_hdr); + + payload_size = image_hdr->update_image_size - signature_size - + fmp_payload_hdr_size; + printf("--------\n"); + printf("Payload Image Size\t\t\t\t: %08X\n", payload_size); +} + +static void dump_fmp_header( + struct efi_firmware_management_capsule_header *fmp_hdr) +{ + int i; + void *capsule_image_hdr; + + printf("EFI_FMP_HDR.VERSION\t\t\t\t: %08X\n", fmp_hdr->version); + printf("EFI_FMP_HDR.EMBEDDED_DRIVER_COUNT\t\t: %08X\n", + fmp_hdr->embedded_driver_count); + printf("EFI_FMP_HDR.PAYLOAD_ITEM_COUNT\t\t\t: %08X\n", + fmp_hdr->payload_item_count); + + /* + * We currently don't support Embedded Drivers. + * Only worry about the payload items. + */ + for (i = 0; i < fmp_hdr->payload_item_count; i++) { + capsule_image_hdr = (char *)fmp_hdr + + fmp_hdr->item_offset_list[i]; + dump_fmp_capsule_image_header(capsule_image_hdr); + } +} + +static void dump_capsule_header(struct efi_capsule_header *capsule_hdr) +{ + printf("EFI_CAPSULE_HDR.CAPSULE_GUID\t\t\t: "); + print_guid((void *)&capsule_hdr->capsule_guid); + printf("EFI_CAPSULE_HDR.HEADER_SIZE\t\t\t: %08X\n", + capsule_hdr->header_size); + printf("EFI_CAPSULE_HDR.FLAGS\t\t\t\t: %08X\n", capsule_hdr->flags); + printf("EFI_CAPSULE_HDR.CAPSULE_IMAGE_SIZE\t\t: %08X\n", + capsule_hdr->capsule_image_size); +} + +static void normal_capsule_dump(void *capsule_buf) +{ + void *fmp_hdr; + struct efi_capsule_header *hdr = capsule_buf; + + dump_capsule_header(hdr); + printf("--------\n"); + + fmp_hdr = (char *)capsule_buf + sizeof(*hdr); + dump_fmp_header(fmp_hdr); +} + +static void empty_capsule_dump(void *capsule_buf) +{ + efi_guid_t *accept_image_guid; + struct efi_capsule_header *hdr = capsule_buf; + efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID; + + dump_capsule_header(hdr); + + if (!memcmp(&efi_empty_accept_capsule, &hdr->capsule_guid, + sizeof(efi_guid_t))) { + accept_image_guid = (void *)(char *)capsule_buf + + sizeof(struct efi_capsule_header); + printf("--------\n"); + printf("ACCEPT_IMAGE_GUID\t\t\t\t: "); + print_guid(accept_image_guid); + } +} + +static void dump_capsule_contents(char *capsule_file) +{ + int fd; + char *ptr; + efi_guid_t efi_fmp_guid = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID; + efi_guid_t efi_empty_accept_capsule = FW_ACCEPT_OS_GUID; + efi_guid_t efi_empty_revert_capsule = FW_REVERT_OS_GUID; + struct stat sbuf; + + if (!capsule_file) { + fprintf(stderr, "No capsule file provided\n"); + exit(EXIT_FAILURE); + } + + if ((fd = open(capsule_file, O_RDONLY)) < 0) { + fprintf(stderr, "Error opening capsule file: %s\n", + capsule_file); + exit(EXIT_FAILURE); + } + + if (fstat(fd, &sbuf) < 0) { + fprintf(stderr, "Can't stat capsule file: %s\n", capsule_file); + exit(EXIT_FAILURE); + } + + if ((ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) + == MAP_FAILED) { + fprintf(stderr, "Can't mmap capsule file: %s\n", capsule_file); + exit(EXIT_FAILURE); + } + + if (!memcmp(&efi_fmp_guid, ptr, sizeof(efi_guid_t))) { + normal_capsule_dump(ptr); + } else if (!memcmp(&efi_empty_accept_capsule, ptr, + sizeof(efi_guid_t)) || + !memcmp(&efi_empty_revert_capsule, ptr, + sizeof(efi_guid_t))) { + empty_capsule_dump(ptr); + } else { + fprintf(stderr, "Unable to decode the capsule file: %s\n", + capsule_file); + exit(EXIT_FAILURE); + } +} + /** * main - main entry function of mkeficapsule * @argc: Number of arguments @@ -666,6 +879,7 @@ int main(int argc, char **argv) unsigned long index, instance; uint64_t mcount; unsigned long oemflags; + bool capsule_dump; char *privkey_file, *cert_file; int c, idx; struct fmp_payload_header_params fmp_ph_params = { 0 }; @@ -676,6 +890,7 @@ int main(int argc, char **argv) mcount = 0; privkey_file = NULL; cert_file = NULL; + capsule_dump = false; dump_sig = 0; capsule_type = CAPSULE_NORMAL_BLOB; oemflags = 0; @@ -754,12 +969,24 @@ int main(int argc, char **argv) exit(1); } break; + case 'D': + capsule_dump = true; + break; default: print_usage(); exit(EXIT_SUCCESS); } } + if (capsule_dump) { + if (argc != optind + 1) { + fprintf(stderr, "Must provide the capsule file to parse\n"); + exit(EXIT_FAILURE); + } + dump_capsule_contents(argv[argc - 1]); + exit(EXIT_SUCCESS); + } + /* check necessary parameters */ if ((capsule_type == CAPSULE_NORMAL_BLOB && ((argc != optind + 2) || !guid ||