From patchwork Mon Apr 16 05:59:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 898476 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 40PdDH011Yz9s1R for ; Mon, 16 Apr 2018 16:06:06 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id A0CC8C21DF8; Mon, 16 Apr 2018 06:02:22 +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 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 50888C21E3E; Mon, 16 Apr 2018 05:59:31 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id DF121C21C3F; Mon, 16 Apr 2018 05:59:20 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.17.20]) by lists.denx.de (Postfix) with ESMTPS id 3A78AC21C3F for ; Mon, 16 Apr 2018 05:59:20 +0000 (UTC) Received: from LPT2.fritz.box ([62.143.246.157]) by mail.gmx.com (mrgmx101 [212.227.17.174]) with ESMTPSA (Nemesis) id 0LtVLE-1eP22t2u4S-010vN7; Mon, 16 Apr 2018 07:59:19 +0200 From: Heinrich Schuchardt To: Alexander Graf Date: Mon, 16 Apr 2018 07:59:09 +0200 Message-Id: <20180416055910.12611-8-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180416055910.12611-1-xypron.glpk@gmx.de> References: <20180416055910.12611-1-xypron.glpk@gmx.de> X-Provags-ID: V03:K1:+YoB7J5DEogxcscksPWdteTBQk966MLfWyak5l4F+5e98ecuXiv CxcMhnB5kN0yS0/DOcM+YougrJtQmDIdrat8chZHw2k8Jc6I6rysjz74dV5pr3WYzKCU0MZ 9JKfdU++k47Jag2dXU5hg0b1QPZlrRLmEfT0iR55yqYUgfmcs+WGU6j7HEoacI5i6sHNIMK 2kmDo8Y8KHfQS63KE7Weg== X-UI-Out-Filterresults: notjunk:1; V01:K0:t6deZFjqLmY=:15CAalJSqxWLsBVmoQgGbl 5SjMjgcMFFMGGXM4cc+RYAM5xDLbhkHSeZhD3ZllT/f7dYbDObofiFmjd4krpGhq6A05nv6ud BQ3IjxeZ0o+QyJaBA+nR4UBC/F3OkCYAtf3bC4/BM7RzxPhzCJI61fXFv/8ymAWfCDRtPuIyk nbwajCtSpwd67fK3o80Hu0MX6OjGLwymePyp2GCz6Ss5uUzEew8UygDVD+rQCusTwunp+n/fJ 7EyZyoyTeyfdWCjLwF/Nv2ydkHNwwU76SpNzoKdneKwFIbFh5LxNpioux1FNQGP4YMCaPTZ4S xPs2cTyK9xdp17B7ABvfYKzvzKLMQZbcBny155GLavTSxFioDRIGhG6DumoStYsP2/F9s/O1D zJp7AuCCtIJ75Cd6Onc4RUP/Qmu9ScfqZV1SKOjg0dnGlCSUITYM7tx14XGNe8p0CSZbTy5XZ rT67HwQ4p7Qzi17gDw59aPcw+AWvvnDk6Rzexsiuwph80Ji/+r4BzT/OyBPzMjC7TF+bPNZAg xCDK+IJlMSQZtvUtvP1yNeU5mYSIU+f8yoXpS4+G73mN0jt0MF9KP7aLFquqQndViaPBWjIml 305M3iR+JsMoZ0i+kGtWix1QPf4rA+Xjs4wfFO2n8dH+CBwJr4Cr562qTtieqg+QhTfW2nE79 ky0p/XXb9ik3/LJLMeqKuKlBcWiDpdXUroy3rHXO47VbDk0EkVA4gvFzW0UrI89k357jm8VmN eMDuLwj8u7IIyDvShvfkk94BJ58caZ6S7xmhQzxbQYFB/XxgJmJmumL2YdY7CLrtIVg4WX9sH FKOhyLKyl+q2utzas43/xvVezN8mQ== Cc: u-boot@lists.denx.de, Heinrich Schuchardt Subject: [U-Boot] [PATCH v2 7/8] efi_loader: complete EFI_DEVICE_PATH_UTILITIES_PROTOCOL 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 missing services of the EFI_DEVICE_PATH_UTILITIES_PROTOCOL are implemented. Signed-off-by: Heinrich Schuchardt --- v2 no change --- include/efi_api.h | 1 + include/efi_loader.h | 9 ++ lib/efi_loader/efi_device_path.c | 64 ++++++++++++ lib/efi_loader/efi_device_path_utilities.c | 116 +++++++++++++++++++-- 4 files changed, 180 insertions(+), 10 deletions(-) diff --git a/include/efi_api.h b/include/efi_api.h index ae93061160..64c27e494b 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -343,6 +343,7 @@ struct efi_loaded_image { 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) #define DEVICE_PATH_TYPE_END 0x7f +# define DEVICE_PATH_SUB_TYPE_INSTANCE_END 0x01 # define DEVICE_PATH_SUB_TYPE_END 0xff struct efi_device_path { diff --git a/include/efi_loader.h b/include/efi_loader.h index 1298b5e160..8d21ba74b1 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -337,6 +337,15 @@ struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp, struct efi_device_path *efi_dp_create_device_node(const u8 type, const u8 sub_type, const u16 length); +/* Append device path instance */ +struct efi_device_path *efi_dp_append_instance( + const struct efi_device_path *dp, + const struct efi_device_path *dpi); +/* Get next device path instance */ +struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, + efi_uintn_t *size); +/* Check if a device path contains muliple instances */ +bool efi_dp_is_multi_instance(const struct efi_device_path *dp); struct efi_device_path *efi_dp_from_dev(struct udevice *dev); struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 09c3ec4273..2861982883 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -351,6 +351,70 @@ struct efi_device_path *efi_dp_create_device_node(const u8 type, return ret; } +struct efi_device_path *efi_dp_append_instance( + const struct efi_device_path *dp, + const struct efi_device_path *dpi) +{ + size_t sz, szi; + struct efi_device_path *p, *ret; + + if (!dpi) + return NULL; + if (!dp) + return efi_dp_dup(dpi); + sz = efi_dp_size(dp); + szi = efi_dp_instance_size(dpi); + p = dp_alloc(sz + szi + 2 * sizeof(END)); + if (!p) + return NULL; + ret = p; + memcpy(p, dp, sz + sizeof(END)); + p = (void *)p + sz; + p->sub_type = DEVICE_PATH_SUB_TYPE_INSTANCE_END; + p = (void *)p + sizeof(END); + memcpy(p, dpi, szi); + p = (void *)p + szi; + memcpy(p, &END, sizeof(END)); + return ret; +} + +struct efi_device_path *efi_dp_get_next_instance(struct efi_device_path **dp, + efi_uintn_t *size) +{ + size_t sz; + struct efi_device_path *p; + + if (size) + *size = 0; + if (!dp || !*dp) + return NULL; + p = *dp; + sz = efi_dp_instance_size(*dp); + p = dp_alloc(sz + sizeof(END)); + if (!p) + return NULL; + memcpy(p, *dp, sz + sizeof(END)); + *dp = (void *)*dp + sz; + if ((*dp)->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END) + *dp = (void *)*dp + sizeof(END); + else + *dp = NULL; + if (size) + *size = sz + sizeof(END); + return p; +} + +bool efi_dp_is_multi_instance(const struct efi_device_path *dp) +{ + const struct efi_device_path *p = dp; + + if (!p) + return false; + while (p->type != DEVICE_PATH_TYPE_END) + p = (void *)p + p->length; + return p->sub_type == DEVICE_PATH_SUB_TYPE_INSTANCE_END; +} + #ifdef CONFIG_DM /* size of device-path not including END node for device and all parents * up to the root device. diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index e73188b242..0ada2111db 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -12,62 +12,158 @@ const efi_guid_t efi_guid_device_path_utilities_protocol = EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; +/* + * Get size of a device path. + * + * This function implements the GetDevicePathSize service of the device path + * utilities protocol. The device path length includes the end of path tag + * which may be an instance end. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * @return size in bytes + */ static efi_uintn_t EFIAPI get_device_path_size( const struct efi_device_path *device_path) { efi_uintn_t sz = 0; - EFI_ENTRY("%p", device_path); + EFI_ENTRY("%pD", device_path); /* size includes the END node: */ if (device_path) sz = efi_dp_size(device_path) + sizeof(struct efi_device_path); return EFI_EXIT(sz); } +/* + * Duplicate a device path. + * + * This function implements the DuplicateDevicePath service of the device path + * utilities protocol. + * + * The UEFI spec does not indicate what happens to the end tag. We follow the + * EDK2 logic: In case the device path ends with an end of instance tag, the + * copy will also end with an end of instance tag. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * @return copy of the device path + */ static struct efi_device_path * EFIAPI duplicate_device_path( const struct efi_device_path *device_path) { - EFI_ENTRY("%p", device_path); + EFI_ENTRY("%pD", device_path); return EFI_EXIT(efi_dp_dup(device_path)); } +/* + * Append device path. + * + * This function implements the AppendDevicePath service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @src1 1st device path + * @src2 2nd device path + * @return concatenated device path + */ static struct efi_device_path * EFIAPI append_device_path( const struct efi_device_path *src1, const struct efi_device_path *src2) { - EFI_ENTRY("%p, %p", src1, src2); + EFI_ENTRY("%pD, %pD", src1, src2); return EFI_EXIT(efi_dp_append(src1, src2)); } +/* + * Append device path node. + * + * This function implements the AppendDeviceNode service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * @device_node device node + * @return concatenated device path + */ static struct efi_device_path * EFIAPI append_device_node( const struct efi_device_path *device_path, const struct efi_device_path *device_node) { - EFI_ENTRY("%p, %p", device_path, device_node); + EFI_ENTRY("%pD, %p", device_path, device_node); return EFI_EXIT(efi_dp_append_node(device_path, device_node)); } +/* + * Append device path instance. + * + * This function implements the AppendDevicePathInstance service of the device + * path utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path 1st device path + * @device_path_instance 2nd device path + * @return concatenated device path + */ static struct efi_device_path * EFIAPI append_device_path_instance( const struct efi_device_path *device_path, const struct efi_device_path *device_path_instance) { - EFI_ENTRY("%p, %p", device_path, device_path_instance); - return EFI_EXIT(NULL); + EFI_ENTRY("%pD, %pD", device_path, device_path_instance); + return EFI_EXIT(efi_dp_append_instance(device_path, + device_path_instance)); } +/* + * Get next device path instance. + * + * This function implements the GetNextDevicePathInstance service of the device + * path utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path_instance next device path instance + * @device_path_instance_size size of the device path instance + * @return concatenated device path + */ static struct efi_device_path * EFIAPI get_next_device_path_instance( struct efi_device_path **device_path_instance, efi_uintn_t *device_path_instance_size) { - EFI_ENTRY("%p, %p", device_path_instance, device_path_instance_size); - return EFI_EXIT(NULL); + EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size); + return EFI_EXIT(efi_dp_get_next_instance(device_path_instance, + device_path_instance_size)); } +/* + * Check if a device path contains more than one instance. + * + * This function implements the AppendDeviceNode service of the device path + * utilities protocol. + * + * See the Unified Extensible Firmware Interface (UEFI) specification + * for details. + * + * @device_path device path + * @device_node device node + * @return concatenated device path + */ static bool EFIAPI is_device_path_multi_instance( const struct efi_device_path *device_path) { - EFI_ENTRY("%p", device_path); - return EFI_EXIT(false); + EFI_ENTRY("%pD", device_path); + return EFI_EXIT(efi_dp_is_multi_instance(device_path)); } /*