xref: /DragonStub/lib/hand.c (revision f1de0317e130286d7363f30f4f92961ab62fe191)
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     va_end (args);
492 
493     //
494     // If there was an error, remove all the interfaces that were
495     // installed without any errors
496     //
497 
498     if (EFI_ERROR(Status)) {
499         va_start (args, Handle);
500         while (Index) {
501 
502             Protocol = va_arg(args, EFI_GUID *);
503             Interface = va_arg(args, VOID *);
504             uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
505 
506             Index -= 1;
507         }
508 
509         *Handle = OldHandle;
510         va_end (args);
511     }
512 
513     //
514     // Done
515     //
516 
517     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
518     return Status;
519 }
520 
521 
522 VOID
523 LibUninstallProtocolInterfaces (
524     IN EFI_HANDLE           Handle,
525     ...
526     )
527 {
528     va_list         args;
529     EFI_STATUS      Status;
530     EFI_GUID        *Protocol;
531     VOID            *Interface;
532 
533 
534     va_start (args, Handle);
535     for (; ;) {
536 
537         //
538         // If protocol is NULL, then it's the end of the list
539         //
540 
541         Protocol = va_arg(args, EFI_GUID *);
542         if (!Protocol) {
543             break;
544         }
545 
546         Interface = va_arg(args, VOID *);
547 
548         //
549         // Uninstall it
550         //
551 
552         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
553         if (EFI_ERROR(Status)) {
554             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
555         }
556     }
557     va_end (args);
558 }
559 
560 
561 EFI_STATUS
562 LibReinstallProtocolInterfaces (
563     IN OUT EFI_HANDLE           *Handle,
564     ...
565     )
566 {
567     va_list         args;
568     EFI_STATUS      Status;
569     EFI_GUID        *Protocol;
570     VOID            *OldInterface, *NewInterface;
571     EFI_TPL         OldTpl;
572     UINTN           Index;
573 
574     //
575     // Syncronize with notifcations
576     //
577 
578     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
579 
580     //
581     // Install the protocol interfaces
582     //
583 
584     Index = 0;
585     Status = EFI_SUCCESS;
586     va_start (args, Handle);
587 
588     while (!EFI_ERROR(Status)) {
589 
590         //
591         // If protocol is NULL, then it's the end of the list
592         //
593 
594         Protocol = va_arg(args, EFI_GUID *);
595         if (!Protocol) {
596             break;
597         }
598 
599         OldInterface = va_arg(args, VOID *);
600         NewInterface = va_arg(args, VOID *);
601 
602         //
603         // Reinstall it
604         //
605 
606         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
607         if (EFI_ERROR(Status)) {
608             break;
609         }
610 
611         Index += 1;
612     }
613     va_end (args);
614 
615     //
616     // If there was an error, undo all the interfaces that were
617     // reinstalled without any errors
618     //
619 
620     if (EFI_ERROR(Status)) {
621         va_start (args, Handle);
622         while (Index) {
623 
624             Protocol = va_arg(args, EFI_GUID *);
625             OldInterface = va_arg(args, VOID *);
626             NewInterface = va_arg(args, VOID *);
627 
628             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
629 
630             Index -= 1;
631         }
632         va_end (args);
633     }
634 
635     //
636     // Done
637     //
638 
639     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
640     return Status;
641 }
642