]> code.delx.au - refind/blob - refind/driver_support.c
Modified SIP/CSR feature to work ON MACS when the csr-active-config
[refind] / refind / driver_support.c
1 /*
2 * Functions related to drivers. Original copyright notices below....
3 */
4 /*
5 * Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
6 * This program and the accompanying materials are licensed and made available under
7 * the terms and conditions of the BSD License that accompanies this distribution.
8 * The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php.
10 *
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 */
15 /*
16 * refit/main.c
17 * Main code for the boot menu
18 *
19 * Copyright (c) 2006-2010 Christoph Pfisterer
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions are
24 * met:
25 *
26 * * Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 *
29 * * Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the
32 * distribution.
33 *
34 * * Neither the name of Christoph Pfisterer nor the names of the
35 * contributors may be used to endorse or promote products derived
36 * from this software without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
39 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
40 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
41 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
42 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
48 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 */
50 /*
51 * Modifications copyright (c) 2012-2016 Roderick W. Smith
52 *
53 * Modifications distributed under the terms of the GNU General Public
54 * License (GPL) version 3 (GPLv3), or (at your option) any later version.
55 *
56 */
57 /*
58 * This program is free software: you can redistribute it and/or modify
59 * it under the terms of the GNU General Public License as published by
60 * the Free Software Foundation, either version 3 of the License, or
61 * (at your option) any later version.
62 *
63 * This program is distributed in the hope that it will be useful,
64 * but WITHOUT ANY WARRANTY; without even the implied warranty of
65 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 * GNU General Public License for more details.
67 *
68 * You should have received a copy of the GNU General Public License
69 * along with this program. If not, see <http://www.gnu.org/licenses/>.
70 */
71
72 #include "driver_support.h"
73 #include "lib.h"
74 #include "mystrings.h"
75 #include "screen.h"
76 #include "../include/refit_call_wrapper.h"
77
78 #if defined (EFIX64)
79 #define DRIVER_DIRS L"drivers,drivers_x64"
80 #elif defined (EFI32)
81 #define DRIVER_DIRS L"drivers,drivers_ia32"
82 #elif defined (EFIAARCH64)
83 #define DRIVER_DIRS L"drivers,drivers_aa64"
84 #endif
85
86 #ifdef __MAKEWITH_GNUEFI
87 // Following "global" constants are from EDK2's AutoGen.c....
88 EFI_GUID gEfiLoadedImageProtocolGuid = { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
89 EFI_GUID gEfiDriverBindingProtocolGuid = { 0x18A031AB, 0xB443, 0x4D1A, { 0xA5, 0xC0, 0x0C, 0x09, 0x26, 0x1E, 0x9F, 0x71 }};
90 EFI_GUID gEfiDriverConfiguration2ProtocolGuid = { 0xBFD7DC1D, 0x24F1, 0x40D9, { 0x82, 0xE7, 0x2E, 0x09, 0xBB, 0x6B, 0x4E, 0xBE }};
91 EFI_GUID gEfiDriverConfigurationProtocolGuid = { 0x107A772B, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
92 EFI_GUID gEfiDriverDiagnosticsProtocolGuid = { 0x0784924F, 0xE296, 0x11D4, { 0x9A, 0x49, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
93 EFI_GUID gEfiDriverDiagnostics2ProtocolGuid = { 0x4D330321, 0x025F, 0x4AAC, { 0x90, 0xD8, 0x5E, 0xD9, 0x00, 0x17, 0x3B, 0x63 }};
94 EFI_GUID gEfiComponentNameProtocolGuid = { 0x107A772C, 0xD5E1, 0x11D4, { 0x9A, 0x46, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }};
95 EFI_GUID gEfiComponentName2ProtocolGuid = { 0x6A7A5CFF, 0xE8D9, 0x4F70, { 0xBA, 0xDA, 0x75, 0xAB, 0x30, 0x25, 0xCE, 0x14 }};
96 EFI_GUID gEfiDevicePathProtocolGuid = { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
97 EFI_GUID gEfiDiskIoProtocolGuid = { 0xCE345171, 0xBA0B, 0x11D2, { 0x8E, 0x4F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
98 EFI_GUID gEfiBlockIoProtocolGuid = { 0x964E5B21, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
99 EFI_GUID gEfiSimpleFileSystemProtocolGuid = { 0x964E5B22, 0x6459, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
100
101 struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
102 struct EFI_FILE_PROTOCOL;
103
104 typedef
105 EFI_STATUS
106 (EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME)(
107 IN struct EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
108 OUT struct EFI_FILE_PROTOCOL **Root
109 );
110
111 typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL {
112 UINT64 Revision;
113 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume;
114 } EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
115
116 typedef struct _EFI_FILE_PROTOCOL {
117 UINT64 Revision;
118 EFI_FILE_OPEN Open;
119 EFI_FILE_CLOSE Close;
120 EFI_FILE_DELETE Delete;
121 EFI_FILE_READ Read;
122 EFI_FILE_WRITE Write;
123 EFI_FILE_GET_POSITION GetPosition;
124 EFI_FILE_SET_POSITION SetPosition;
125 EFI_FILE_GET_INFO GetInfo;
126 EFI_FILE_SET_INFO SetInfo;
127 EFI_FILE_FLUSH Flush;
128 } EFI_FILE_PROTOCOL;
129
130 typedef struct _EFI_BLOCK_IO_PROTOCOL {
131 UINT64 Revision;
132 EFI_BLOCK_IO_MEDIA *Media;
133 EFI_BLOCK_RESET Reset;
134 EFI_BLOCK_READ ReadBlocks;
135 EFI_BLOCK_WRITE WriteBlocks;
136 EFI_BLOCK_FLUSH FlushBlocks;
137 } EFI_BLOCK_IO_PROTOCOL;
138 #endif
139
140 /* LibScanHandleDatabase() is used by rEFInd's driver-loading code (inherited
141 * from rEFIt), but has not been implemented in GNU-EFI and seems to have been
142 * dropped from current versions of the Tianocore library. This function was
143 * taken from http://git.etherboot.org/?p=mirror/efi/shell/.git;a=commitdiff;h=b1b0c63423cac54dc964c2930e04aebb46a946ec,
144 * The original files are copyright 2006-2011 Intel and BSD-licensed. Minor
145 * modifications by Roderick Smith are GPLv3.
146 */
147 EFI_STATUS
148 LibScanHandleDatabase (EFI_HANDLE DriverBindingHandle, OPTIONAL
149 UINT32 *DriverBindingHandleIndex, OPTIONAL
150 EFI_HANDLE ControllerHandle, OPTIONAL
151 UINT32 *ControllerHandleIndex, OPTIONAL
152 UINTN *HandleCount,
153 EFI_HANDLE **HandleBuffer,
154 UINT32 **HandleType) {
155 EFI_STATUS Status;
156 UINTN HandleIndex;
157 EFI_GUID **ProtocolGuidArray;
158 UINTN ArrayCount;
159 UINTN ProtocolIndex;
160 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
161 UINTN OpenInfoCount;
162 UINTN OpenInfoIndex;
163 UINTN ChildIndex;
164 BOOLEAN DriverBindingHandleIndexValid;
165
166 DriverBindingHandleIndexValid = FALSE;
167 if (DriverBindingHandleIndex != NULL) {
168 *DriverBindingHandleIndex = 0xffffffff;
169 }
170
171 if (ControllerHandleIndex != NULL) {
172 *ControllerHandleIndex = 0xffffffff;
173 }
174
175 *HandleCount = 0;
176 *HandleBuffer = NULL;
177 *HandleType = NULL;
178
179 //
180 // Retrieve the list of all handles from the handle database
181 //
182
183 Status = refit_call5_wrapper(BS->LocateHandleBuffer,
184 AllHandles,
185 NULL,
186 NULL,
187 HandleCount,
188 HandleBuffer
189 );
190 if (EFI_ERROR (Status)) {
191 goto Error;
192 }
193
194 *HandleType = AllocatePool (*HandleCount * sizeof (UINT32));
195 if (*HandleType == NULL) {
196 goto Error;
197 }
198
199 for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
200 //
201 // Assume that the handle type is unknown
202 //
203 (*HandleType)[HandleIndex] = EFI_HANDLE_TYPE_UNKNOWN;
204
205 if (DriverBindingHandle != NULL &&
206 DriverBindingHandleIndex != NULL &&
207 (*HandleBuffer)[HandleIndex] == DriverBindingHandle
208 ) {
209 *DriverBindingHandleIndex = (UINT32) HandleIndex;
210 DriverBindingHandleIndexValid = TRUE;
211 }
212
213 if (ControllerHandle != NULL && ControllerHandleIndex != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
214 *ControllerHandleIndex = (UINT32) HandleIndex;
215 }
216
217 }
218
219 for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
220 //
221 // Retrieve the list of all the protocols on each handle
222 //
223
224 Status = refit_call3_wrapper(BS->ProtocolsPerHandle,
225 (*HandleBuffer)[HandleIndex],
226 &ProtocolGuidArray,
227 &ArrayCount
228 );
229 if (!EFI_ERROR (Status)) {
230
231 for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
232
233 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) == 0) {
234 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_IMAGE_HANDLE;
235 }
236
237 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) == 0) {
238 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE;
239 }
240
241 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) == 0) {
242 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_CONFIGURATION_HANDLE;
243 }
244
245 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) == 0) {
246 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DRIVER_DIAGNOSTICS_HANDLE;
247 }
248
249 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) == 0) {
250 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_COMPONENT_NAME_HANDLE;
251 }
252
253 if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) == 0) {
254 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_DEVICE_HANDLE;
255 }
256 //
257 // Retrieve the list of agents that have opened each protocol
258 //
259
260 Status = refit_call4_wrapper(BS->OpenProtocolInformation,
261 (*HandleBuffer)[HandleIndex],
262 ProtocolGuidArray[ProtocolIndex],
263 &OpenInfo,
264 &OpenInfoCount
265 );
266 if (!EFI_ERROR (Status)) {
267
268 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
269 if (DriverBindingHandle != NULL && OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
270 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
271 //
272 // Mark the device handle as being managed by the driver specified by DriverBindingHandle
273 //
274 (*HandleType)[HandleIndex] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE | EFI_HANDLE_TYPE_CONTROLLER_HANDLE);
275 //
276 // Mark the DriverBindingHandle as being a driver that is managing at least one controller
277 //
278 if (DriverBindingHandleIndexValid) {
279 (*HandleType)[*DriverBindingHandleIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER;
280 }
281 }
282
283 if ((
284 OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
285 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
286 ) {
287 //
288 // Mark the DriverBindingHandle as being a driver that is managing at least one child controller
289 //
290 if (DriverBindingHandleIndexValid) {
291 (*HandleType)[*DriverBindingHandleIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER;
292 }
293 }
294
295 if (ControllerHandle != NULL && (*HandleBuffer)[HandleIndex] == ControllerHandle) {
296 if ((
297 OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
298 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
299 ) {
300 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
301 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].ControllerHandle) {
302 (*HandleType)[ChildIndex] |= (EFI_HANDLE_TYPE_DEVICE_HANDLE | EFI_HANDLE_TYPE_CHILD_HANDLE);
303 }
304 }
305 }
306 }
307 }
308
309 if (DriverBindingHandle == NULL && OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
310 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
311 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
312 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
313 (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_DEVICE_DRIVER;
314 }
315 }
316 }
317
318 if ((
319 OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
320 ) == EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
321 ) {
322 (*HandleType)[HandleIndex] |= EFI_HANDLE_TYPE_PARENT_HANDLE;
323 for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
324 if ((*HandleBuffer)[ChildIndex] == OpenInfo[OpenInfoIndex].AgentHandle) {
325 (*HandleType)[ChildIndex] |= EFI_HANDLE_TYPE_BUS_DRIVER;
326 }
327 }
328 }
329 }
330 }
331
332 MyFreePool (OpenInfo);
333 }
334 }
335
336 MyFreePool (ProtocolGuidArray);
337 }
338 }
339
340 return EFI_SUCCESS;
341
342 Error:
343 MyFreePool (*HandleType);
344 MyFreePool (*HandleBuffer);
345
346 *HandleCount = 0;
347 *HandleBuffer = NULL;
348 *HandleType = NULL;
349
350 return Status;
351 } /* EFI_STATUS LibScanHandleDatabase() */
352
353 #ifdef __MAKEWITH_GNUEFI
354 /* Modified from EDK2 function of a similar name; original copyright Intel &
355 * BSD-licensed; modifications by Roderick Smith are GPLv3. */
356 EFI_STATUS ConnectAllDriversToAllControllers(VOID)
357 {
358 EFI_STATUS Status;
359 UINTN AllHandleCount;
360 EFI_HANDLE *AllHandleBuffer;
361 UINTN Index;
362 UINTN HandleCount;
363 EFI_HANDLE *HandleBuffer;
364 UINT32 *HandleType;
365 UINTN HandleIndex;
366 BOOLEAN Parent;
367 BOOLEAN Device;
368
369 Status = LibLocateHandle(AllHandles,
370 NULL,
371 NULL,
372 &AllHandleCount,
373 &AllHandleBuffer);
374 if (EFI_ERROR(Status))
375 return Status;
376
377 for (Index = 0; Index < AllHandleCount; Index++) {
378 //
379 // Scan the handle database
380 //
381 Status = LibScanHandleDatabase(NULL,
382 NULL,
383 AllHandleBuffer[Index],
384 NULL,
385 &HandleCount,
386 &HandleBuffer,
387 &HandleType);
388 if (EFI_ERROR (Status))
389 goto Done;
390
391 Device = TRUE;
392 if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE)
393 Device = FALSE;
394 if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE)
395 Device = FALSE;
396
397 if (Device) {
398 Parent = FALSE;
399 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
400 if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE)
401 Parent = TRUE;
402 } // for
403
404 if (!Parent) {
405 if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE) {
406 Status = refit_call4_wrapper(BS->ConnectController,
407 AllHandleBuffer[Index],
408 NULL,
409 NULL,
410 TRUE);
411 }
412 }
413 }
414
415 MyFreePool (HandleBuffer);
416 MyFreePool (HandleType);
417 }
418
419 Done:
420 MyFreePool (AllHandleBuffer);
421 return Status;
422 } /* EFI_STATUS ConnectAllDriversToAllControllers() */
423 #else
424 EFI_STATUS ConnectAllDriversToAllControllers(VOID) {
425 BdsLibConnectAllDriversToAllControllers();
426 return 0;
427 }
428 #endif
429
430 /*
431 * ConnectFilesystemDriver() is modified from DisconnectInvalidDiskIoChildDrivers()
432 * in Clover (https://sourceforge.net/projects/cloverefiboot/), which is derived
433 * from rEFIt. The refit/main.c file from which this function was taken continues
434 * to bear rEFIt's original copyright/licence notice (BSD); modifications by
435 * Roderick Smith (2016) are GPLv3.
436 */
437 /**
438 * Some UEFI's (like HPQ EFI from HP notebooks) have DiskIo protocols
439 * opened BY_DRIVER (by Partition driver in HP case) even when no file system
440 * is produced from this DiskIo. This then blocks our FS drivers from connecting
441 * and producing file systems.
442 * To fix it: we will disconnect drivers that connected to DiskIo BY_DRIVER
443 * if this is partition volume and if those drivers did not produce file system,
444 * then try to connect every unconnected device to the driver whose handle is
445 * passed to us. This should have no effect on systems unaffected by this EFI
446 * bug/quirk.
447 */
448 VOID ConnectFilesystemDriver(EFI_HANDLE DriverHandle) {
449 EFI_STATUS Status;
450 UINTN HandleCount = 0;
451 UINTN Index;
452 UINTN OpenInfoIndex;
453 EFI_HANDLE *Handles = NULL;
454 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
455 EFI_BLOCK_IO_PROTOCOL *BlockIo;
456 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
457 UINTN OpenInfoCount;
458 EFI_HANDLE DriverHandleList[2];
459
460 //
461 // Get all DiskIo handles
462 //
463 Status = refit_call5_wrapper(gBS->LocateHandleBuffer,
464 ByProtocol,
465 &gEfiDiskIoProtocolGuid,
466 NULL,
467 &HandleCount,
468 &Handles);
469 if (EFI_ERROR(Status) || HandleCount == 0)
470 return;
471
472 //
473 // Check every DiskIo handle
474 //
475 for (Index = 0; Index < HandleCount; Index++) {
476 //
477 // If this is not partition - skip it.
478 // This is then whole disk and DiskIo
479 // should be opened here BY_DRIVER by Partition driver
480 // to produce partition volumes.
481 //
482 Status = refit_call3_wrapper(gBS->HandleProtocol,
483 Handles[Index],
484 &gEfiBlockIoProtocolGuid,
485 (VOID **) &BlockIo);
486 if (EFI_ERROR (Status))
487 continue;
488 if (BlockIo->Media == NULL || !BlockIo->Media->LogicalPartition)
489 continue;
490
491 //
492 // If SimpleFileSystem is already produced - skip it, this is ok
493 //
494 Status = refit_call3_wrapper(gBS->HandleProtocol,
495 Handles[Index],
496 &gEfiSimpleFileSystemProtocolGuid,
497 (VOID **) &Fs);
498 if (Status == EFI_SUCCESS)
499 continue;
500
501 //
502 // If no SimpleFileSystem on this handle but DiskIo is opened BY_DRIVER
503 // then disconnect this connection and try to connect our driver to it
504 //
505 Status = refit_call4_wrapper(gBS->OpenProtocolInformation,
506 Handles[Index],
507 &gEfiDiskIoProtocolGuid,
508 &OpenInfo,
509 &OpenInfoCount);
510 if (EFI_ERROR (Status))
511 continue;
512 DriverHandleList[1] = NULL;
513 for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
514 if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) {
515 Status = refit_call3_wrapper(gBS->DisconnectController,
516 Handles[Index],
517 OpenInfo[OpenInfoIndex].AgentHandle,
518 NULL);
519 if (!(EFI_ERROR(Status))) {
520 DriverHandleList[0] = DriverHandle;
521 refit_call4_wrapper(gBS->ConnectController,
522 Handles[Index],
523 DriverHandleList,
524 NULL,
525 FALSE);
526 } // if
527 } // if
528 } // for
529 FreePool (OpenInfo);
530 }
531 FreePool(Handles);
532 } // VOID ConnectFilesystemDriver()
533
534 // Scan a directory for drivers.
535 // Originally from rEFIt's main.c (BSD), but modified since then (GPLv3).
536 static UINTN ScanDriverDir(IN CHAR16 *Path)
537 {
538 EFI_STATUS Status;
539 REFIT_DIR_ITER DirIter;
540 UINTN NumFound = 0;
541 EFI_FILE_INFO *DirEntry;
542 CHAR16 FileName[256];
543
544 CleanUpPathNameSlashes(Path);
545 // look through contents of the directory
546 DirIterOpen(SelfRootDir, Path, &DirIter);
547 while (DirIterNext(&DirIter, 2, LOADER_MATCH_PATTERNS, &DirEntry)) {
548 if (DirEntry->FileName[0] == '.')
549 continue; // skip this
550
551 SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName);
552 NumFound++;
553 Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName),
554 L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE);
555 }
556 Status = DirIterClose(&DirIter);
557 if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) {
558 SPrint(FileName, 255, L"while scanning the %s directory", Path);
559 CheckError(Status, FileName);
560 }
561 return (NumFound);
562 } // static UINTN ScanDriverDir()
563
564
565 // Load all EFI drivers from rEFInd's "drivers" subdirectory and from the
566 // directories specified by the user in the "scan_driver_dirs" configuration
567 // file line.
568 // Originally from rEFIt's main.c (BSD), but modified since then (GPLv3).
569 VOID LoadDrivers(VOID) {
570 CHAR16 *Directory, *SelfDirectory;
571 UINTN i = 0, Length, NumFound = 0;
572
573 // load drivers from the subdirectories of rEFInd's home directory specified
574 // in the DRIVER_DIRS constant.
575 while ((Directory = FindCommaDelimited(DRIVER_DIRS, i++)) != NULL) {
576 SelfDirectory = SelfDirPath ? StrDuplicate(SelfDirPath) : NULL;
577 CleanUpPathNameSlashes(SelfDirectory);
578 MergeStrings(&SelfDirectory, Directory, L'\\');
579 NumFound += ScanDriverDir(SelfDirectory);
580 MyFreePool(Directory);
581 MyFreePool(SelfDirectory);
582 }
583
584 // Scan additional user-specified driver directories....
585 i = 0;
586 while ((Directory = FindCommaDelimited(GlobalConfig.DriverDirs, i++)) != NULL) {
587 CleanUpPathNameSlashes(Directory);
588 Length = StrLen(Directory);
589 if (Length > 0) {
590 NumFound += ScanDriverDir(Directory);
591 } // if
592 MyFreePool(Directory);
593 } // while
594
595 // connect all devices
596 if (NumFound > 0)
597 ConnectAllDriversToAllControllers();
598 } /* VOID LoadDrivers() */