Home | History | Annotate | Line # | Download | only in lib
      1 /*	$NetBSD: hand.c,v 1.5 2021/09/30 19:02:48 jmcneill 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       *Next, *DevPath;
    123     HARDDRIVE_DEVICE_PATH *HardDriveDevicePath;
    124     BOOLEAN               Match;
    125     BOOLEAN               PreviousNodeIsHardDriveDevicePath;
    126 
    127     //
    128     // Initialize for GrowBuffer loop
    129     //
    130 
    131     Status = EFI_SUCCESS;
    132     BlockIoBuffer = NULL;
    133     BufferSize = 50 * sizeof(EFI_HANDLE);
    134 
    135     //
    136     // Call the real function
    137     //
    138 
    139     while (GrowBuffer (&Status, (VOID **)&BlockIoBuffer, BufferSize)) {
    140 
    141         //
    142         // Get list of device handles that support the BLOCK_IO Protocol.
    143         //
    144 
    145         Status = uefi_call_wrapper(
    146 			BS->LocateHandle,
    147 			5,
    148                         ByProtocol,
    149                         &BlockIoProtocol,
    150                         NULL,
    151                         &BufferSize,
    152                         BlockIoBuffer
    153                         );
    154 
    155     }
    156 
    157     NoBlockIoHandles = BufferSize / sizeof (EFI_HANDLE);
    158     if (EFI_ERROR(Status)) {
    159         NoBlockIoHandles = 0;
    160     }
    161 
    162     //
    163     // If there was an error or there are no device handles that support
    164     // the BLOCK_IO Protocol, then return.
    165     //
    166 
    167     if (NoBlockIoHandles == 0) {
    168         FreePool(BlockIoBuffer);
    169         *NoHandles = 0;
    170         *Buffer = NULL;
    171         return Status;
    172     }
    173 
    174     //
    175     // Loop through all the device handles that support the BLOCK_IO Protocol
    176     //
    177 
    178     *NoHandles = 0;
    179 
    180     for(Index=0;Index<NoBlockIoHandles;Index++) {
    181 
    182         Status = uefi_call_wrapper(
    183 				     BS->HandleProtocol,
    184 					3,
    185 				     BlockIoBuffer[Index],
    186                                      &DevicePathProtocol,
    187                                      (VOID*)&DevicePath
    188                                      );
    189 
    190         //
    191         // Search DevicePath for a Hard Drive Media Device Path node.
    192         // If one is found, then see if it matches the signature that was
    193         // passed in.  If it does match, and the next node is the End of the
    194         // device path, and the previous node is not a Hard Drive Media Device
    195         // Path, then we have found a match.
    196         //
    197 
    198         Match = FALSE;
    199 
    200         if (DevicePath != NULL) {
    201 
    202             PreviousNodeIsHardDriveDevicePath = FALSE;
    203 
    204             DevPath = DevicePath;
    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     Status = EFI_SUCCESS;
    345     Buffer = NULL;
    346     BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
    347 
    348     //
    349     // Call the real function
    350     //
    351 
    352     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    353         Status = uefi_call_wrapper(
    354 		    FHand->GetInfo,
    355 			4,
    356                     FHand,
    357                     &GenericFileInfo,
    358                     &BufferSize,
    359                     Buffer
    360                     );
    361     }
    362 
    363     return Buffer;
    364 }
    365 
    366 
    367 EFI_FILE_SYSTEM_INFO *
    368 LibFileSystemInfo (
    369     IN EFI_FILE_HANDLE      FHand
    370     )
    371 {
    372     EFI_STATUS              Status;
    373     EFI_FILE_SYSTEM_INFO    *Buffer;
    374     UINTN                   BufferSize;
    375 
    376     //
    377     // Initialize for GrowBuffer loop
    378     //
    379 
    380     Status = EFI_SUCCESS;
    381     Buffer = NULL;
    382     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
    383 
    384     //
    385     // Call the real function
    386     //
    387 
    388     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    389         Status = uefi_call_wrapper(
    390 		    FHand->GetInfo,
    391 			4,
    392                     FHand,
    393                     &FileSystemInfo,
    394                     &BufferSize,
    395                     Buffer
    396                     );
    397     }
    398 
    399     return Buffer;
    400 }
    401 
    402 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
    403 LibFileSystemVolumeLabelInfo (
    404     IN EFI_FILE_HANDLE      FHand
    405     )
    406 {
    407     EFI_STATUS                        Status;
    408     EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
    409     UINTN                             BufferSize;
    410 
    411     //
    412     // Initialize for GrowBuffer loop
    413     //
    414 
    415     Status = EFI_SUCCESS;
    416     Buffer = NULL;
    417     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
    418 
    419     //
    420     // Call the real function
    421     //
    422 
    423     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    424         Status = uefi_call_wrapper(
    425 		    FHand->GetInfo,
    426 			4,
    427                     FHand,
    428                     &FileSystemVolumeLabelInfo,
    429                     &BufferSize,
    430                     Buffer
    431                     );
    432     }
    433 
    434     return Buffer;
    435 }
    436 
    437 
    438 
    439 EFI_STATUS
    440 LibInstallProtocolInterfaces (
    441     IN OUT EFI_HANDLE           *Handle,
    442     ...
    443     )
    444 {
    445     va_list         args;
    446     EFI_STATUS      Status;
    447     EFI_GUID        *Protocol;
    448     VOID            *Interface;
    449     EFI_TPL         OldTpl;
    450     UINTN           Index;
    451     EFI_HANDLE      OldHandle;
    452 
    453     //
    454     // Syncronize with notifcations
    455     //
    456 
    457     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
    458     OldHandle = *Handle;
    459 
    460     //
    461     // Install the protocol interfaces
    462     //
    463 
    464     Index = 0;
    465     Status = EFI_SUCCESS;
    466     va_start (args, Handle);
    467 
    468     while (!EFI_ERROR(Status)) {
    469 
    470         //
    471         // If protocol is NULL, then it's the end of the list
    472         //
    473 
    474         Protocol = va_arg(args, EFI_GUID *);
    475         if (!Protocol) {
    476             break;
    477         }
    478 
    479         Interface = va_arg(args, VOID *);
    480 
    481         //
    482         // Install it
    483         //
    484 
    485         DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
    486         Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
    487         if (EFI_ERROR(Status)) {
    488             break;
    489         }
    490 
    491         Index += 1;
    492     }
    493     va_end (args);
    494 
    495     va_end (args);
    496 
    497     //
    498     // If there was an error, remove all the interfaces that were
    499     // installed without any errors
    500     //
    501 
    502     if (EFI_ERROR(Status)) {
    503         va_start (args, Handle);
    504         while (Index) {
    505 
    506             Protocol = va_arg(args, EFI_GUID *);
    507             Interface = va_arg(args, VOID *);
    508             uefi_call_wrapper(BS->UninstallProtocolInterface, 3, *Handle, Protocol, Interface);
    509 
    510             Index -= 1;
    511         }
    512 	va_end (args);
    513 
    514         *Handle = OldHandle;
    515         va_end (args);
    516     }
    517 
    518     //
    519     // Done
    520     //
    521 
    522     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
    523     return Status;
    524 }
    525 
    526 
    527 VOID
    528 LibUninstallProtocolInterfaces (
    529     IN EFI_HANDLE           Handle,
    530     ...
    531     )
    532 {
    533     va_list         args;
    534     EFI_STATUS      Status;
    535     EFI_GUID        *Protocol;
    536     VOID            *Interface;
    537 
    538 
    539     va_start (args, Handle);
    540     for (; ;) {
    541 
    542         //
    543         // If protocol is NULL, then it's the end of the list
    544         //
    545 
    546         Protocol = va_arg(args, EFI_GUID *);
    547         if (!Protocol) {
    548             break;
    549         }
    550 
    551         Interface = va_arg(args, VOID *);
    552 
    553         //
    554         // Uninstall it
    555         //
    556 
    557         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
    558         if (EFI_ERROR(Status)) {
    559             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
    560         }
    561     }
    562     va_end (args);
    563 }
    564 
    565 
    566 EFI_STATUS
    567 LibReinstallProtocolInterfaces (
    568     IN OUT EFI_HANDLE           *Handle,
    569     ...
    570     )
    571 {
    572     va_list         args;
    573     EFI_STATUS      Status;
    574     EFI_GUID        *Protocol;
    575     VOID            *OldInterface, *NewInterface;
    576     EFI_TPL         OldTpl;
    577     UINTN           Index;
    578 
    579     //
    580     // Syncronize with notifcations
    581     //
    582 
    583     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
    584 
    585     //
    586     // Install the protocol interfaces
    587     //
    588 
    589     Index = 0;
    590     Status = EFI_SUCCESS;
    591     va_start (args, Handle);
    592 
    593     while (!EFI_ERROR(Status)) {
    594 
    595         //
    596         // If protocol is NULL, then it's the end of the list
    597         //
    598 
    599         Protocol = va_arg(args, EFI_GUID *);
    600         if (!Protocol) {
    601             break;
    602         }
    603 
    604         OldInterface = va_arg(args, VOID *);
    605         NewInterface = va_arg(args, VOID *);
    606 
    607         //
    608         // Reinstall it
    609         //
    610 
    611         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
    612         if (EFI_ERROR(Status)) {
    613             break;
    614         }
    615 
    616         Index += 1;
    617     }
    618     va_end (args);
    619 
    620     va_end (args);
    621 
    622     //
    623     // If there was an error, undo all the interfaces that were
    624     // reinstalled without any errors
    625     //
    626 
    627     if (EFI_ERROR(Status)) {
    628         va_start (args, Handle);
    629         while (Index) {
    630 
    631             Protocol = va_arg(args, EFI_GUID *);
    632             OldInterface = va_arg(args, VOID *);
    633             NewInterface = va_arg(args, VOID *);
    634 
    635             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
    636 
    637             Index -= 1;
    638         }
    639         va_end (args);
    640     }
    641 
    642     //
    643     // Done
    644     //
    645 
    646     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
    647     return Status;
    648 }
    649