From patchwork Wed Mar 17 19:54:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 403218 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp777402jai; Wed, 17 Mar 2021 12:55:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzRAWV0jJXpfhMaZ6QY7KGCRbIBwmHCLRTNd6kjJAyoD3eDx6PCSCJJ/5VWNQBuEpzQWtQ4 X-Received: by 2002:a17:906:2504:: with SMTP id i4mr37906486ejb.115.1616010926919; Wed, 17 Mar 2021 12:55:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616010926; cv=none; d=google.com; s=arc-20160816; b=l0kHooxuvMGWRg5//Sy/1Dua8RCe195cAI/iM/ReqIivpmGI4VOLPe6uH9xetX7Icx rOAYKkP9q+VR06897+I8pAdxFZWtL2uq1DSTFSAgWrgjV9zbQYLnvV1N3DgRzmCIFL6j 4fnvhFFgk6BF3e0Gsp1sPu6KXXEhYZgOIL9LCDdCu/O9yHbVGPw+8gscyDpUVuwkjx8C kDkDuraNKIly8byJ5ufEL9zoGw+lOMNkwkgesO+9Wu0/5akz+zczktxNf5+S/5IdiEAu SuLrAQmoWwy8xL8aklHBkF6lZMP4k9fiuZ0PPh4B6GrDiplzT/sZHxJQYEViXfapcTJp x+xg== 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:dkim-signature; bh=PvZ6Jt8wgAXlsiDa/9CswidFx8bAWTuh0kBKbg5M6Q8=; b=F6xWzCu8Q8Aoq7S8SscDdWfcpdBuDF3CkKf/uSnOtv5CHvyUltuyfOv6LfcwupAOaq zkTXkTClixc+43EYD5LH07LUAjGNZNH0HOGFPbBMw24QrAhboVch3jEzgu6mH0m8zOvr 8JukknIsj7tYZd85LeV/YQdZOzbRq1Ir9CpbQyDcWBDcZgrDugQvnTLupPKqNOT0OFMb B6f3vUBkXBxAOATll0IZ/yBHnwblfs/VylNML9gGeTjlkQK5id2yIaR8ABwjfKPRn/xf W8iLG+iYj1J6FWQnRozSUEE55J/VH4tZyxCBCYFJjbPK3z1ErKwV6XqDOL2rhAtZRF1g ojEA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZSj4GZDA; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id q2si14966641ejx.352.2021.03.17.12.55.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:26 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZSj4GZDA; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (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 740738232D; Wed, 17 Mar 2021 20:55:19 +0100 (CET) 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="ZSj4GZDA"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 61F5E8232D; Wed, 17 Mar 2021 20:55:16 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) (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 0F9BA80040 for ; Wed, 17 Mar 2021 20:55:13 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wr1-x42b.google.com with SMTP id x13so3086134wrs.9 for ; Wed, 17 Mar 2021 12:55:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PvZ6Jt8wgAXlsiDa/9CswidFx8bAWTuh0kBKbg5M6Q8=; b=ZSj4GZDArCh3aKjGZXsjAd1LjbeAY7M08s0cohvD3gkuCkSbNxVU2I2Vy6C2nezhQ1 4bFAhKgFuLSat5c/WaC2lD2WNIJ/5F4eIUfAll6Ct0wMnkmEXEp6lq7hvGgJxEmNcN94 gE6qX2BBchc+ljVXGdryxrU1dKmztms5KcTmRv4OZ9s3mMbZLGLBx/AkGL4OlMef2l/x fVgHchvz9xrtdTHflCETyZO2XWMU3HdOSH3DKXsPH6Gcjy4bd6B1Angps8TfC29C/msh qwhTwsg1hMEu0a8MRDJ9rO/DrKkOi+gwO9qw70cKfxW/3KC05/xC8IQX0X8YIM0CvNks uBDQ== 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=PvZ6Jt8wgAXlsiDa/9CswidFx8bAWTuh0kBKbg5M6Q8=; b=q/l2OFX67Ff+Lre0v5bNRvX2sxNZGU65i6hooxAsmxs31NTCN8nAHsmpjY963Ts0gS T6EpBmID5kPRDE6kt0M7/8ZP8lRXsJH33vj0XJ6Yfs0Q/SMXcF+2OrrE+jq1mFCiTwTY 3Cw0th6MASBbfUd/v5CN1Jh3eGtRo+/hQUb/xyT1fwRiXkgDSrS8bKwnluqkPOWMegyn v0tPyqD0nZaQ6As27ndn2lV+EzRsHY92gRvAtfbjQypxCYTh5cjAX/27KlTgb3E1tdwM doatlPOFPhYE4YYvbzqODGW9lOHjd31ZKvlQUMeRz6T/jDCI/mnP3cgVaDWFnUZeD63F FGCA== X-Gm-Message-State: AOAM533LwFWoC+LkFmyRiGtrouJp9R6p0QwwUWAvLA8v5L7qfTS7bKsy pXv/XdSh87US0AcwjGbGzOSRd862sCCtPG6t X-Received: by 2002:adf:fb42:: with SMTP id c2mr6096128wrs.83.1616010912650; Wed, 17 Mar 2021 12:55:12 -0700 (PDT) Received: from localhost.localdomain (ppp-94-64-113-158.home.otenet.gr. [94.64.113.158]) by smtp.gmail.com with ESMTPSA id z82sm3343853wmg.19.2021.03.17.12.55.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:12 -0700 (PDT) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, Ilias Apalodimas , Alexander Graf , Sughosh Ganu , u-boot@lists.denx.de Subject: [PATCH 1/5 v4] efi_loader: Add device path related functions for initrd via Boot#### Date: Wed, 17 Mar 2021 21:54:58 +0200 Message-Id: <20210317195505.337105-2-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210317195505.337105-1-ilias.apalodimas@linaro.org> References: <20210317195505.337105-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.4 at phobos.denx.de X-Virus-Status: Clean On the following patches we allow for an initrd path to be stored in Boot#### variables. Specifically we encode in the FIlePathList[] of the EFI_LOAD_OPTIONS for each Boot#### variable. The FilePathList[] array looks like this: kernel - 0xff - VenMedia(initrd GUID) - initrd1 - 0x01 initrd2 - 0xff So let's add the relevant functions to concatenate and retrieve a device path based on a Vendor GUID. Signed-off-by: Ilias Apalodimas --- include/efi_loader.h | 4 ++ lib/efi_loader/efi_device_path.c | 106 +++++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 5 deletions(-) -- 2.31.0 Reviewed-by: Heinrich Schuchardt diff --git a/include/efi_loader.h b/include/efi_loader.h index 68daa1a4a9dc..5d534e69bb59 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -744,6 +744,10 @@ struct efi_load_option { const u8 *optional_data; }; +struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, + efi_uintn_t *size, efi_guid_t guid); +struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, + const struct efi_device_path *dp2); efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data, efi_uintn_t *size); unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index c9315dd45857..1491251e224b 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -282,11 +282,30 @@ struct efi_device_path *efi_dp_dup(const struct efi_device_path *dp) return ndp; } -struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, - const struct efi_device_path *dp2) +/** efi_dp_append_or_concatenate() - Append or concatenate two device paths. + * Concatenated device path will be separated + * by a sub-type 0xff end node + * + * @dp1: First device path + * @dp2: Second device path + * @concat: If true the two device paths will be concatenated and separated + * by an end of entrire device path sub-type 0xff end node. + * If true the second device path will be appended to the first and + * terminated by an end node + * + * Return: concatenated device path or NULL. Caller must free the returned + * value + */ +static struct +efi_device_path *efi_dp_append_or_concatenate(const struct efi_device_path *dp1, + const struct efi_device_path *dp2, + bool concat) { struct efi_device_path *ret; + size_t end_size = sizeof(END); + if (concat) + end_size = 2 * sizeof(END); if (!dp1 && !dp2) { /* return an end node */ ret = efi_dp_dup(&END); @@ -298,18 +317,56 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, /* both dp1 and dp2 are non-null */ unsigned sz1 = efi_dp_size(dp1); unsigned sz2 = efi_dp_size(dp2); - void *p = dp_alloc(sz1 + sz2 + sizeof(END)); + void *p = dp_alloc(sz1 + sz2 + end_size); if (!p) return NULL; + ret = p; memcpy(p, dp1, sz1); + p += sz1; + + if (concat) { + memcpy(p, &END, sizeof(END)); + p += sizeof(END); + } + /* the end node of the second device path has to be retained */ - memcpy(p + sz1, dp2, sz2 + sizeof(END)); - ret = p; + memcpy(p, dp2, sz2); + p += sz2; + memcpy(p, &END, sizeof(END)); } return ret; } +/** efi_dp_append() - Append a device to an existing device path. + * + * @dp1: First device path + * @dp2: Second device path + * + * Return: concatenated device path or NULL. Caller must free the returned + * value + */ +struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1, + const struct efi_device_path *dp2) +{ + return efi_dp_append_or_concatenate(dp1, dp2, false); +} + +/** efi_dp_concat() - Concatenate 2 device paths. The final device path will + * contain two device paths separated by and end node (0xff). + * + * @dp1: First device path + * @dp2: Second device path + * + * Return: concatenated device path or NULL. Caller must free the returned + * value + */ +struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1, + const struct efi_device_path *dp2) +{ + return efi_dp_append_or_concatenate(dp1, dp2, true); +} + struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, const struct efi_device_path *node) { @@ -1160,3 +1217,42 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp, dp = (const struct efi_device_path *)((const u8 *)dp + len); } } + +/** + * efi_dp_from_lo() - Get the instance of a VenMedia node in a + * multi-instance device path that matches + * a specific GUID. This kind of device paths + * is found in Boot#### options describing an + * initrd location + * + * @load_option: EFI_LOAD_OPTION containing a valid device path + * @size: size of the discovered device path + * @guid: guid to search for + * + * Return: device path including the VenMedia node or NULL. + * Caller must free the returned value + */ +struct +efi_device_path *efi_dp_from_lo(struct efi_load_option *lo, + efi_uintn_t *size, efi_guid_t guid) +{ + struct efi_device_path *fp = lo->file_path; + struct efi_device_path_vendor *vendor; + int lo_len = lo->file_path_length; + + for (; lo_len >= sizeof(struct efi_device_path); + lo_len -= fp->length, fp = (void *)fp + fp->length) { + if (lo_len < 0 || efi_dp_check_length(fp, lo_len) < 0) + break; + if (fp->type != DEVICE_PATH_TYPE_MEDIA_DEVICE || + fp->sub_type != DEVICE_PATH_SUB_TYPE_VENDOR_PATH) + continue; + + vendor = (struct efi_device_path_vendor *)fp; + if (!guidcmp(&vendor->guid, &guid)) + return efi_dp_dup(fp); + } + log_debug("VenMedia(%pUl) not found in %ls\n", &guid, lo->label); + + return NULL; +} From patchwork Wed Mar 17 19:54:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 403219 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp777492jai; Wed, 17 Mar 2021 12:55:38 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwCc5QFfWFKfhRaD+XNQih6dhc7gynl9bt9pBBNwodYIjNdIC1Yni4WCSkgRal6hDuKwRHq X-Received: by 2002:a17:906:2c44:: with SMTP id f4mr35997268ejh.508.1616010938177; Wed, 17 Mar 2021 12:55:38 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616010938; cv=none; d=google.com; s=arc-20160816; b=caL73gjE9nNvouXfN7eLnyitF3PD/jIvOsXPsW6/vrCi+CDVlc7PQ0agPCnMR9NNU2 xuPGEVZQvDUrFleW+EPU3yNIh8geu36toLFMtgPyzb1jDDCzvRgWCinZtO3mML30ozMO NYf3iqGmaylhzqIi1v3+xtbgxekrD4JyStIMtdeyX6/1KJHVm6oDFFk4fLHjqXAHkSum Obvje8Tj1hMZzCNuOrCsoJej8JcQ5fyXaSqLrbb6QOz7oPxKxlLIwDomEPt8ehLpWSrL j4o8jpO0xR0hEVJXKoO9tbpSJJ+xCskOMVlRgFRL+VRR5EJEwyKhlnZaWK5OOa5xnzQv dtZg== 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:dkim-signature; bh=VmtQUQMKXOL62uUuonj/OqOi3MylaZv7lYHULieqI3Y=; b=G3Fr6i0xzWt6nWovvW+wKrfeNolX2CPmqSO+UUzAf4RKQLghGeie8ADLIX3o5dkr/5 mbzAtqHv8kK5ari/4aAKOVEyxAWIuP2Fgxf3qiGY4yToYy/06lGep1TCCvl/rP3N6Y79 6Wxeje4NFZ1qG3v8VD6KMnHxIVD49iV53lsJ3c7YEPzCMYBVMHaKcoR4BVy49B5VZUql JWe7GDhkLWGPsq4sHPxWJfM/ojpMYKDPIn8wC/gvc4To0kgCUwbGhfAk9guTZ9O3w0wT R7rQXFd7cIWDJFh/C+DTJRQ4u2TWwijtPfsZyT+zEzDVHwk+ztnXK6bdcowNQxx6Mbdd 7gOw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OxCdOsYC; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id m22si16517223ejr.463.2021.03.17.12.55.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:38 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=OxCdOsYC; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (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 7589E827AB; Wed, 17 Mar 2021 20:55:24 +0100 (CET) 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="OxCdOsYC"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1FF39827A8; Wed, 17 Mar 2021 20:55:21 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) (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 16E6C80040 for ; Wed, 17 Mar 2021 20:55:17 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wr1-x42b.google.com with SMTP id v11so3079248wro.7 for ; Wed, 17 Mar 2021 12:55:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VmtQUQMKXOL62uUuonj/OqOi3MylaZv7lYHULieqI3Y=; b=OxCdOsYCNQlWAHw44Wkphg+K++BZHmB/xfocJyPIYsfFvxyLnKBHlepYVOzCOcVAOP N1cHBqNi4aaBSLnWrHdJ9b30ZV6EDFUs5aSJz45idLZdP/uwyYb6KdKhCjy0JmmlRSrY s7pTM3D8AQXeisWpBQunE8fqSaewcwVe6GgNEtePhX62DVHKf5dpvlPToCuXqDvAd9kf EwCNkw/Rc3yMsbeAVQfFREaLUTbu+ujc2BM84Ie80Kfve5mJW05Fq1MtBvm6+X1ZYTko 7F5lICOA46UeD2bWOZxUpYfO73PvOkreTJBl4avMWtbYI5Dl4drxiX4ExuK/CQNesh+D YzVA== 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=VmtQUQMKXOL62uUuonj/OqOi3MylaZv7lYHULieqI3Y=; b=j8Gl6Adih0mTqUooJUIMPZecxO55m/JmJPj/XABaYAhZNfYcqC8un1YL7ajQtSnOqh WmhLg+rjM7nLy5Owip1FH0YqB4wxKMHe6qA9b7Jdj736nKrJjs9O5QpwvRAmnsrV7IN9 PEEf0mfHPJZU1NalwzHYma/csfgtLT/FuKXmvLJduzB+nTOVzf5tJf8A42Vl0vCsKDKc mNuah2SHBA6d4ee0GsyZV9gLzz288ebGJ1CUeyvrJJcwmC8KGi7k0WVhHdyx4BReIB1J NWgUIMfN+HK0nPSqZfVdEStJA3A7MlfHqJA2hQZFAKyxLZrvaIm8BXKNAHFWeda0K1bD Yi4g== X-Gm-Message-State: AOAM531x9Xc7TWR7NzSqoXnsGo0y9KsbvJoW41Y+XwzQ547kxHXDW6z6 EN5fk7RYtar52IsPFD11PMxvog== X-Received: by 2002:a5d:6945:: with SMTP id r5mr5936804wrw.367.1616010916693; Wed, 17 Mar 2021 12:55:16 -0700 (PDT) Received: from localhost.localdomain (ppp-94-64-113-158.home.otenet.gr. [94.64.113.158]) by smtp.gmail.com with ESMTPSA id z82sm3343853wmg.19.2021.03.17.12.55.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:16 -0700 (PDT) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, Ilias Apalodimas , Alexander Graf , Sughosh Ganu , u-boot@lists.denx.de Subject: [PATCH 2/5 v4] efi_loader: Add helper functions for EFI Date: Wed, 17 Mar 2021 21:54:59 +0200 Message-Id: <20210317195505.337105-3-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210317195505.337105-1-ilias.apalodimas@linaro.org> References: <20210317195505.337105-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.4 at phobos.denx.de X-Virus-Status: Clean A following patch introduces a different logic for loading initrd's based on the EFI_LOAD_FILE2_PROTOCOL. Since similar logic can be applied in the future for other system files (i.e DTBs), let's add some helper functions which will retrieve and parse file paths stored in EFI variables. Signed-off-by: Ilias Apalodimas --- include/efi_loader.h | 7 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_file.c | 39 +++++++++++++ lib/efi_loader/efi_helper.c | 98 +++++++++++++++++++++++++++++++++ lib/efi_loader/efi_var_common.c | 33 +++++++++++ 5 files changed, 178 insertions(+) create mode 100644 lib/efi_loader/efi_helper.c -- 2.31.0 diff --git a/include/efi_loader.h b/include/efi_loader.h index 5d534e69bb59..9c227005d13e 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -558,6 +558,11 @@ struct efi_simple_file_system_protocol *efi_simple_file_system( /* open file from device-path: */ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); +efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size); + +/* get a device path from a Boot#### option */ +struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid); + /** * efi_size_in_pages() - convert size in bytes to size in pages * @@ -723,6 +728,8 @@ efi_status_t EFIAPI efi_query_variable_info( u64 *remaining_variable_storage_size, u64 *maximum_variable_size); +void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size); + /* * See section 3.1.3 in the v2.7 UEFI spec for more details on * the layout of EFI_LOAD_OPTION. In short it is: diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 10b42e8847bf..da2741adecfa 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -23,6 +23,7 @@ endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o obj-y += efi_boottime.o +obj-y += efi_helper.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o obj-y += efi_console.o diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 8ece8e71ee1c..204105e25afd 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -409,6 +409,45 @@ static efi_status_t efi_get_file_size(struct file_handle *fh, return EFI_SUCCESS; } +/** + * efi_file_size() - Get the size of a file using an EFI file handle + * + * @fh: EFI file handle + * @size: buffer to fill in the discovered size + * + * Return: size of the file + */ +efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size) +{ + struct efi_file_info *info = NULL; + efi_uintn_t bs = 0; + efi_status_t ret; + + *size = 0; + ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs, + info)); + if (ret != EFI_BUFFER_TOO_SMALL) { + ret = EFI_DEVICE_ERROR; + goto out; + } + + info = malloc(bs); + if (!info) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs, + info)); + if (ret != EFI_SUCCESS) + goto out; + + *size = info->file_size; + +out: + free(info); + return ret; +} + static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size, void *buffer) { diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c new file mode 100644 index 000000000000..d03a7364615e --- /dev/null +++ b/lib/efi_loader/efi_helper.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#define LOG_CATEGORY LOGC_EFI +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * efi_create_current_boot_var() - Return Boot#### name were #### is replaced by + * the value of BootCurrent + * + * @var_name: variable name + * @var_name_size: size of var_name + * + * Return: Status code + */ +static efi_status_t efi_create_current_boot_var(u16 var_name[], + size_t var_name_size) +{ + efi_uintn_t boot_current_size; + efi_status_t ret; + u16 boot_current; + u16 *pos; + + boot_current_size = sizeof(boot_current); + ret = efi_get_variable_int(L"BootCurrent", + &efi_global_variable_guid, NULL, + &boot_current_size, &boot_current, NULL); + if (ret != EFI_SUCCESS) + goto out; + + pos = efi_create_indexed_name(var_name, var_name_size, "Boot", + boot_current); + if (!pos) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + +out: + return ret; +} + +/** + * efi_get_dp_from_boot() - Retrieve and return a device path from an EFI + * Boot### variable. + * A boot option may contain an array of device paths. + * We use a VenMedia() with a specific GUID to identify + * the usage of the array members. This function is + * used to extract a specific device path + * + * @guid: vendor GUID of the VenMedia() device path node identifying the + * device path + * + * Return: device path or NULL. Caller must free the returned value + */ +struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid) +{ + struct efi_device_path *file_path = NULL; + struct efi_device_path *tmp = NULL; + struct efi_load_option lo; + void *var_value = NULL; + efi_uintn_t size; + efi_status_t ret; + u16 var_name[16]; + + ret = efi_create_current_boot_var(var_name, sizeof(var_name)); + if (ret != EFI_SUCCESS) + return NULL; + + var_value = efi_get_var(var_name, &efi_global_variable_guid, &size); + if (!var_value) + return NULL; + + ret = efi_deserialize_load_option(&lo, var_value, &size); + if (ret != EFI_SUCCESS) + goto out; + + tmp = efi_dp_from_lo(&lo, &size, guid); + if (!tmp) + goto out; + + /* efi_dp_dup will just return NULL if efi_dp_next is NULL */ + file_path = efi_dp_dup(efi_dp_next(tmp)); + +out: + efi_free_pool(tmp); + free(var_value); + + return file_path; +} diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index 1c7459266a38..b11ed91a74a4 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -9,6 +9,7 @@ #include #include #include +#include enum efi_secure_mode { EFI_MODE_SETUP, @@ -343,3 +344,35 @@ enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid) } return EFI_AUTH_VAR_NONE; } + +/** + * efi_get_var() - read value of an EFI variable + * + * @name: variable name + * @start: vendor GUID + * @size: size of allocated buffer + * + * Return: buffer with variable data or NULL + */ +void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size) +{ + efi_status_t ret; + void *buf = NULL; + + *size = 0; + ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) { + buf = malloc(*size); + if (!buf) + return NULL; + ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL); + } + + if (ret != EFI_SUCCESS) { + free(buf); + *size = 0; + return NULL; + } + + return buf; +} From patchwork Wed Mar 17 19:55:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 403220 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp777622jai; Wed, 17 Mar 2021 12:55:50 -0700 (PDT) X-Google-Smtp-Source: ABdhPJys9cnhq5R7RuKt+WbQVveaXNX8tsxXWfc+FELVCihMmZ/URDjmdYFCK+CU76sm7cbALay3 X-Received: by 2002:aa7:dd99:: with SMTP id g25mr43530567edv.230.1616010950669; Wed, 17 Mar 2021 12:55:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616010950; cv=none; d=google.com; s=arc-20160816; b=QIZsLAgyBuGQg0d3VZTfwUR9LkGHM4UeMj/pbyUzC+v/OmCjTUfYRA5dZC31Jeg7+q /2NwRx0ERdGQLyAmKp88zadz0J6TkzgqrjGIrbkosCmp0MV+C8pH1536+qThtCqjnuAM HbqVagiu/rA+Vy4pumJ/7zdbt8x6OIGimK0cY/HSRfr57LTuZRiif1lXh5JFHj4Im1qr gtcf8AGW6J/QFy2JyOKklwNmD7a3KLy0go3u/Naj4tFE7VAW2fdE6TyR9H2gbLKlf9Du ouiGxRvjuIb4qx+OOsomaTJrRQfnPlnimjU1WJH+RApAuUgaiQC/2cM1i9ovdgoLRu3r 83Wg== 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:dkim-signature; bh=cXLG/Qrss+JJ5lBwmwEb2f7DP37IfH1LEJMSC2V26RA=; b=sPTRrHfSQB3Px4Ak2pbjuxWdmS/nouNUWK0WjzJpgFOpA1xv6IhGGsenPM8iSptwuo oDsJVtbvrER2WQOaH0QOVTESYsDjCunOv3dv30NwAT7vjJ1I+LXgFMgRfplIQVJWHP/C +Ku9kDTXV+fGtWgshfHWVlukhz0Y0/7+/QPkmEcoCsJlI2Bna3v219CuViVar489iamm rVdaYfE+f+pUBGycgvP+ymgnnGJB9cR2HgyGWWfCAaDs/eSeVt/BGwliGUVu2v8VN6bT o+AEBlXtM4LbNCWqkknrbWtFDcXWKjvlbocfZHV8GGzPb7W5bAdbMyNvmA1ebvv2zQZF Cbrg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=pPAanY2G; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id s10si12242586edx.425.2021.03.17.12.55.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:50 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=pPAanY2G; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (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 E070A827E9; Wed, 17 Mar 2021 20:55:28 +0100 (CET) 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="pPAanY2G"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6B00B8276D; Wed, 17 Mar 2021 20:55:25 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) (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 4797F80040 for ; Wed, 17 Mar 2021 20:55:21 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wr1-x42c.google.com with SMTP id b9so3081115wrt.8 for ; Wed, 17 Mar 2021 12:55:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cXLG/Qrss+JJ5lBwmwEb2f7DP37IfH1LEJMSC2V26RA=; b=pPAanY2GL4t3qGg1JbX9gpKuyodAluIueEeZa8VIQ2uX0+j3iM3cZe2Rpha77Ntwua KocQ0Jc/pkda4la3OEvYEiFZISKFktj6CqB84ovld0XCImz1Y14a+ffLuRv/hdPBVeq9 edJNfVZpDwGnI54wej+yly+2kAVhVxIRT4FauULxhm/GBVBZdHWFRk9Y2n8Vals6O7NA Pt6GlwthIbYmWNv2oHiv4zmxG0lekbmO/yFyPyASNoTqUUUpG/qCEQEz73QFHLAsqz06 gqptEgEIHsBoCR/G3Q1Y0iy7eduTOXOxDLxdNgQtS+khWPjLC2r51K3BuG/FPYB+n386 Grhw== 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=cXLG/Qrss+JJ5lBwmwEb2f7DP37IfH1LEJMSC2V26RA=; b=AFNQyAKgib8svgvhmWHwLpTQK6SvJU6hCnbb+f+gQ8C+5uIAUMRT1A/2s5tnYaO1aN Q6J8ZLH82FGK2g692EjotoxoASZW+BbGHeADC5xiLxy1q9S5XMdjSfNebCIYvd5mv4Qr s/kSfv+k59ujyrYkCq5yHlbLSrtRKezTaTyhf1zJAEsot1bbI9/ypU0VZ/ReWYyAkdqv PXPhzbBzqL4WnvE4KVTS00wEeesX8oJgvT+QeQeR1vc+SuhESapR2qsKQP0hUghRYo/U yJ7H4KPg68fJ660b/FDleD2hgBC3YOCw4AvEHP7zVT6rw0i2TtEJm8ulH+u5nBshTjER zrhg== X-Gm-Message-State: AOAM533b7hy3ZSGGBk9sPdogoBD7Ggr378enz3zLVQi3A3m8+YV3wWUb AvxHtZANleciNOkufhSn7NbpGw== X-Received: by 2002:adf:e38a:: with SMTP id e10mr6049059wrm.37.1616010920838; Wed, 17 Mar 2021 12:55:20 -0700 (PDT) Received: from localhost.localdomain (ppp-94-64-113-158.home.otenet.gr. [94.64.113.158]) by smtp.gmail.com with ESMTPSA id z82sm3343853wmg.19.2021.03.17.12.55.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:20 -0700 (PDT) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, Ilias Apalodimas , Alexander Graf , Sughosh Ganu , u-boot@lists.denx.de Subject: [PATCH 3/5 v4] efi_loader: Replace config option for initrd loading Date: Wed, 17 Mar 2021 21:55:00 +0200 Message-Id: <20210317195505.337105-4-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210317195505.337105-1-ilias.apalodimas@linaro.org> References: <20210317195505.337105-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.4 at phobos.denx.de X-Virus-Status: Clean Up to now we install EFI_LOAD_FILE2_PROTOCOL to load an initrd unconditionally. Although we correctly return various EFI exit codes depending on the file status (i.e EFI_NO_MEDIA, EFI_NOT_FOUND etc), the kernel loader, only falls back to the cmdline interpreted initrd if the protocol is not installed. This creates a problem for EFI installers, since they won't be able to load their own initrd and continue the installation. It also makes the feature hard to use, since we can either have a single initrd or we have to recompile u-boot if the filename changes. So let's introduce a different logic that will decouple the initrd path from the config option we currently have. When defining a UEFI BootXXXX we can use the filepathlist and store a file path pointing to our initrd. Specifically the EFI spec describes: "The first element of the array is a device path that describes the device and location of the Image for this load option. Other device paths may optionally exist in the FilePathList, but their usage is OSV specific" When the EFI application is launched through the bootmgr, we'll try to interpret the extra device path. If that points to a file that exists on our disk, we'll now install the load_file2 and the efi-stub will be able to use it. This opens up another path using U-Boot and defines a new boot flow. A user will be able to control the kernel/initrd pairs without explicit cmdline args or GRUB. Signed-off-by: Ilias Apalodimas Reviewed-by: Heinrich Schuchardt --- cmd/bootefi.c | 3 + include/efi_loader.h | 1 + lib/efi_loader/Kconfig | 17 +-- lib/efi_loader/efi_bootmgr.c | 19 ++- lib/efi_loader/efi_load_initrd.c | 202 ++++++++++++++++++------------- 5 files changed, 144 insertions(+), 98 deletions(-) -- 2.31.0 diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 271b385edea6..cba81ffe75e4 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -358,6 +358,9 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options) free(load_options); + if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) + efi_initrd_deregister(); + return ret; } diff --git a/include/efi_loader.h b/include/efi_loader.h index 9c227005d13e..903bf60bc0a3 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -437,6 +437,7 @@ efi_status_t efi_net_register(void); /* Called by bootefi to make the watchdog available */ efi_status_t efi_watchdog_register(void); efi_status_t efi_initrd_register(void); +void efi_initrd_deregister(void); /* Called by bootefi to make SMBIOS tables available */ /** * efi_acpi_register() - write out ACPI tables diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 634d3b1ff4e3..0a412441a719 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -315,18 +315,13 @@ config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE config EFI_LOAD_FILE2_INITRD bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk" - default n - help - Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can - use to load the initial ramdisk. Once this is enabled using - initrd= will stop working. - -config EFI_INITRD_FILESPEC - string "initramfs path" - default "host 0:1 initrd" - depends on EFI_LOAD_FILE2_INITRD + default y help - Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz. + Linux v5.7 and later can make use of this option. If the boot option + selected by the UEFI boot manager specifies an existing file to be used + as initial RAM disk, a Linux specific Load File2 protocol will be + installed and Linux 5.7+ will ignore any initrd= command line + argument. config EFI_SECURE_BOOT bool "Enable EFI secure boot support" diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 25f5cebfdb67..46c8011344b9 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -118,11 +118,13 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, ret = efi_set_variable_int(L"BootCurrent", &efi_global_variable_guid, attributes, sizeof(n), &n, false); - if (ret != EFI_SUCCESS) { - if (EFI_CALL(efi_unload_image(*handle)) - != EFI_SUCCESS) - log_err("Unloading image failed\n"); - goto error; + if (ret != EFI_SUCCESS) + goto unload; + /* try to register load file2 for initrd's */ + if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) { + ret = efi_initrd_register(); + if (ret != EFI_SUCCESS) + goto unload; } log_info("Booting: %ls\n", lo.label); @@ -146,6 +148,13 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, error: free(load_option); + return ret; + +unload: + if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS) + log_err("Unloading image failed\n"); + free(load_option); + return ret; } diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index b9ee8839054f..e2a806302303 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -3,9 +3,11 @@ * Copyright (c) 2020, Linaro Limited */ +#define LOG_CATEGORY LOGC_EFI #include #include #include +#include #include #include #include @@ -23,57 +25,56 @@ static const struct efi_load_file_protocol efi_lf2_protocol = { * Device path defined by Linux to identify the handle providing the * EFI_LOAD_FILE2_PROTOCOL used for loading the initial ramdisk. */ -static const struct efi_initrd_dp dp = { +static const struct efi_initrd_dp dp_lf2_handle = { .vendor = { { DEVICE_PATH_TYPE_MEDIA_DEVICE, DEVICE_PATH_SUB_TYPE_VENDOR_PATH, - sizeof(dp.vendor), + sizeof(dp_lf2_handle.vendor), }, EFI_INITRD_MEDIA_GUID, }, .end = { DEVICE_PATH_TYPE_END, DEVICE_PATH_SUB_TYPE_END, - sizeof(dp.end), + sizeof(dp_lf2_handle.end), } }; +static efi_handle_t efi_initrd_handle; + /** - * get_file_size() - retrieve the size of initramfs, set efi status on error + * get_initrd_fp() - Get initrd device path from a FilePathList device path * - * @dev: device to read from, e.g. "mmc" - * @part: device partition, e.g. "0:1" - * @file: name of file - * @status: EFI exit code in case of failure + * @initrd_fp: the final initrd filepath * - * Return: size of file + * Return: status code. Caller must free initrd_fp */ -static loff_t get_file_size(const char *dev, const char *part, const char *file, - efi_status_t *status) +static efi_status_t get_initrd_fp(struct efi_device_path **initrd_fp) { - loff_t sz = 0; - int ret; - - ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY); - if (ret) { - *status = EFI_NO_MEDIA; - goto out; - } + const efi_guid_t lf2_initrd_guid = EFI_INITRD_MEDIA_GUID; + struct efi_device_path *dp = NULL; - ret = fs_size(file, &sz); - if (ret) { - sz = 0; - *status = EFI_NOT_FOUND; - goto out; - } + /* + * if bootmgr is setup with and initrd, the device path will be + * in the FilePathList[] of our load options in Boot####. + * The first device path of the multi instance device path will + * start with a VenMedia and the initrds will follow. + * + * If the device path is not found return EFI_INVALID_PARAMETER. + * We can then use this specific return value and not install the + * protocol, while allowing the boot to continue + */ + dp = efi_get_dp_from_boot(lf2_initrd_guid); + if (!dp) + return EFI_INVALID_PARAMETER; -out: - return sz; + *initrd_fp = dp; + return EFI_SUCCESS; } /** - * efi_load_file2initrd() - load initial RAM disk + * efi_load_file2_initrd() - load initial RAM disk * * This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL * in order to load an initial RAM disk requested by the Linux kernel stub. @@ -93,102 +94,125 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, struct efi_device_path *file_path, bool boot_policy, efi_uintn_t *buffer_size, void *buffer) { - char *filespec; - efi_status_t status = EFI_NOT_FOUND; - loff_t file_sz = 0, read_sz = 0; - char *dev, *part, *file; - char *pos; - int ret; + struct efi_device_path *initrd_fp = NULL; + efi_status_t ret = EFI_NOT_FOUND; + struct efi_file_handle *f = NULL; + efi_uintn_t bs; EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy, buffer_size, buffer); - filespec = strdup(CONFIG_EFI_INITRD_FILESPEC); - if (!filespec) - goto out; - pos = filespec; - if (!this || this != &efi_lf2_protocol || !buffer_size) { - status = EFI_INVALID_PARAMETER; + ret = EFI_INVALID_PARAMETER; goto out; } - if (file_path->type != dp.end.type || - file_path->sub_type != dp.end.sub_type) { - status = EFI_INVALID_PARAMETER; + if (file_path->type != dp_lf2_handle.end.type || + file_path->sub_type != dp_lf2_handle.end.sub_type) { + ret = EFI_INVALID_PARAMETER; goto out; } if (boot_policy) { - status = EFI_UNSUPPORTED; + ret = EFI_UNSUPPORTED; goto out; } - /* - * expect a string with three space separated parts: - * - * * a block device type, e.g. "mmc" - * * a device and partition identifier, e.g. "0:1" - * * a file path on the block device, e.g. "/boot/initrd.cpio.gz" - */ - dev = strsep(&pos, " "); - if (!dev) + ret = get_initrd_fp(&initrd_fp); + if (ret != EFI_SUCCESS) goto out; - part = strsep(&pos, " "); - if (!part) - goto out; - file = strsep(&pos, " "); - if (!file) + + /* Open file */ + f = efi_file_from_path(initrd_fp); + if (!f) { + log_err("Can't find initrd specified in Boot####\n"); + ret = EFI_NOT_FOUND; goto out; + } - file_sz = get_file_size(dev, part, file, &status); - if (!file_sz) + /* Get file size */ + ret = efi_file_size(f, &bs); + if (ret != EFI_SUCCESS) goto out; - if (!buffer || *buffer_size < file_sz) { - status = EFI_BUFFER_TOO_SMALL; - *buffer_size = file_sz; + if (!buffer || *buffer_size < bs) { + ret = EFI_BUFFER_TOO_SMALL; + *buffer_size = bs; } else { - ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY); - if (ret) { - status = EFI_NO_MEDIA; - goto out; - } - - ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size, - &read_sz); - if (ret || read_sz != file_sz) - goto out; - *buffer_size = read_sz; - - status = EFI_SUCCESS; + ret = EFI_CALL(f->read(f, &bs, (void *)(uintptr_t)buffer)); + *buffer_size = bs; + } + +out: + efi_free_pool(initrd_fp); + if (f) + EFI_CALL(f->close(f)); + return EFI_EXIT(ret); +} + +/** + * check_initrd() - Determine if the file defined as an initrd in Boot#### + * load_options device path is present + * + * Return: status code + */ +static efi_status_t check_initrd(void) +{ + struct efi_device_path *initrd_fp = NULL; + struct efi_file_handle *f; + efi_status_t ret; + + ret = get_initrd_fp(&initrd_fp); + if (ret != EFI_SUCCESS) + goto out; + + /* + * If the file is not found, but the file path is set, return an error + * and trigger the bootmgr fallback + */ + f = efi_file_from_path(initrd_fp); + if (!f) { + log_err("Can't find initrd specified in Boot####\n"); + ret = EFI_NOT_FOUND; + goto out; } + EFI_CALL(f->close(f)); + out: - free(filespec); - return EFI_EXIT(status); + efi_free_pool(initrd_fp); + return ret; } /** * efi_initrd_register() - create handle for loading initial RAM disk * * This function creates a new handle and installs a Linux specific vendor - * device path and an EFI_LOAD_FILE_2_PROTOCOL. Linux uses the device path + * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path * to identify the handle and then calls the LoadFile service of the - * EFI_LOAD_FILE_2_PROTOCOL to read the initial RAM disk. + * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk. * * Return: status code */ efi_status_t efi_initrd_register(void) { - efi_handle_t efi_initrd_handle = NULL; efi_status_t ret; + /* + * Allow the user to continue if Boot#### file path is not set for + * an initrd + */ + ret = check_initrd(); + if (ret == EFI_INVALID_PARAMETER) + return EFI_SUCCESS; + if (ret != EFI_SUCCESS) + return ret; + ret = EFI_CALL(efi_install_multiple_protocol_interfaces (&efi_initrd_handle, /* initramfs */ - &efi_guid_device_path, &dp, + &efi_guid_device_path, &dp_lf2_handle, /* LOAD_FILE2 */ &efi_guid_load_file2_protocol, (void *)&efi_lf2_protocol, @@ -196,3 +220,17 @@ efi_status_t efi_initrd_register(void) return ret; } + +/** + * efi_initrd_deregister() - delete the handle for loading initial RAM disk + * + * This will delete the handle containing the Linux specific vendor device + * path and EFI_LOAD_FILE2_PROTOCOL for loading an initrd + * + * Return: status code + */ +void efi_initrd_deregister(void) +{ + efi_delete_handle(efi_initrd_handle); + efi_initrd_handle = NULL; +} From patchwork Wed Mar 17 19:55:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 403221 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp777717jai; Wed, 17 Mar 2021 12:56:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwQt+ZBR/WkQDo0rxnwabyOQpqWZPH6ereOQ1tw9PG/RiWmdbxTkOFAzUOeF18unVcpgGfe X-Received: by 2002:a17:906:abcd:: with SMTP id kq13mr38159991ejb.477.1616010963451; Wed, 17 Mar 2021 12:56:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616010963; cv=none; d=google.com; s=arc-20160816; b=Xqql58lkykjB+BqCK8LClQy0+lFpEolRIvC4xRr2qGxco5BEm6QZ1hVAe3Bj8UKF4B 9CDLQlGht+5+O1Z3qiUeaMc9HvuH2qPXfyQBV72LsEAgs9mtv7b60BfQbfz1xktFa1Ws HLV8TjlXm4DBBPw6q39SJ+wIfIbfAtXXG3rGmZxXP6NEEQdiRsxw/fcmVhHNUcE2XIj0 T8SPSR7cCfpeOqpYLtQDmnxXm2G5Z3SEzQEPc1mjJHWtRRtfrbzSXH2pFd7ZLjglGn/F WNpx0xgoGVwHS6O35hVyzikMbFtD6SRzqBoNranqmSQNWFwQOEWayMOPGkzw6Z47at8v buLQ== 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:dkim-signature; bh=Wu8/J2Xru6ryD0NwjsWqGxk7wNVygVdeHIrIgE48aww=; b=pf7kenv24KRj2SVTV+MEgyTD8DmHCqbgf9jxaYH1iUxPVpTmAUxuWLZiF+ffcZlaWO bnnsipJVr1gAg+34NaHMvvy5zDp6FCQl1WMxId0N6pRn32J8DGyEq29JOc2zUwAUUwfT lRLJHdkRr35iEsGKWNKQmpWVKGe0O/yH8mESDAtKv1XKw/wRIOoWgiTfwYbslNRXkI5h 5kaE82UgkapvaaDiRZD1RRW/sNEFmZA/Ed/Gira33U+wEIfh0Syh+vgnelkiW3zgwIKu gv9VSIGyjvXACqpu9iJ+uSUb0nOeufR5PPvLsZEbjDzm13BOIeKGGHa4TTVBmhzGrOu4 ov0A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=DZpOXjrV; 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=pass (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 r20si17979815edw.406.2021.03.17.12.56.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:56:03 -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; dkim=pass header.i=@linaro.org header.s=google header.b=DZpOXjrV; 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=pass (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 6D5C082843; Wed, 17 Mar 2021 20:55:34 +0100 (CET) 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="DZpOXjrV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DB34C82822; Wed, 17 Mar 2021 20:55:31 +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=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) (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 8C80E80040 for ; Wed, 17 Mar 2021 20:55:25 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wm1-x32f.google.com with SMTP id u5-20020a7bcb050000b029010e9316b9d5so2022768wmj.2 for ; Wed, 17 Mar 2021 12:55:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Wu8/J2Xru6ryD0NwjsWqGxk7wNVygVdeHIrIgE48aww=; b=DZpOXjrVxk4ObauBZZZ/ZOxdMZBtqwIRa1z7+uMMJVM3AIXeyFYphu8mAipgPOD6y5 iOrxOv4C58psgAzBzGBanLnV7p4bahMOMNnOkwoOx0oQAUgXn1DECp4xRAX6QfOufwHb Ph+w/i80VV7LM5JEvBVYZg8BxXlAf4ub4U3W8jhPl5zyoNcOh8TC6Eu9/6wjcGn2Ybi6 L4pJmmcf/CtRuqc+QbK20jsb9milcQZ9iQDqi2KhY2cua4eW2cdOC2I0JhwB1xLUgp+X hgmKibM5TXEirvB+lG2mlIh0Hu5iN+KgR+dXFnhLK7uAe6psIzf/2Dug8q6bOIasjDKK mpXA== 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=Wu8/J2Xru6ryD0NwjsWqGxk7wNVygVdeHIrIgE48aww=; b=MwgI+V0GHDWjLEJp3fW4as/w843eV0Hbx23cV8HeUI+EYVbyGhZBpS2QdZgdC5bRes qXCGZZHlIR78rOxo1pk6n9KaSGekIpqKp6vJQwh56aWLnXZEWExMnxmtu4czWndQ4kvx YGVf5Sxwg1+zwpHa37GU0AdSayIiViZQz+9QGkoWAUCcR/Fxkjpqlu8bvwlVnoiPKrMw 3iSaEp7fo7Ex6mjCBRhoDnfqlRGSKbQYi8S/VUc8YrPBcG75JjRWmDr5iRbkZNhBS0Kt jOkfV08XVqH8TSfImphN45ufx5rfxbqLnTKReVHLLuT2wXvhWbeaYisRG3OuYtfyMOMY OwJA== X-Gm-Message-State: AOAM532y3eCzvsKCQL625tpmlwnL2HblFLbtRwmnTH5wXZzQ0LXHxxF+ G+LWIwckWZXa25if/NMEpvtOdw== X-Received: by 2002:a05:600c:47d7:: with SMTP id l23mr398178wmo.155.1616010925021; Wed, 17 Mar 2021 12:55:25 -0700 (PDT) Received: from localhost.localdomain (ppp-94-64-113-158.home.otenet.gr. [94.64.113.158]) by smtp.gmail.com with ESMTPSA id z82sm3343853wmg.19.2021.03.17.12.55.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Mar 2021 12:55:24 -0700 (PDT) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, Ilias Apalodimas , Alexander Graf , Sughosh Ganu , u-boot@lists.denx.de Subject: [PATCH 4/5 v4] efidebug: add multiple device path instances on Boot#### Date: Wed, 17 Mar 2021 21:55:01 +0200 Message-Id: <20210317195505.337105-5-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210317195505.337105-1-ilias.apalodimas@linaro.org> References: <20210317195505.337105-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.4 at phobos.denx.de X-Virus-Status: Clean The UEFI spec allows a packed array of UEFI device paths in the FilePathList[] of an EFI_LOAD_OPTION. The first file path must describe the loaded image but the rest are OS specific. Previous patches parse the device path and try to use the second member of the array as an initrd. So let's modify efidebug slightly and install the second file described in the command line as the initrd device path. Signed-off-by: Ilias Apalodimas --- cmd/efidebug.c | 191 ++++++++++++++---- doc/board/emulation/qemu_capsule_update.rst | 4 +- doc/uefi/uefi.rst | 2 +- .../test_efi_capsule/test_capsule_firmware.py | 6 +- test/py/tests/test_efi_secboot/test_signed.py | 16 +- .../test_efi_secboot/test_signed_intca.py | 8 +- .../tests/test_efi_secboot/test_unsigned.py | 8 +- 7 files changed, 177 insertions(+), 58 deletions(-) -- 2.31.0 diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 55c7abe3d078..80ddd598e0a1 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #define BS systab.boottime #define RT systab.runtime @@ -798,6 +800,54 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag, return CMD_RET_SUCCESS; } +/** + * create_initrd_dp() - Create a special device for our Boot### option + * + * @dev: Device + * @part: Disk partition + * @file: Filename + * Return: Pointer to the device path or ERR_PTR + * + */ +static +struct efi_device_path *create_initrd_dp(const char *dev, const char *part, + const char *file) + +{ + struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL; + struct efi_device_path *initrd_dp = NULL; + efi_status_t ret; + const struct efi_initrd_dp id_dp = { + .vendor = { + { + DEVICE_PATH_TYPE_MEDIA_DEVICE, + DEVICE_PATH_SUB_TYPE_VENDOR_PATH, + sizeof(id_dp.vendor), + }, + EFI_INITRD_MEDIA_GUID, + }, + .end = { + DEVICE_PATH_TYPE_END, + DEVICE_PATH_SUB_TYPE_END, + sizeof(id_dp.end), + } + }; + + ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp); + if (ret != EFI_SUCCESS) { + printf("Cannot create device path for \"%s %s\"\n", part, file); + goto out; + } + + initrd_dp = efi_dp_append((const struct efi_device_path *)&id_dp, + tmp_fp); + +out: + efi_free_pool(tmp_dp); + efi_free_pool(tmp_fp); + return initrd_dp; +} + /** * do_efi_boot_add() - set UEFI load option * @@ -810,7 +860,9 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag, * * Implement efidebug "boot add" sub-command. Create or change UEFI load option. * - * efidebug boot add