Commit 191a41cc3295f1f468f70fe52b4b2ec93992abce
Committed by
Alexander Graf
1 parent
fe1599daf5
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
efi_loader: open_info in OpenProtocol
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> Signed-off-by: Alexander Graf <agraf@suse.de>
Showing 1 changed file with 103 additions and 4 deletions Side-by-side Diff
lib/efi_loader/efi_boottime.c
... | ... | @@ -2123,6 +2123,101 @@ |
2123 | 2123 | /* |
2124 | 2124 | * Open protocol interface on a handle. |
2125 | 2125 | * |
2126 | + * @handler handler of a protocol | |
2127 | + * @protocol_interface interface implementing the protocol | |
2128 | + * @agent_handle handle of the driver | |
2129 | + * @controller_handle handle of the controller | |
2130 | + * @attributes attributes indicating how to open the protocol | |
2131 | + * @return status code | |
2132 | + */ | |
2133 | +static efi_status_t efi_protocol_open( | |
2134 | + struct efi_handler *handler, | |
2135 | + void **protocol_interface, void *agent_handle, | |
2136 | + void *controller_handle, uint32_t attributes) | |
2137 | +{ | |
2138 | + struct efi_open_protocol_info_item *item; | |
2139 | + struct efi_open_protocol_info_entry *match = NULL; | |
2140 | + bool opened_by_driver = false; | |
2141 | + bool opened_exclusive = false; | |
2142 | + | |
2143 | + /* If there is no agent, only return the interface */ | |
2144 | + if (!agent_handle) | |
2145 | + goto out; | |
2146 | + | |
2147 | + /* For TEST_PROTOCOL ignore interface attribute */ | |
2148 | + if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) | |
2149 | + *protocol_interface = NULL; | |
2150 | + | |
2151 | + /* | |
2152 | + * Check if the protocol is already opened by a driver with the same | |
2153 | + * attributes or opened exclusively | |
2154 | + */ | |
2155 | + list_for_each_entry(item, &handler->open_infos, link) { | |
2156 | + if (item->info.agent_handle == agent_handle) { | |
2157 | + if ((attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) && | |
2158 | + (item->info.attributes == attributes)) | |
2159 | + return EFI_ALREADY_STARTED; | |
2160 | + } | |
2161 | + if (item->info.attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) | |
2162 | + opened_exclusive = true; | |
2163 | + } | |
2164 | + | |
2165 | + /* Only one controller can open the protocol exclusively */ | |
2166 | + if (opened_exclusive && attributes & | |
2167 | + (EFI_OPEN_PROTOCOL_EXCLUSIVE | EFI_OPEN_PROTOCOL_BY_DRIVER)) | |
2168 | + return EFI_ACCESS_DENIED; | |
2169 | + | |
2170 | + /* Prepare exclusive opening */ | |
2171 | + if (attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) { | |
2172 | + /* Try to disconnect controllers */ | |
2173 | + list_for_each_entry(item, &handler->open_infos, link) { | |
2174 | + if (item->info.attributes == | |
2175 | + EFI_OPEN_PROTOCOL_BY_DRIVER) | |
2176 | + EFI_CALL(efi_disconnect_controller( | |
2177 | + item->info.controller_handle, | |
2178 | + item->info.agent_handle, | |
2179 | + NULL)); | |
2180 | + } | |
2181 | + opened_by_driver = false; | |
2182 | + /* Check if all controllers are disconnected */ | |
2183 | + list_for_each_entry(item, &handler->open_infos, link) { | |
2184 | + if (item->info.attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) | |
2185 | + opened_by_driver = true; | |
2186 | + } | |
2187 | + /* Only one controller can be conncected */ | |
2188 | + if (opened_by_driver) | |
2189 | + return EFI_ACCESS_DENIED; | |
2190 | + } | |
2191 | + | |
2192 | + /* Find existing entry */ | |
2193 | + list_for_each_entry(item, &handler->open_infos, link) { | |
2194 | + if (item->info.agent_handle == agent_handle && | |
2195 | + item->info.controller_handle == controller_handle) | |
2196 | + match = &item->info; | |
2197 | + } | |
2198 | + /* None found, create one */ | |
2199 | + if (!match) { | |
2200 | + match = efi_create_open_info(handler); | |
2201 | + if (!match) | |
2202 | + return EFI_OUT_OF_RESOURCES; | |
2203 | + } | |
2204 | + | |
2205 | + match->agent_handle = agent_handle; | |
2206 | + match->controller_handle = controller_handle; | |
2207 | + match->attributes = attributes; | |
2208 | + match->open_count++; | |
2209 | + | |
2210 | +out: | |
2211 | + /* For TEST_PROTOCOL ignore interface attribute. */ | |
2212 | + if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) | |
2213 | + *protocol_interface = handler->protocol_interface; | |
2214 | + | |
2215 | + return EFI_SUCCESS; | |
2216 | +} | |
2217 | + | |
2218 | +/* | |
2219 | + * Open protocol interface on a handle. | |
2220 | + * | |
2126 | 2221 | * This function implements the OpenProtocol interface. |
2127 | 2222 | * See the Unified Extensible Firmware Interface (UEFI) specification |
2128 | 2223 | * for details. |
2129 | 2224 | |
2130 | 2225 | |
2131 | 2226 | |
... | ... | @@ -2161,12 +2256,16 @@ |
2161 | 2256 | case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER: |
2162 | 2257 | if (controller_handle == handle) |
2163 | 2258 | goto out; |
2259 | + /* fall-through */ | |
2164 | 2260 | case EFI_OPEN_PROTOCOL_BY_DRIVER: |
2165 | 2261 | case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE: |
2166 | - if (controller_handle == NULL) | |
2262 | + /* Check that the controller handle is valid */ | |
2263 | + if (!efi_search_obj(controller_handle)) | |
2167 | 2264 | goto out; |
2265 | + /* fall-through */ | |
2168 | 2266 | case EFI_OPEN_PROTOCOL_EXCLUSIVE: |
2169 | - if (agent_handle == NULL) | |
2267 | + /* Check that the agent handle is valid */ | |
2268 | + if (!efi_search_obj(agent_handle)) | |
2170 | 2269 | goto out; |
2171 | 2270 | break; |
2172 | 2271 | default: |
... | ... | @@ -2177,8 +2276,8 @@ |
2177 | 2276 | if (r != EFI_SUCCESS) |
2178 | 2277 | goto out; |
2179 | 2278 | |
2180 | - if (attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) | |
2181 | - *protocol_interface = handler->protocol_interface; | |
2279 | + r = efi_protocol_open(handler, protocol_interface, agent_handle, | |
2280 | + controller_handle, attributes); | |
2182 | 2281 | out: |
2183 | 2282 | return EFI_EXIT(r); |
2184 | 2283 | } |