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