xref: /netbsd/sys/external/bsd/gnu-efi/dist/lib/hand.c (revision 48704958)
1*48704958Sjmcneill /*	$NetBSD: hand.c,v 1.5 2021/09/30 19:02:48 jmcneill Exp $	*/
201d0c315Sjakllsch 
301d0c315Sjakllsch /*++
401d0c315Sjakllsch 
501d0c315Sjakllsch Copyright (c) 1998  Intel Corporation
601d0c315Sjakllsch 
701d0c315Sjakllsch Module Name:
801d0c315Sjakllsch 
901d0c315Sjakllsch     hand.c
1001d0c315Sjakllsch 
1101d0c315Sjakllsch Abstract:
1201d0c315Sjakllsch 
1301d0c315Sjakllsch 
1401d0c315Sjakllsch 
1501d0c315Sjakllsch 
1601d0c315Sjakllsch Revision History
1701d0c315Sjakllsch 
1801d0c315Sjakllsch --*/
1901d0c315Sjakllsch 
2001d0c315Sjakllsch #include "lib.h"
2101d0c315Sjakllsch #include "efistdarg.h"                        // !!!
2201d0c315Sjakllsch 
2301d0c315Sjakllsch 
2401d0c315Sjakllsch EFI_STATUS
LibLocateProtocol(IN EFI_GUID * ProtocolGuid,OUT VOID ** Interface)2501d0c315Sjakllsch LibLocateProtocol (
2601d0c315Sjakllsch     IN  EFI_GUID    *ProtocolGuid,
2701d0c315Sjakllsch     OUT VOID        **Interface
2801d0c315Sjakllsch     )
2901d0c315Sjakllsch //
3001d0c315Sjakllsch // Find the first instance of this Protocol in the system and return it's interface
3101d0c315Sjakllsch //
3201d0c315Sjakllsch {
3301d0c315Sjakllsch     EFI_STATUS      Status;
3401d0c315Sjakllsch     UINTN           NumberHandles, Index;
3501d0c315Sjakllsch     EFI_HANDLE      *Handles;
3601d0c315Sjakllsch 
3701d0c315Sjakllsch 
3801d0c315Sjakllsch     *Interface = NULL;
3901d0c315Sjakllsch     Status = LibLocateHandle (ByProtocol, ProtocolGuid, NULL, &NumberHandles, &Handles);
4001d0c315Sjakllsch     if (EFI_ERROR(Status)) {
4101d0c315Sjakllsch         DEBUG((D_INFO, "LibLocateProtocol: Handle not found\n"));
4201d0c315Sjakllsch         return Status;
4301d0c315Sjakllsch     }
4401d0c315Sjakllsch 
4501d0c315Sjakllsch     for (Index=0; Index < NumberHandles; Index++) {
4601d0c315Sjakllsch         Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handles[Index], ProtocolGuid, Interface);
4701d0c315Sjakllsch         if (!EFI_ERROR(Status)) {
4801d0c315Sjakllsch             break;
4901d0c315Sjakllsch         }
5001d0c315Sjakllsch     }
5101d0c315Sjakllsch 
5201d0c315Sjakllsch     if (Handles) {
5301d0c315Sjakllsch         FreePool (Handles);
5401d0c315Sjakllsch     }
5501d0c315Sjakllsch 
5601d0c315Sjakllsch     return Status;
5701d0c315Sjakllsch }
5801d0c315Sjakllsch 
5901d0c315Sjakllsch EFI_STATUS
LibLocateHandle(IN EFI_LOCATE_SEARCH_TYPE SearchType,IN EFI_GUID * Protocol OPTIONAL,IN VOID * SearchKey OPTIONAL,IN OUT UINTN * NoHandles,OUT EFI_HANDLE ** Buffer)6001d0c315Sjakllsch LibLocateHandle (
6101d0c315Sjakllsch     IN EFI_LOCATE_SEARCH_TYPE       SearchType,
6201d0c315Sjakllsch     IN EFI_GUID                     *Protocol OPTIONAL,
6301d0c315Sjakllsch     IN VOID                         *SearchKey OPTIONAL,
6401d0c315Sjakllsch     IN OUT UINTN                    *NoHandles,
6501d0c315Sjakllsch     OUT EFI_HANDLE                  **Buffer
6601d0c315Sjakllsch     )
6701d0c315Sjakllsch 
6801d0c315Sjakllsch {
6901d0c315Sjakllsch     EFI_STATUS          Status;
7001d0c315Sjakllsch     UINTN               BufferSize;
7101d0c315Sjakllsch 
7201d0c315Sjakllsch     //
7301d0c315Sjakllsch     // Initialize for GrowBuffer loop
7401d0c315Sjakllsch     //
7501d0c315Sjakllsch 
7601d0c315Sjakllsch     Status = EFI_SUCCESS;
7701d0c315Sjakllsch     *Buffer = NULL;
7801d0c315Sjakllsch     BufferSize = 50 * sizeof(EFI_HANDLE);
7901d0c315Sjakllsch 
8001d0c315Sjakllsch     //
8101d0c315Sjakllsch     // Call the real function
8201d0c315Sjakllsch     //
8301d0c315Sjakllsch 
8401d0c315Sjakllsch     while (GrowBuffer (&Status, (VOID **) Buffer, BufferSize)) {
8501d0c315Sjakllsch 
8601d0c315Sjakllsch         Status = uefi_call_wrapper(
8701d0c315Sjakllsch 			BS->LocateHandle,
8801d0c315Sjakllsch 			5,
8901d0c315Sjakllsch                         SearchType,
9001d0c315Sjakllsch                         Protocol,
9101d0c315Sjakllsch                         SearchKey,
9201d0c315Sjakllsch                         &BufferSize,
9301d0c315Sjakllsch                         *Buffer
9401d0c315Sjakllsch                         );
9501d0c315Sjakllsch 
9601d0c315Sjakllsch     }
9701d0c315Sjakllsch 
9801d0c315Sjakllsch     *NoHandles = BufferSize / sizeof (EFI_HANDLE);
9901d0c315Sjakllsch     if (EFI_ERROR(Status)) {
10001d0c315Sjakllsch         *NoHandles = 0;
10101d0c315Sjakllsch     }
10201d0c315Sjakllsch 
10301d0c315Sjakllsch     return Status;
10401d0c315Sjakllsch }
10501d0c315Sjakllsch 
10601d0c315Sjakllsch EFI_STATUS
LibLocateHandleByDiskSignature(IN UINT8 MBRType,IN UINT8 SignatureType,IN VOID * Signature,IN OUT UINTN * NoHandles,OUT EFI_HANDLE ** Buffer)10701d0c315Sjakllsch LibLocateHandleByDiskSignature (
10801d0c315Sjakllsch     IN UINT8                        MBRType,
10901d0c315Sjakllsch     IN UINT8                        SignatureType,
11001d0c315Sjakllsch     IN VOID                         *Signature,
11101d0c315Sjakllsch     IN OUT UINTN                    *NoHandles,
11201d0c315Sjakllsch     OUT EFI_HANDLE                  **Buffer
11301d0c315Sjakllsch     )
11401d0c315Sjakllsch 
11501d0c315Sjakllsch {
11601d0c315Sjakllsch     EFI_STATUS            Status;
11701d0c315Sjakllsch     UINTN                 BufferSize;
11801d0c315Sjakllsch     UINTN                 NoBlockIoHandles;
11901d0c315Sjakllsch     EFI_HANDLE            *BlockIoBuffer;
12001d0c315Sjakllsch     EFI_DEVICE_PATH       *DevicePath;
12101d0c315Sjakllsch     UINTN                 Index;
1224d6ac919Sjmcneill     EFI_DEVICE_PATH       *Next, *DevPath;
12301d0c315Sjakllsch     HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
12401d0c315Sjakllsch     BOOLEAN               Match;
12501d0c315Sjakllsch     BOOLEAN               PreviousNodeIsHardDriveDevicePath;
12601d0c315Sjakllsch 
12701d0c315Sjakllsch     //
12801d0c315Sjakllsch     // Initialize for GrowBuffer loop
12901d0c315Sjakllsch     //
13001d0c315Sjakllsch 
1314d6ac919Sjmcneill     Status = EFI_SUCCESS;
13201d0c315Sjakllsch     BlockIoBuffer = NULL;
13301d0c315Sjakllsch     BufferSize = 50 * sizeof(EFI_HANDLE);
13401d0c315Sjakllsch 
13501d0c315Sjakllsch     //
13601d0c315Sjakllsch     // Call the real function
13701d0c315Sjakllsch     //
13801d0c315Sjakllsch 
13901d0c315Sjakllsch     while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
14001d0c315Sjakllsch 
14101d0c315Sjakllsch         //
14201d0c315Sjakllsch         // Get list of device handles that support the BLOCK_IO Protocol.
14301d0c315Sjakllsch         //
14401d0c315Sjakllsch 
14501d0c315Sjakllsch         Status = uefi_call_wrapper(
14601d0c315Sjakllsch 			BS->LocateHandle,
14701d0c315Sjakllsch 			5,
14801d0c315Sjakllsch                         ByProtocol,
14901d0c315Sjakllsch                         &BlockIoProtocol,
15001d0c315Sjakllsch                         NULL,
15101d0c315Sjakllsch                         &BufferSize,
15201d0c315Sjakllsch                         BlockIoBuffer
15301d0c315Sjakllsch                         );
15401d0c315Sjakllsch 
15501d0c315Sjakllsch     }
15601d0c315Sjakllsch 
15701d0c315Sjakllsch     NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
15801d0c315Sjakllsch     if (EFI_ERROR(Status)) {
15901d0c315Sjakllsch         NoBlockIoHandles = 0;
16001d0c315Sjakllsch     }
16101d0c315Sjakllsch 
16201d0c315Sjakllsch     //
16301d0c315Sjakllsch     // If there was an error or there are no device handles that support
16401d0c315Sjakllsch     // the BLOCK_IO Protocol, then return.
16501d0c315Sjakllsch     //
16601d0c315Sjakllsch 
16701d0c315Sjakllsch     if (NoBlockIoHandles == 0) {
16801d0c315Sjakllsch         FreePool(BlockIoBuffer);
16901d0c315Sjakllsch         *NoHandles = 0;
17001d0c315Sjakllsch         *Buffer = NULL;
17101d0c315Sjakllsch         return Status;
17201d0c315Sjakllsch     }
17301d0c315Sjakllsch 
17401d0c315Sjakllsch     //
17501d0c315Sjakllsch     // Loop through all the device handles that support the BLOCK_IO Protocol
17601d0c315Sjakllsch     //
17701d0c315Sjakllsch 
17801d0c315Sjakllsch     *NoHandles = 0;
17901d0c315Sjakllsch 
18001d0c315Sjakllsch     for(Index=0;Index<NoBlockIoHandles;Index++) {
18101d0c315Sjakllsch 
18201d0c315Sjakllsch         Status = uefi_call_wrapper(
18301d0c315Sjakllsch 				     BS->HandleProtocol,
18401d0c315Sjakllsch 					3,
18501d0c315Sjakllsch 				     BlockIoBuffer[Index],
18601d0c315Sjakllsch                                      &DevicePathProtocol,
18701d0c315Sjakllsch                                      (VOID*)&DevicePath
18801d0c315Sjakllsch                                      );
18901d0c315Sjakllsch 
19001d0c315Sjakllsch         //
19101d0c315Sjakllsch         // Search DevicePath for a Hard Drive Media Device Path node.
19201d0c315Sjakllsch         // If one is found, then see if it matches the signature that was
19301d0c315Sjakllsch         // passed in.  If it does match, and the next node is the End of the
19401d0c315Sjakllsch         // device path, and the previous node is not a Hard Drive Media Device
19501d0c315Sjakllsch         // Path, then we have found a match.
19601d0c315Sjakllsch         //
19701d0c315Sjakllsch 
19801d0c315Sjakllsch         Match = FALSE;
19901d0c315Sjakllsch 
20001d0c315Sjakllsch         if (DevicePath != NULL) {
20101d0c315Sjakllsch 
20201d0c315Sjakllsch             PreviousNodeIsHardDriveDevicePath = FALSE;
20301d0c315Sjakllsch 
20401d0c315Sjakllsch             DevPath = DevicePath;
20501d0c315Sjakllsch 
20601d0c315Sjakllsch             //
20701d0c315Sjakllsch             // Check for end of device path type
20801d0c315Sjakllsch             //
20901d0c315Sjakllsch 
21001d0c315Sjakllsch             for (; ;) {
21101d0c315Sjakllsch 
21201d0c315Sjakllsch                 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
21301d0c315Sjakllsch                     (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
21401d0c315Sjakllsch 
21501d0c315Sjakllsch                     HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
21601d0c315Sjakllsch 
21701d0c315Sjakllsch                     if (PreviousNodeIsHardDriveDevicePath == FALSE) {
21801d0c315Sjakllsch 
21901d0c315Sjakllsch                         Next = NextDevicePathNode(DevPath);
22001d0c315Sjakllsch                         if (IsDevicePathEndType(Next)) {
22101d0c315Sjakllsch                             if ((HardDriveDevicePath->MBRType == MBRType) &&
22201d0c315Sjakllsch                                 (HardDriveDevicePath->SignatureType == SignatureType)) {
22301d0c315Sjakllsch                                     switch(SignatureType) {
22401d0c315Sjakllsch                                         case SIGNATURE_TYPE_MBR:
22501d0c315Sjakllsch                                             if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
22601d0c315Sjakllsch                                                 Match = TRUE;
22701d0c315Sjakllsch                                             }
22801d0c315Sjakllsch                                             break;
22901d0c315Sjakllsch                                         case SIGNATURE_TYPE_GUID:
23001d0c315Sjakllsch                                             if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
23101d0c315Sjakllsch                                                 Match = TRUE;
23201d0c315Sjakllsch                                             }
23301d0c315Sjakllsch                                             break;
23401d0c315Sjakllsch                                     }
23501d0c315Sjakllsch                             }
23601d0c315Sjakllsch                         }
23701d0c315Sjakllsch                     }
23801d0c315Sjakllsch                     PreviousNodeIsHardDriveDevicePath = TRUE;
23901d0c315Sjakllsch                 } else {
24001d0c315Sjakllsch                     PreviousNodeIsHardDriveDevicePath = FALSE;
24101d0c315Sjakllsch                 }
24201d0c315Sjakllsch 
24301d0c315Sjakllsch                 if (IsDevicePathEnd(DevPath)) {
24401d0c315Sjakllsch                     break;
24501d0c315Sjakllsch                 }
24601d0c315Sjakllsch 
24701d0c315Sjakllsch                 DevPath = NextDevicePathNode(DevPath);
24801d0c315Sjakllsch             }
24901d0c315Sjakllsch 
25001d0c315Sjakllsch         }
25101d0c315Sjakllsch 
25201d0c315Sjakllsch         if (Match == FALSE) {
25301d0c315Sjakllsch             BlockIoBuffer[Index] = NULL;
25401d0c315Sjakllsch         } else {
25501d0c315Sjakllsch             *NoHandles = *NoHandles + 1;
25601d0c315Sjakllsch         }
25701d0c315Sjakllsch     }
25801d0c315Sjakllsch 
25901d0c315Sjakllsch     //
26001d0c315Sjakllsch     // If there are no matches, then return
26101d0c315Sjakllsch     //
26201d0c315Sjakllsch 
26301d0c315Sjakllsch     if (*NoHandles == 0) {
26401d0c315Sjakllsch         FreePool(BlockIoBuffer);
26501d0c315Sjakllsch         *NoHandles = 0;
26601d0c315Sjakllsch         *Buffer = NULL;
26701d0c315Sjakllsch         return EFI_SUCCESS;
26801d0c315Sjakllsch     }
26901d0c315Sjakllsch 
27001d0c315Sjakllsch     //
27101d0c315Sjakllsch     // Allocate space for the return buffer of device handles.
27201d0c315Sjakllsch     //
27301d0c315Sjakllsch 
27401d0c315Sjakllsch     *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
27501d0c315Sjakllsch 
27601d0c315Sjakllsch     if (*Buffer == NULL) {
27701d0c315Sjakllsch         FreePool(BlockIoBuffer);
27801d0c315Sjakllsch         *NoHandles = 0;
27901d0c315Sjakllsch         *Buffer = NULL;
28001d0c315Sjakllsch         return EFI_OUT_OF_RESOURCES;
28101d0c315Sjakllsch     }
28201d0c315Sjakllsch 
28301d0c315Sjakllsch     //
28401d0c315Sjakllsch     // Build list of matching device handles.
28501d0c315Sjakllsch     //
28601d0c315Sjakllsch 
28701d0c315Sjakllsch     *NoHandles = 0;
28801d0c315Sjakllsch     for(Index=0;Index<NoBlockIoHandles;Index++) {
28901d0c315Sjakllsch         if (BlockIoBuffer[Index] != NULL) {
29001d0c315Sjakllsch             (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
29101d0c315Sjakllsch             *NoHandles = *NoHandles + 1;
29201d0c315Sjakllsch         }
29301d0c315Sjakllsch     }
29401d0c315Sjakllsch 
29501d0c315Sjakllsch     FreePool(BlockIoBuffer);
29601d0c315Sjakllsch 
29701d0c315Sjakllsch     return EFI_SUCCESS;
29801d0c315Sjakllsch }
29901d0c315Sjakllsch 
30001d0c315Sjakllsch EFI_FILE_HANDLE
LibOpenRoot(IN EFI_HANDLE DeviceHandle)30101d0c315Sjakllsch LibOpenRoot (
30201d0c315Sjakllsch     IN EFI_HANDLE               DeviceHandle
30301d0c315Sjakllsch     )
30401d0c315Sjakllsch {
30501d0c315Sjakllsch     EFI_STATUS                  Status;
30601d0c315Sjakllsch     EFI_FILE_IO_INTERFACE       *Volume;
30701d0c315Sjakllsch     EFI_FILE_HANDLE             File;
30801d0c315Sjakllsch 
30901d0c315Sjakllsch 
31001d0c315Sjakllsch     //
31101d0c315Sjakllsch     // File the file system interface to the device
31201d0c315Sjakllsch     //
31301d0c315Sjakllsch 
31401d0c315Sjakllsch     Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
31501d0c315Sjakllsch 
31601d0c315Sjakllsch     //
31701d0c315Sjakllsch     // Open the root directory of the volume
31801d0c315Sjakllsch     //
31901d0c315Sjakllsch 
32001d0c315Sjakllsch     if (!EFI_ERROR(Status)) {
32101d0c315Sjakllsch         Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
32201d0c315Sjakllsch     }
32301d0c315Sjakllsch 
32401d0c315Sjakllsch     //
32501d0c315Sjakllsch     // Done
32601d0c315Sjakllsch     //
32701d0c315Sjakllsch 
32801d0c315Sjakllsch     return EFI_ERROR(Status) ? NULL : File;
32901d0c315Sjakllsch }
33001d0c315Sjakllsch 
33101d0c315Sjakllsch EFI_FILE_INFO *
LibFileInfo(IN EFI_FILE_HANDLE FHand)33201d0c315Sjakllsch LibFileInfo (
33301d0c315Sjakllsch     IN EFI_FILE_HANDLE      FHand
33401d0c315Sjakllsch     )
33501d0c315Sjakllsch {
33601d0c315Sjakllsch     EFI_STATUS              Status;
33701d0c315Sjakllsch     EFI_FILE_INFO           *Buffer;
33801d0c315Sjakllsch     UINTN                   BufferSize;
33901d0c315Sjakllsch 
34001d0c315Sjakllsch     //
34101d0c315Sjakllsch     // Initialize for GrowBuffer loop
34201d0c315Sjakllsch     //
34301d0c315Sjakllsch 
3444d6ac919Sjmcneill     Status = EFI_SUCCESS;
34501d0c315Sjakllsch     Buffer = NULL;
34601d0c315Sjakllsch     BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
34701d0c315Sjakllsch 
34801d0c315Sjakllsch     //
34901d0c315Sjakllsch     // Call the real function
35001d0c315Sjakllsch     //
35101d0c315Sjakllsch 
35201d0c315Sjakllsch     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
35301d0c315Sjakllsch         Status = uefi_call_wrapper(
35401d0c315Sjakllsch 		    FHand->GetInfo,
35501d0c315Sjakllsch 			4,
35601d0c315Sjakllsch                     FHand,
35701d0c315Sjakllsch                     &GenericFileInfo,
35801d0c315Sjakllsch                     &BufferSize,
35901d0c315Sjakllsch                     Buffer
36001d0c315Sjakllsch                     );
36101d0c315Sjakllsch     }
36201d0c315Sjakllsch 
36301d0c315Sjakllsch     return Buffer;
36401d0c315Sjakllsch }
36501d0c315Sjakllsch 
36601d0c315Sjakllsch 
36701d0c315Sjakllsch EFI_FILE_SYSTEM_INFO *
LibFileSystemInfo(IN EFI_FILE_HANDLE FHand)36801d0c315Sjakllsch LibFileSystemInfo (
36901d0c315Sjakllsch     IN EFI_FILE_HANDLE      FHand
37001d0c315Sjakllsch     )
37101d0c315Sjakllsch {
37201d0c315Sjakllsch     EFI_STATUS              Status;
37301d0c315Sjakllsch     EFI_FILE_SYSTEM_INFO    *Buffer;
37401d0c315Sjakllsch     UINTN                   BufferSize;
37501d0c315Sjakllsch 
37601d0c315Sjakllsch     //
37701d0c315Sjakllsch     // Initialize for GrowBuffer loop
37801d0c315Sjakllsch     //
37901d0c315Sjakllsch 
3804d6ac919Sjmcneill     Status = EFI_SUCCESS;
38101d0c315Sjakllsch     Buffer = NULL;
38201d0c315Sjakllsch     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
38301d0c315Sjakllsch 
38401d0c315Sjakllsch     //
38501d0c315Sjakllsch     // Call the real function
38601d0c315Sjakllsch     //
38701d0c315Sjakllsch 
38801d0c315Sjakllsch     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
38901d0c315Sjakllsch         Status = uefi_call_wrapper(
39001d0c315Sjakllsch 		    FHand->GetInfo,
39101d0c315Sjakllsch 			4,
39201d0c315Sjakllsch                     FHand,
39301d0c315Sjakllsch                     &FileSystemInfo,
39401d0c315Sjakllsch                     &BufferSize,
39501d0c315Sjakllsch                     Buffer
39601d0c315Sjakllsch                     );
39701d0c315Sjakllsch     }
39801d0c315Sjakllsch 
39901d0c315Sjakllsch     return Buffer;
40001d0c315Sjakllsch }
40101d0c315Sjakllsch 
40201d0c315Sjakllsch EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
LibFileSystemVolumeLabelInfo(IN EFI_FILE_HANDLE FHand)40301d0c315Sjakllsch LibFileSystemVolumeLabelInfo (
40401d0c315Sjakllsch     IN EFI_FILE_HANDLE      FHand
40501d0c315Sjakllsch     )
40601d0c315Sjakllsch {
40701d0c315Sjakllsch     EFI_STATUS                        Status;
40801d0c315Sjakllsch     EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
40901d0c315Sjakllsch     UINTN                             BufferSize;
41001d0c315Sjakllsch 
41101d0c315Sjakllsch     //
41201d0c315Sjakllsch     // Initialize for GrowBuffer loop
41301d0c315Sjakllsch     //
41401d0c315Sjakllsch 
4154d6ac919Sjmcneill     Status = EFI_SUCCESS;
41601d0c315Sjakllsch     Buffer = NULL;
41701d0c315Sjakllsch     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
41801d0c315Sjakllsch 
41901d0c315Sjakllsch     //
42001d0c315Sjakllsch     // Call the real function
42101d0c315Sjakllsch     //
42201d0c315Sjakllsch 
42301d0c315Sjakllsch     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
42401d0c315Sjakllsch         Status = uefi_call_wrapper(
42501d0c315Sjakllsch 		    FHand->GetInfo,
42601d0c315Sjakllsch 			4,
42701d0c315Sjakllsch                     FHand,
42801d0c315Sjakllsch                     &FileSystemVolumeLabelInfo,
42901d0c315Sjakllsch                     &BufferSize,
43001d0c315Sjakllsch                     Buffer
43101d0c315Sjakllsch                     );
43201d0c315Sjakllsch     }
43301d0c315Sjakllsch 
43401d0c315Sjakllsch     return Buffer;
43501d0c315Sjakllsch }
43601d0c315Sjakllsch 
43701d0c315Sjakllsch 
43801d0c315Sjakllsch 
43901d0c315Sjakllsch EFI_STATUS
LibInstallProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)44001d0c315Sjakllsch LibInstallProtocolInterfaces (
44101d0c315Sjakllsch     IN OUT EFI_HANDLE           *Handle,
44201d0c315Sjakllsch     ...
44301d0c315Sjakllsch     )
44401d0c315Sjakllsch {
44501d0c315Sjakllsch     va_list         args;
44601d0c315Sjakllsch     EFI_STATUS      Status;
44701d0c315Sjakllsch     EFI_GUID        *Protocol;
44801d0c315Sjakllsch     VOID            *Interface;
44901d0c315Sjakllsch     EFI_TPL         OldTpl;
45001d0c315Sjakllsch     UINTN           Index;
45101d0c315Sjakllsch     EFI_HANDLE      OldHandle;
45201d0c315Sjakllsch 
45301d0c315Sjakllsch     //
45401d0c315Sjakllsch     // Syncronize with notifcations
45501d0c315Sjakllsch     //
45601d0c315Sjakllsch 
45701d0c315Sjakllsch     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
45801d0c315Sjakllsch     OldHandle = *Handle;
45901d0c315Sjakllsch 
46001d0c315Sjakllsch     //
46101d0c315Sjakllsch     // Install the protocol interfaces
46201d0c315Sjakllsch     //
46301d0c315Sjakllsch 
46401d0c315Sjakllsch     Index = 0;
46501d0c315Sjakllsch     Status = EFI_SUCCESS;
46601d0c315Sjakllsch     va_start (args, Handle);
46701d0c315Sjakllsch 
46801d0c315Sjakllsch     while (!EFI_ERROR(Status)) {
46901d0c315Sjakllsch 
47001d0c315Sjakllsch         //
47101d0c315Sjakllsch         // If protocol is NULL, then it's the end of the list
47201d0c315Sjakllsch         //
47301d0c315Sjakllsch 
47401d0c315Sjakllsch         Protocol = va_arg(args, EFI_GUID *);
47501d0c315Sjakllsch         if (!Protocol) {
47601d0c315Sjakllsch             break;
47701d0c315Sjakllsch         }
47801d0c315Sjakllsch 
47901d0c315Sjakllsch         Interface = va_arg(args, VOID *);
48001d0c315Sjakllsch 
48101d0c315Sjakllsch         //
48201d0c315Sjakllsch         // Install it
48301d0c315Sjakllsch         //
48401d0c315Sjakllsch 
48501d0c315Sjakllsch         DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
48601d0c315Sjakllsch         Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
48701d0c315Sjakllsch         if (EFI_ERROR(Status)) {
48801d0c315Sjakllsch             break;
48901d0c315Sjakllsch         }
49001d0c315Sjakllsch 
49101d0c315Sjakllsch         Index += 1;
49201d0c315Sjakllsch     }
493*48704958Sjmcneill     va_end (args);
49401d0c315Sjakllsch 
49570763d92Schristos     va_end (args);
49670763d92Schristos 
49701d0c315Sjakllsch     //
49801d0c315Sjakllsch     // If there was an error, remove all the interfaces that were
49901d0c315Sjakllsch     // installed without any errors
50001d0c315Sjakllsch     //
50101d0c315Sjakllsch 
50201d0c315Sjakllsch     if (EFI_ERROR(Status)) {
50301d0c315Sjakllsch         va_start (args, Handle);
50401d0c315Sjakllsch         while (Index) {
50501d0c315Sjakllsch 
50601d0c315Sjakllsch             Protocol = va_arg(args, EFI_GUID *);
50701d0c315Sjakllsch             Interface = va_arg(args, VOID *);
50801d0c315Sjakllsch             uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
50901d0c315Sjakllsch 
51001d0c315Sjakllsch             Index -= 1;
51101d0c315Sjakllsch         }
51270763d92Schristos 	va_end (args);
51301d0c315Sjakllsch 
51401d0c315Sjakllsch         *Handle = OldHandle;
515*48704958Sjmcneill         va_end (args);
51601d0c315Sjakllsch     }
51701d0c315Sjakllsch 
51801d0c315Sjakllsch     //
51901d0c315Sjakllsch     // Done
52001d0c315Sjakllsch     //
52101d0c315Sjakllsch 
52201d0c315Sjakllsch     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
52301d0c315Sjakllsch     return Status;
52401d0c315Sjakllsch }
52501d0c315Sjakllsch 
52601d0c315Sjakllsch 
52701d0c315Sjakllsch VOID
LibUninstallProtocolInterfaces(IN EFI_HANDLE Handle,...)52801d0c315Sjakllsch LibUninstallProtocolInterfaces (
52901d0c315Sjakllsch     IN EFI_HANDLE           Handle,
53001d0c315Sjakllsch     ...
53101d0c315Sjakllsch     )
53201d0c315Sjakllsch {
53301d0c315Sjakllsch     va_list         args;
53401d0c315Sjakllsch     EFI_STATUS      Status;
53501d0c315Sjakllsch     EFI_GUID        *Protocol;
53601d0c315Sjakllsch     VOID            *Interface;
53701d0c315Sjakllsch 
53801d0c315Sjakllsch 
53901d0c315Sjakllsch     va_start (args, Handle);
54001d0c315Sjakllsch     for (; ;) {
54101d0c315Sjakllsch 
54201d0c315Sjakllsch         //
54301d0c315Sjakllsch         // If protocol is NULL, then it's the end of the list
54401d0c315Sjakllsch         //
54501d0c315Sjakllsch 
54601d0c315Sjakllsch         Protocol = va_arg(args, EFI_GUID *);
54701d0c315Sjakllsch         if (!Protocol) {
54801d0c315Sjakllsch             break;
54901d0c315Sjakllsch         }
55001d0c315Sjakllsch 
55101d0c315Sjakllsch         Interface = va_arg(args, VOID *);
55201d0c315Sjakllsch 
55301d0c315Sjakllsch         //
55401d0c315Sjakllsch         // Uninstall it
55501d0c315Sjakllsch         //
55601d0c315Sjakllsch 
55701d0c315Sjakllsch         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
55801d0c315Sjakllsch         if (EFI_ERROR(Status)) {
55901d0c315Sjakllsch             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
56001d0c315Sjakllsch         }
56101d0c315Sjakllsch     }
56270763d92Schristos     va_end (args);
56301d0c315Sjakllsch }
56401d0c315Sjakllsch 
56501d0c315Sjakllsch 
56601d0c315Sjakllsch EFI_STATUS
LibReinstallProtocolInterfaces(IN OUT EFI_HANDLE * Handle,...)56701d0c315Sjakllsch LibReinstallProtocolInterfaces (
56801d0c315Sjakllsch     IN OUT EFI_HANDLE           *Handle,
56901d0c315Sjakllsch     ...
57001d0c315Sjakllsch     )
57101d0c315Sjakllsch {
57201d0c315Sjakllsch     va_list         args;
57301d0c315Sjakllsch     EFI_STATUS      Status;
57401d0c315Sjakllsch     EFI_GUID        *Protocol;
57501d0c315Sjakllsch     VOID            *OldInterface, *NewInterface;
57601d0c315Sjakllsch     EFI_TPL         OldTpl;
57701d0c315Sjakllsch     UINTN           Index;
57801d0c315Sjakllsch 
57901d0c315Sjakllsch     //
58001d0c315Sjakllsch     // Syncronize with notifcations
58101d0c315Sjakllsch     //
58201d0c315Sjakllsch 
58301d0c315Sjakllsch     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
58401d0c315Sjakllsch 
58501d0c315Sjakllsch     //
58601d0c315Sjakllsch     // Install the protocol interfaces
58701d0c315Sjakllsch     //
58801d0c315Sjakllsch 
58901d0c315Sjakllsch     Index = 0;
59001d0c315Sjakllsch     Status = EFI_SUCCESS;
59101d0c315Sjakllsch     va_start (args, Handle);
59201d0c315Sjakllsch 
59301d0c315Sjakllsch     while (!EFI_ERROR(Status)) {
59401d0c315Sjakllsch 
59501d0c315Sjakllsch         //
59601d0c315Sjakllsch         // If protocol is NULL, then it's the end of the list
59701d0c315Sjakllsch         //
59801d0c315Sjakllsch 
59901d0c315Sjakllsch         Protocol = va_arg(args, EFI_GUID *);
60001d0c315Sjakllsch         if (!Protocol) {
60101d0c315Sjakllsch             break;
60201d0c315Sjakllsch         }
60301d0c315Sjakllsch 
60401d0c315Sjakllsch         OldInterface = va_arg(args, VOID *);
60501d0c315Sjakllsch         NewInterface = va_arg(args, VOID *);
60601d0c315Sjakllsch 
60701d0c315Sjakllsch         //
60801d0c315Sjakllsch         // Reinstall it
60901d0c315Sjakllsch         //
61001d0c315Sjakllsch 
61101d0c315Sjakllsch         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
61201d0c315Sjakllsch         if (EFI_ERROR(Status)) {
61301d0c315Sjakllsch             break;
61401d0c315Sjakllsch         }
61501d0c315Sjakllsch 
61601d0c315Sjakllsch         Index += 1;
61701d0c315Sjakllsch     }
618*48704958Sjmcneill     va_end (args);
61901d0c315Sjakllsch 
62070763d92Schristos     va_end (args);
62170763d92Schristos 
62201d0c315Sjakllsch     //
62301d0c315Sjakllsch     // If there was an error, undo all the interfaces that were
62401d0c315Sjakllsch     // reinstalled without any errors
62501d0c315Sjakllsch     //
62601d0c315Sjakllsch 
62701d0c315Sjakllsch     if (EFI_ERROR(Status)) {
62801d0c315Sjakllsch         va_start (args, Handle);
62901d0c315Sjakllsch         while (Index) {
63001d0c315Sjakllsch 
63101d0c315Sjakllsch             Protocol = va_arg(args, EFI_GUID *);
63201d0c315Sjakllsch             OldInterface = va_arg(args, VOID *);
63301d0c315Sjakllsch             NewInterface = va_arg(args, VOID *);
63401d0c315Sjakllsch 
63501d0c315Sjakllsch             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
63601d0c315Sjakllsch 
63701d0c315Sjakllsch             Index -= 1;
63801d0c315Sjakllsch         }
63970763d92Schristos         va_end (args);
64001d0c315Sjakllsch     }
64101d0c315Sjakllsch 
64201d0c315Sjakllsch     //
64301d0c315Sjakllsch     // Done
64401d0c315Sjakllsch     //
64501d0c315Sjakllsch 
64601d0c315Sjakllsch     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
64701d0c315Sjakllsch     return Status;
64801d0c315Sjakllsch }
649