xref: /netbsd-src/sys/external/bsd/gnu-efi/dist/lib/hand.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: hand.c,v 1.1.1.1 2014/04/01 16:16:07 jakllsch Exp $	*/
2 
3 /*++
4 
5 Copyright (c) 1998  Intel Corporation
6 
7 Module Name:
8 
9     hand.c
10 
11 Abstract:
12 
13 
14 
15 
16 Revision History
17 
18 --*/
19 
20 #include "lib.h"
21 #include "efistdarg.h"                        // !!!
22 
23 
24 EFI_STATUS
25 LibLocateProtocol (
26     IN  EFI_GUID    *ProtocolGuid,
27     OUT VOID        **Interface
28     )
29 //
30 // Find the first instance of this Protocol in the system and return it's interface
31 //
32 {
33     EFI_STATUS      Status;
34     UINTN           NumberHandles, Index;
35     EFI_HANDLE      *Handles;
36 
37 
38     *Interface = NULL;
39     Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles);
40     if (EFI_ERROR(Status)) {
41         DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n"));
42         return Status;
43     }
44 
45     for (Index=0; Index < NumberHandles; Index++) {
46         Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface);
47         if (!EFI_ERROR(Status)) {
48             break;
49         }
50     }
51 
52     if (Handles) {
53         FreePool (Handles);
54     }
55 
56     return Status;
57 }
58 
59 EFI_STATUS
60 LibLocateHandle (
61     IN EFI_LOCATE_SEARCH_TYPE       SearchType,
62     IN EFI_GUID                     *Protocol OPTIONAL,
63     IN VOID                         *SearchKey OPTIONAL,
64     IN OUT UINTN                    *NoHandles,
65     OUT EFI_HANDLE                  **Buffer
66     )
67 
68 {
69     EFI_STATUS          Status;
70     UINTN               BufferSize;
71 
72     //
73     // Initialize for GrowBuffer loop
74     //
75 
76     Status = EFI_SUCCESS;
77     *Buffer = NULL;
78     BufferSize = 50 * sizeof(EFI_HANDLE);
79 
80     //
81     // Call the real function
82     //
83 
84     while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
85 
86         Status = uefi_call_wrapper(
87 			BS->LocateHandle,
88 			5,
89                         SearchType,
90                         Protocol,
91                         SearchKey,
92                         &BufferSize,
93                         *Buffer
94                         );
95 
96     }
97 
98     *NoHandles = BufferSize / sizeof (EFI_HANDLE);
99     if (EFI_ERROR(Status)) {
100         *NoHandles = 0;
101     }
102 
103     return Status;
104 }
105 
106 EFI_STATUS
107 LibLocateHandleByDiskSignature (
108     IN UINT8                        MBRType,
109     IN UINT8                        SignatureType,
110     IN VOID                         *Signature,
111     IN OUT UINTN                    *NoHandles,
112     OUT EFI_HANDLE                  **Buffer
113     )
114 
115 {
116     EFI_STATUS            Status;
117     UINTN                 BufferSize;
118     UINTN                 NoBlockIoHandles;
119     EFI_HANDLE            *BlockIoBuffer;
120     EFI_DEVICE_PATH       *DevicePath;
121     UINTN                 Index;
122     EFI_DEVICE_PATH       *Start, *Next, *DevPath;
123     HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
124     BOOLEAN               Match;
125     BOOLEAN               PreviousNodeIsHardDriveDevicePath;
126 
127     //
128     // Initialize for GrowBuffer loop
129     //
130 
131     BlockIoBuffer = NULL;
132     BufferSize = 50 * sizeof(EFI_HANDLE);
133 
134     //
135     // Call the real function
136     //
137 
138     while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
139 
140         //
141         // Get list of device handles that support the BLOCK_IO Protocol.
142         //
143 
144         Status = uefi_call_wrapper(
145 			BS->LocateHandle,
146 			5,
147                         ByProtocol,
148                         &BlockIoProtocol,
149                         NULL,
150                         &BufferSize,
151                         BlockIoBuffer
152                         );
153 
154     }
155 
156     NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
157     if (EFI_ERROR(Status)) {
158         NoBlockIoHandles = 0;
159     }
160 
161     //
162     // If there was an error or there are no device handles that support
163     // the BLOCK_IO Protocol, then return.
164     //
165 
166     if (NoBlockIoHandles == 0) {
167         FreePool(BlockIoBuffer);
168         *NoHandles = 0;
169         *Buffer = NULL;
170         return Status;
171     }
172 
173     //
174     // Loop through all the device handles that support the BLOCK_IO Protocol
175     //
176 
177     *NoHandles = 0;
178 
179     for(Index=0;Index<NoBlockIoHandles;Index++) {
180 
181         Status = uefi_call_wrapper(
182 				     BS->HandleProtocol,
183 					3,
184 				     BlockIoBuffer[Index],
185                                      &DevicePathProtocol,
186                                      (VOID*)&DevicePath
187                                      );
188 
189         //
190         // Search DevicePath for a Hard Drive Media Device Path node.
191         // If one is found, then see if it matches the signature that was
192         // passed in.  If it does match, and the next node is the End of the
193         // device path, and the previous node is not a Hard Drive Media Device
194         // Path, then we have found a match.
195         //
196 
197         Match = FALSE;
198 
199         if (DevicePath != NULL) {
200 
201             PreviousNodeIsHardDriveDevicePath = FALSE;
202 
203             DevPath = DevicePath;
204             Start = DevPath;
205 
206             //
207             // Check for end of device path type
208             //
209 
210             for (; ;) {
211 
212                 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
213                     (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
214 
215                     HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
216 
217                     if (PreviousNodeIsHardDriveDevicePath == FALSE) {
218 
219                         Next = NextDevicePathNode(DevPath);
220                         if (IsDevicePathEndType(Next)) {
221                             if ((HardDriveDevicePath->MBRType == MBRType) &&
222                                 (HardDriveDevicePath->SignatureType == SignatureType)) {
223                                     switch(SignatureType) {
224                                         case SIGNATURE_TYPE_MBR:
225                                             if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
226                                                 Match = TRUE;
227                                             }
228                                             break;
229                                         case SIGNATURE_TYPE_GUID:
230                                             if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
231                                                 Match = TRUE;
232                                             }
233                                             break;
234                                     }
235                             }
236                         }
237                     }
238                     PreviousNodeIsHardDriveDevicePath = TRUE;
239                 } else {
240                     PreviousNodeIsHardDriveDevicePath = FALSE;
241                 }
242 
243                 if (IsDevicePathEnd(DevPath)) {
244                     break;
245                 }
246 
247                 DevPath = NextDevicePathNode(DevPath);
248             }
249 
250         }
251 
252         if (Match == FALSE) {
253             BlockIoBuffer[Index] = NULL;
254         } else {
255             *NoHandles = *NoHandles + 1;
256         }
257     }
258 
259     //
260     // If there are no matches, then return
261     //
262 
263     if (*NoHandles == 0) {
264         FreePool(BlockIoBuffer);
265         *NoHandles = 0;
266         *Buffer = NULL;
267         return EFI_SUCCESS;
268     }
269 
270     //
271     // Allocate space for the return buffer of device handles.
272     //
273 
274     *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
275 
276     if (*Buffer == NULL) {
277         FreePool(BlockIoBuffer);
278         *NoHandles = 0;
279         *Buffer = NULL;
280         return EFI_OUT_OF_RESOURCES;
281     }
282 
283     //
284     // Build list of matching device handles.
285     //
286 
287     *NoHandles = 0;
288     for(Index=0;Index<NoBlockIoHandles;Index++) {
289         if (BlockIoBuffer[Index] != NULL) {
290             (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
291             *NoHandles = *NoHandles + 1;
292         }
293     }
294 
295     FreePool(BlockIoBuffer);
296 
297     return EFI_SUCCESS;
298 }
299 
300 EFI_FILE_HANDLE
301 LibOpenRoot (
302     IN EFI_HANDLE               DeviceHandle
303     )
304 {
305     EFI_STATUS                  Status;
306     EFI_FILE_IO_INTERFACE       *Volume;
307     EFI_FILE_HANDLE             File;
308 
309 
310     //
311     // File the file system interface to the device
312     //
313 
314     Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
315 
316     //
317     // Open the root directory of the volume
318     //
319 
320     if (!EFI_ERROR(Status)) {
321         Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
322     }
323 
324     //
325     // Done
326     //
327 
328     return EFI_ERROR(Status) ? NULL : File;
329 }
330 
331 EFI_FILE_INFO *
332 LibFileInfo (
333     IN EFI_FILE_HANDLE      FHand
334     )
335 {
336     EFI_STATUS              Status;
337     EFI_FILE_INFO           *Buffer;
338     UINTN                   BufferSize;
339 
340     //
341     // Initialize for GrowBuffer loop
342     //
343 
344     Buffer = NULL;
345     BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
346 
347     //
348     // Call the real function
349     //
350 
351     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
352         Status = uefi_call_wrapper(
353 		    FHand->GetInfo,
354 			4,
355                     FHand,
356                     &GenericFileInfo,
357                     &BufferSize,
358                     Buffer
359                     );
360     }
361 
362     return Buffer;
363 }
364 
365 
366 EFI_FILE_SYSTEM_INFO *
367 LibFileSystemInfo (
368     IN EFI_FILE_HANDLE      FHand
369     )
370 {
371     EFI_STATUS              Status;
372     EFI_FILE_SYSTEM_INFO    *Buffer;
373     UINTN                   BufferSize;
374 
375     //
376     // Initialize for GrowBuffer loop
377     //
378 
379     Buffer = NULL;
380     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
381 
382     //
383     // Call the real function
384     //
385 
386     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
387         Status = uefi_call_wrapper(
388 		    FHand->GetInfo,
389 			4,
390                     FHand,
391                     &FileSystemInfo,
392                     &BufferSize,
393                     Buffer
394                     );
395     }
396 
397     return Buffer;
398 }
399 
400 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
401 LibFileSystemVolumeLabelInfo (
402     IN EFI_FILE_HANDLE      FHand
403     )
404 {
405     EFI_STATUS                        Status;
406     EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
407     UINTN                             BufferSize;
408 
409     //
410     // Initialize for GrowBuffer loop
411     //
412 
413     Buffer = NULL;
414     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
415 
416     //
417     // Call the real function
418     //
419 
420     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
421         Status = uefi_call_wrapper(
422 		    FHand->GetInfo,
423 			4,
424                     FHand,
425                     &FileSystemVolumeLabelInfo,
426                     &BufferSize,
427                     Buffer
428                     );
429     }
430 
431     return Buffer;
432 }
433 
434 
435 
436 EFI_STATUS
437 LibInstallProtocolInterfaces (
438     IN OUT EFI_HANDLE           *Handle,
439     ...
440     )
441 {
442     va_list         args;
443     EFI_STATUS      Status;
444     EFI_GUID        *Protocol;
445     VOID            *Interface;
446     EFI_TPL         OldTpl;
447     UINTN           Index;
448     EFI_HANDLE      OldHandle;
449 
450     //
451     // Syncronize with notifcations
452     //
453 
454     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
455     OldHandle = *Handle;
456 
457     //
458     // Install the protocol interfaces
459     //
460 
461     Index = 0;
462     Status = EFI_SUCCESS;
463     va_start (args, Handle);
464 
465     while (!EFI_ERROR(Status)) {
466 
467         //
468         // If protocol is NULL, then it's the end of the list
469         //
470 
471         Protocol = va_arg(args, EFI_GUID *);
472         if (!Protocol) {
473             break;
474         }
475 
476         Interface = va_arg(args, VOID *);
477 
478         //
479         // Install it
480         //
481 
482         DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
483         Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
484         if (EFI_ERROR(Status)) {
485             break;
486         }
487 
488         Index += 1;
489     }
490 
491     //
492     // If there was an error, remove all the interfaces that were
493     // installed without any errors
494     //
495 
496     if (EFI_ERROR(Status)) {
497         va_start (args, Handle);
498         while (Index) {
499 
500             Protocol = va_arg(args, EFI_GUID *);
501             Interface = va_arg(args, VOID *);
502             uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
503 
504             Index -= 1;
505         }
506 
507         *Handle = OldHandle;
508     }
509 
510     //
511     // Done
512     //
513 
514     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
515     return Status;
516 }
517 
518 
519 VOID
520 LibUninstallProtocolInterfaces (
521     IN EFI_HANDLE           Handle,
522     ...
523     )
524 {
525     va_list         args;
526     EFI_STATUS      Status;
527     EFI_GUID        *Protocol;
528     VOID            *Interface;
529 
530 
531     va_start (args, Handle);
532     for (; ;) {
533 
534         //
535         // If protocol is NULL, then it's the end of the list
536         //
537 
538         Protocol = va_arg(args, EFI_GUID *);
539         if (!Protocol) {
540             break;
541         }
542 
543         Interface = va_arg(args, VOID *);
544 
545         //
546         // Uninstall it
547         //
548 
549         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
550         if (EFI_ERROR(Status)) {
551             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
552         }
553     }
554 }
555 
556 
557 EFI_STATUS
558 LibReinstallProtocolInterfaces (
559     IN OUT EFI_HANDLE           *Handle,
560     ...
561     )
562 {
563     va_list         args;
564     EFI_STATUS      Status;
565     EFI_GUID        *Protocol;
566     VOID            *OldInterface, *NewInterface;
567     EFI_TPL         OldTpl;
568     UINTN           Index;
569 
570     //
571     // Syncronize with notifcations
572     //
573 
574     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
575 
576     //
577     // Install the protocol interfaces
578     //
579 
580     Index = 0;
581     Status = EFI_SUCCESS;
582     va_start (args, Handle);
583 
584     while (!EFI_ERROR(Status)) {
585 
586         //
587         // If protocol is NULL, then it's the end of the list
588         //
589 
590         Protocol = va_arg(args, EFI_GUID *);
591         if (!Protocol) {
592             break;
593         }
594 
595         OldInterface = va_arg(args, VOID *);
596         NewInterface = va_arg(args, VOID *);
597 
598         //
599         // Reinstall it
600         //
601 
602         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
603         if (EFI_ERROR(Status)) {
604             break;
605         }
606 
607         Index += 1;
608     }
609 
610     //
611     // If there was an error, undo all the interfaces that were
612     // reinstalled without any errors
613     //
614 
615     if (EFI_ERROR(Status)) {
616         va_start (args, Handle);
617         while (Index) {
618 
619             Protocol = va_arg(args, EFI_GUID *);
620             OldInterface = va_arg(args, VOID *);
621             NewInterface = va_arg(args, VOID *);
622 
623             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
624 
625             Index -= 1;
626         }
627     }
628 
629     //
630     // Done
631     //
632 
633     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
634     return Status;
635 }
636