All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v3 05/16] efi_loader: open_info in OpenProtocol
Date: Thu, 11 Jan 2018 08:15:58 +0100	[thread overview]
Message-ID: <20180111071609.4058-6-xypron.glpk@gmx.de> (raw)
In-Reply-To: <20180111071609.4058-1-xypron.glpk@gmx.de>

efi_open_protocol has to keep track of opened protocols.

OpenProtocol enters the agent and controller handle
information into this list.

A unit test is supplied with a subsequent patch.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
---
v3
	no change
v2
	no change
---
 lib/efi_loader/efi_boottime.c | 107 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 103 insertions(+), 4 deletions(-)

diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index f5ec2a8866..bb80c6066a 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -2100,6 +2100,101 @@ static void EFIAPI efi_set_mem(void *buffer, size_t size, uint8_t value)
 	EFI_EXIT(EFI_SUCCESS);
 }
 
+/*
+ * Open protocol interface on a handle.
+ *
+ * @handler		handler of a protocol
+ * @protocol_interface	interface implementing the protocol
+ * @agent_handle	handle of the driver
+ * @controller_handle	handle of the controller
+ * @attributes		attributes indicating how to open the protocol
+ * @return		status code
+ */
+static efi_status_t efi_protocol_open(
+			struct efi_handler *handler,
+			void **protocol_interface, void *agent_handle,
+			void *controller_handle, uint32_t attributes)
+{
+	struct efi_open_protocol_info_item *item;
+	struct efi_open_protocol_info_entry *match = NULL;
+	bool opened_by_driver = false;
+	bool opened_exclusive = false;
+
+	/* If there is no agent, only return the interface */
+	if (!agent_handle)
+		goto out;
+
+	/* For TEST_PROTOCOL ignore interface attribute */
+	if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+		*protocol_interface = NULL;
+
+	/*
+	 * Check if the protocol is already opened by a driver with the same
+	 * attributes or opened exclusively
+	 */
+	list_for_each_entry(item, &handler->open_infos, link) {
+		if (item->info.agent_handle == agent_handle) {
+			if ((attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) &&
+			    (item->info.attributes == attributes))
+				return EFI_ALREADY_STARTED;
+		}
+		if (item->info.attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE)
+			opened_exclusive = true;
+	}
+
+	/* Only one controller can open the protocol exclusively */
+	if (opened_exclusive && attributes &
+	    (EFI_OPEN_PROTOCOL_EXCLUSIVE | EFI_OPEN_PROTOCOL_BY_DRIVER))
+		return EFI_ACCESS_DENIED;
+
+	/* Prepare exclusive opening */
+	if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) {
+		/* Try to disconnect controllers */
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.attributes ==
+					EFI_OPEN_PROTOCOL_BY_DRIVER)
+				EFI_CALL(efi_disconnect_controller(
+						item->info.controller_handle,
+						item->info.agent_handle,
+						NULL));
+		}
+		opened_by_driver = false;
+		/* Check if all controllers are disconnected */
+		list_for_each_entry(item, &handler->open_infos, link) {
+			if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_DRIVER)
+				opened_by_driver = true;
+		}
+		/* Only one controller can be conncected */
+		if (opened_by_driver)
+			return EFI_ACCESS_DENIED;
+	}
+
+	/* Find existing entry */
+	list_for_each_entry(item, &handler->open_infos, link) {
+		if (item->info.agent_handle == agent_handle &&
+		    item->info.controller_handle == controller_handle)
+			match = &item->info;
+	}
+	/* None found, create one */
+	if (!match) {
+		match = efi_create_open_info(handler);
+		if (!match)
+			return EFI_OUT_OF_RESOURCES;
+	}
+
+	match->agent_handle = agent_handle;
+	match->controller_handle = controller_handle;
+	match->attributes = attributes;
+	match->open_count++;
+
+out:
+	/* For TEST_PROTOCOL ignore interface attribute. */
+	if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
+		*protocol_interface = handler->protocol_interface;
+
+	return EFI_SUCCESS;
+}
+
 /*
  * Open protocol interface on a handle.
  *
@@ -2141,12 +2236,16 @@ static efi_status_t EFIAPI efi_open_protocol(
 	case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
 		if (controller_handle == handle)
 			goto out;
+		/* fall-through */
 	case EFI_OPEN_PROTOCOL_BY_DRIVER:
 	case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
-		if (controller_handle == NULL)
+		/* Check that the controller handle is valid */
+		if (!efi_search_obj(controller_handle))
 			goto out;
+		/* fall-through */
 	case EFI_OPEN_PROTOCOL_EXCLUSIVE:
-		if (agent_handle == NULL)
+		/* Check that the agent handle is valid */
+		if (!efi_search_obj(agent_handle))
 			goto out;
 		break;
 	default:
@@ -2157,8 +2256,8 @@ static efi_status_t EFIAPI efi_open_protocol(
 	if (r != EFI_SUCCESS)
 		goto out;
 
-	if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL)
-		*protocol_interface = handler->protocol_interface;
+	r = efi_protocol_open(handler, protocol_interface, agent_handle,
+			      controller_handle, attributes);
 out:
 	return EFI_EXIT(r);
 }
-- 
2.14.2

  parent reply	other threads:[~2018-01-11  7:15 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-11  7:15 [U-Boot] [PATCH v3 00/16] efi_loader: implement driver management Heinrich Schuchardt
2018-01-11  7:15 ` [U-Boot] [PATCH v3 01/16] efi_selftest: colored test output Heinrich Schuchardt
2018-01-16 14:56   ` Simon Glass
2018-01-11  7:15 ` [U-Boot] [PATCH v3 02/16] efi_loader: simplify efi_remove_all_protocols Heinrich Schuchardt
2018-01-16 14:56   ` Simon Glass
2018-01-11  7:15 ` [U-Boot] [PATCH v3 03/16] efi_selftest: do not try to close device path protocol Heinrich Schuchardt
2018-01-16 14:56   ` Simon Glass
2018-01-11  7:15 ` [U-Boot] [PATCH v3 04/16] efi_loader: list of open protocol infos Heinrich Schuchardt
2018-01-11  7:15 ` Heinrich Schuchardt [this message]
2018-01-11  7:15 ` [U-Boot] [PATCH v3 06/16] efi_loader: open_info in CloseProtocol Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 07/16] efi_loader: implement OpenProtocolInformation Heinrich Schuchardt
2018-01-19 16:30   ` Alexander Graf
2018-01-11  7:16 ` [U-Boot] [PATCH v3 08/16] efi_loader: debug output installed device path Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 09/16] efi_loader: implement ConnectController Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 10/16] efi_loader: fix signature of efi_disconnect_controller Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 11/16] efi_loader: implement DisconnectController Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 12/16] efi_loader: disconnect controllers in UninstallProtocol Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 13/16] efi_selftest: remove todo in manage protocols Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 14/16] efi_selftest: remove todo in device path test Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 15/16] efi_selftest: test for (Dis)ConnectController Heinrich Schuchardt
2018-01-11  7:16 ` [U-Boot] [PATCH v3 16/16] efi_loader: consistently use efi_handle_t for handles Heinrich Schuchardt
2018-01-16 14:56   ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180111071609.4058-6-xypron.glpk@gmx.de \
    --to=xypron.glpk@gmx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.