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