From patchwork Sat Aug 5 20:32:29 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 798304 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=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3xPwYj1T37z9sNc for ; Sun, 6 Aug 2017 06:36:25 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E3238C21D82; Sat, 5 Aug 2017 20:35:26 +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.7 required=5.0 tests=FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, 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 B9FCBC21F3B; Sat, 5 Aug 2017 20:34:35 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 110CAC21C72; Sat, 5 Aug 2017 20:34:32 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.17.21]) by lists.denx.de (Postfix) with ESMTPS id B86B7C21DE1 for ; Sat, 5 Aug 2017 20:34:31 +0000 (UTC) Received: from workstation4.fritz.box ([84.118.154.110]) by mail.gmx.com (mrgmx103 [212.227.17.174]) with ESMTPSA (Nemesis) id 0Ma2Lr-1dwZpp2Tap-00Ln4O; Sat, 05 Aug 2017 22:34:30 +0200 From: Heinrich Schuchardt To: Alexander Graf Date: Sat, 5 Aug 2017 22:32:29 +0200 Message-Id: <20170805203230.19796-3-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170805203230.19796-1-xypron.glpk@gmx.de> References: <20170805203230.19796-1-xypron.glpk@gmx.de> X-Provags-ID: V03:K0:cOy95vZroPaoqWSB9OB1x4i+7L1WG/oZvZNfcSlI11M08KOUPAB 87Olt35+DxfaZ+v8+/ieo8pCKMk3fi4mebRKf3hNJLDHgWFxrh9XYQClAYGwtl2zT9smksA BXZDh/iPMwMpCQU76HygEco/DnOFv0s7MNnSB4UiIn4lgsx4QHfQ64Pb+rjZDcTNLUVs1tE a7Vzm0gIr70XGdY8jGtvw== X-UI-Out-Filterresults: notjunk:1; V01:K0:xN7ClucxOtg=:IQz5jv/bmd0ow4M4se+bxb zBS00d+y6NAA7nMampmYG9x4DPBVxdjRaE1IziWKhu6LkKyrbYIzCVG2gfIdmgBjMOz8pZ9kh oUpf7zkhBHtobTnpELmpJj1CUVvfYyJ3amxtyjYP0Ir7IWj9AyZwTW/T5XCUfokb/4/hyRBJo AsrSowJs0zLXjpfHcym+2fNsJ18RrDbgPeIGhCcCDpslMBmLYjJVFSQ3ydcqXUFh+pBvzefdK OcjssUgYL+9yPKoDjkrl/vUq6FoLf/n257xqVLFtxgTwVsU0Y7dsU7FGIgAqniZPu2rMkwIru oU4/w0mb9gpMpmlAMpXRYcm+ywAGABsWS4YytnM1tCjTwu8zoTiptOk9mLbA52r2dV45De/aM mV2oFjPEL+rtayk90B8juxe2bws3MlN+Us5W0u+JTf7/R3fXiFbqmp1PJj6iKlEDKltv5zgfm A2FAdt+1LMxwVYx8QHHlhozwWlEHryVtEgONEVkm8CIziDNjNrtPHUbph6AMdW3X7xWyISkK4 sOOCslG8eM07MiadJ3Wo1dI2187X0rX22tQeNNkHPM9wqdvTPHtzkHlf0BvHBzSh1MmTauRWi gnJ4SSpozCbjRvCFqeTJt607x+FDDLB1zitTeWgn5LEB+4Jk2vVVmvBVCJKBJWTqWN4p+6sar e3h2Bq2gBwPiP/N9PLPqYHWP5we+pjoHW4jeyNkZHAYNweE84Cy2IvYmDhsS9sooqJwigoGXE uCxy3zqMqkjWwgd4bXYutdd2AY9sctF+6/WEo2bZGWxFxOFZ13Pu4cr6wPECa1UAhI3DerpHm gxYxls8hvDb6d3HxJPUVrDALs/26A== Cc: u-boot@lists.denx.de, Heinrich Schuchardt Subject: [U-Boot] [PATCH v3 2/3] efi_loader: open_info in OpenProtocol, CloseProtocol 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" efi_open_protocol and close_protocol have to keep track of opened protocols. So we add an array open_info to each protocol of each handle. Cc: Rob Clark Signed-off-by: Heinrich Schuchardt --- v3: use EFI_CALL to avoid wrapper for efi_disconnect_controller use list_for_each_entry move variable declarations out of loops v2: new patch --- include/efi_loader.h | 1 + lib/efi_loader/efi_boottime.c | 164 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 155 insertions(+), 10 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index 553c615f11..222b251a38 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -88,6 +88,7 @@ extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; struct efi_handler { const efi_guid_t *guid; void *protocol_interface; + struct efi_open_protocol_info_entry open_info[4]; }; /* diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index ebb557abb2..e969814476 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -898,23 +898,78 @@ static efi_status_t EFIAPI efi_connect_controller( return EFI_EXIT(EFI_NOT_FOUND); } -static efi_status_t EFIAPI efi_disconnect_controller(void *controller_handle, - void *driver_image_handle, - void *child_handle) +static efi_status_t EFIAPI efi_disconnect_controller( + void *controller_handle, + void *driver_image_handle, + void *child_handle) { EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle, child_handle); return EFI_EXIT(EFI_INVALID_PARAMETER); } +static efi_status_t efi_close_protocol_int(struct efi_handler *protocol, + void *agent_handle, + void *controller_handle) +{ + size_t i; + struct efi_open_protocol_info_entry *open_info; + + for (i = 0; i < ARRAY_SIZE(protocol->open_info); ++i) { + open_info = &protocol->open_info[i]; + + if (!open_info->open_count) + continue; + + if (open_info->agent_handle == agent_handle && + open_info->controller_handle == + controller_handle) { + open_info->open_count--; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + static efi_status_t EFIAPI efi_close_protocol(void *handle, efi_guid_t *protocol, void *agent_handle, void *controller_handle) { + struct efi_object *efiobj; + size_t i; + efi_status_t r = EFI_NOT_FOUND; + EFI_ENTRY("%p, %p, %p, %p", handle, protocol, agent_handle, controller_handle); - return EFI_EXIT(EFI_NOT_FOUND); + + if (!handle || !protocol || !agent_handle) { + r = EFI_INVALID_PARAMETER; + goto out; + } + + EFI_PRINT_GUID("protocol:", protocol); + + list_for_each_entry(efiobj, &efi_obj_list, link) { + if (efiobj->handle != handle) + continue; + + for (i = 0; i < ARRAY_SIZE(efiobj->protocols); i++) { + struct efi_handler *handler = &efiobj->protocols[i]; + const efi_guid_t *hprotocol = handler->guid; + if (!hprotocol) + continue; + if (!guidcmp(hprotocol, protocol)) { + r = efi_close_protocol_int(handler, + agent_handle, + controller_handle); + goto out; + } + } + goto out; + } +out: + return EFI_EXIT(r); } static efi_status_t EFIAPI efi_open_protocol_information(efi_handle_t handle, @@ -1119,6 +1174,96 @@ static void EFIAPI efi_set_mem(void *buffer, unsigned long size, uint8_t value) memset(buffer, value, size); } +static efi_status_t efi_open_protocol_int( + struct efi_handler *protocol, + void **protocol_interface, void *agent_handle, + void *controller_handle, uint32_t attributes) +{ + bool opened_exclusive = false; + bool opened_by_driver = false; + int i; + struct efi_open_protocol_info_entry *open_info; + struct efi_open_protocol_info_entry *match = NULL; + + if (attributes != + EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { + *protocol_interface = NULL; + } + + for (i = 0; i < ARRAY_SIZE(protocol->open_info); ++i) { + open_info = &protocol->open_info[i]; + + if (!open_info->open_count) + continue; + if (open_info->agent_handle == agent_handle) { + if ((attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) && + (open_info->attributes == attributes)) + return EFI_ALREADY_STARTED; + if (open_info->controller_handle == controller_handle) + match = open_info; + } + if (open_info->attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) + opened_exclusive = true; + } + + if (attributes & + (EFI_OPEN_PROTOCOL_EXCLUSIVE | EFI_OPEN_PROTOCOL_BY_DRIVER) && + opened_exclusive) + return EFI_ACCESS_DENIED; + + if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) { + for (i = 0; i < ARRAY_SIZE(protocol->open_info); ++i) { + open_info = &protocol->open_info[i]; + + if (!open_info->open_count) + continue; + if (open_info->attributes == + EFI_OPEN_PROTOCOL_BY_DRIVER) + EFI_CALL(efi_disconnect_controller( + open_info->controller_handle, + open_info->agent_handle, + NULL)); + } + opened_by_driver = false; + for (i = 0; i < ARRAY_SIZE(protocol->open_info); ++i) { + open_info = &protocol->open_info[i]; + + if (!open_info->open_count) + continue; + if (open_info->attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) + opened_by_driver = true; + } + if (opened_by_driver) + return EFI_ACCESS_DENIED; + if (match && !match->open_count) + match = NULL; + } + + /* + * Find an empty slot. + */ + if (!match) { + for (i = 0; i < ARRAY_SIZE(protocol->open_info); ++i) { + open_info = &protocol->open_info[i]; + + if (!open_info->open_count) { + match = open_info; + break; + } + } + } + if (!match) + return EFI_OUT_OF_RESOURCES; + + match->agent_handle = agent_handle; + match->controller_handle = controller_handle; + match->attributes = attributes; + match->open_count++; + *protocol_interface = protocol->protocol_interface; + + return EFI_SUCCESS; +} + static efi_status_t EFIAPI efi_open_protocol( void *handle, efi_guid_t *protocol, void **protocol_interface, void *agent_handle, @@ -1173,12 +1318,11 @@ static efi_status_t EFIAPI efi_open_protocol( if (!hprotocol) continue; if (!guidcmp(hprotocol, protocol)) { - if (attributes != - EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { - *protocol_interface = - handler->protocol_interface; - } - r = EFI_SUCCESS; + r = efi_open_protocol_int(handler, + protocol_interface, + agent_handle, + controller_handle, + attributes); goto out; } }