Home | History | Annotate | Download | only in lib
      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       *Start, *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             Start = DevPath;
    204 
    205             //
    206             // Check for end of device path type
    207             //
    208 
    209             for (; ;) {
    210 
    211                 if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
    212                     (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
    213 
    214                     HardDriveDevicePath = (HARDDRIVE_DEVICE_PATH *)(DevPath);
    215 
    216                     if (PreviousNodeIsHardDriveDevicePath == FALSE) {
    217 
    218                         Next = NextDevicePathNode(DevPath);
    219                         if (IsDevicePathEndType(Next)) {
    220                             if ((HardDriveDevicePath->MBRType == MBRType) &&
    221                                 (HardDriveDevicePath->SignatureType == SignatureType)) {
    222                                     switch(SignatureType) {
    223                                         case SIGNATURE_TYPE_MBR:
    224                                             if (*((UINT32 *)(Signature)) == *(UINT32 *)(&(HardDriveDevicePath->Signature[0]))) {
    225                                                 Match = TRUE;
    226                                             }
    227                                             break;
    228                                         case SIGNATURE_TYPE_GUID:
    229                                             if (CompareGuid((EFI_GUID *)Signature,(EFI_GUID *)(&(HardDriveDevicePath->Signature[0]))) == 0) {
    230                                                 Match = TRUE;
    231                                             }
    232                                             break;
    233                                     }
    234                             }
    235                         }
    236                     }
    237                     PreviousNodeIsHardDriveDevicePath = TRUE;
    238                 } else {
    239                     PreviousNodeIsHardDriveDevicePath = FALSE;
    240                 }
    241 
    242                 if (IsDevicePathEnd(DevPath)) {
    243                     break;
    244                 }
    245 
    246                 DevPath = NextDevicePathNode(DevPath);
    247             }
    248 
    249         }
    250 
    251         if (Match == FALSE) {
    252             BlockIoBuffer[Index] = NULL;
    253         } else {
    254             *NoHandles = *NoHandles + 1;
    255         }
    256     }
    257 
    258     //
    259     // If there are no matches, then return
    260     //
    261 
    262     if (*NoHandles == 0) {
    263         FreePool(BlockIoBuffer);
    264         *NoHandles = 0;
    265         *Buffer = NULL;
    266         return EFI_SUCCESS;
    267     }
    268 
    269     //
    270     // Allocate space for the return buffer of device handles.
    271     //
    272 
    273     *Buffer = AllocatePool(*NoHandles * sizeof(EFI_HANDLE));
    274 
    275     if (*Buffer == NULL) {
    276         FreePool(BlockIoBuffer);
    277         *NoHandles = 0;
    278         *Buffer = NULL;
    279         return EFI_OUT_OF_RESOURCES;
    280     }
    281 
    282     //
    283     // Build list of matching device handles.
    284     //
    285 
    286     *NoHandles = 0;
    287     for(Index=0;Index<NoBlockIoHandles;Index++) {
    288         if (BlockIoBuffer[Index] != NULL) {
    289             (*Buffer)[*NoHandles] = BlockIoBuffer[Index];
    290             *NoHandles = *NoHandles + 1;
    291         }
    292     }
    293 
    294     FreePool(BlockIoBuffer);
    295 
    296     return EFI_SUCCESS;
    297 }
    298 
    299 EFI_FILE_HANDLE
    300 LibOpenRoot (
    301     IN EFI_HANDLE               DeviceHandle
    302     )
    303 {
    304     EFI_STATUS                  Status;
    305     EFI_FILE_IO_INTERFACE       *Volume;
    306     EFI_FILE_HANDLE             File;
    307 
    308 
    309     //
    310     // File the file system interface to the device
    311     //
    312 
    313     Status = uefi_call_wrapper(BS->HandleProtocol, 3, DeviceHandle, &FileSystemProtocol, (VOID*)&Volume);
    314 
    315     //
    316     // Open the root directory of the volume
    317     //
    318 
    319     if (!EFI_ERROR(Status)) {
    320         Status = uefi_call_wrapper(Volume->OpenVolume, 2, Volume, &File);
    321     }
    322 
    323     //
    324     // Done
    325     //
    326 
    327     return EFI_ERROR(Status) ? NULL : File;
    328 }
    329 
    330 EFI_FILE_INFO *
    331 LibFileInfo (
    332     IN EFI_FILE_HANDLE      FHand
    333     )
    334 {
    335     EFI_STATUS              Status;
    336     EFI_FILE_INFO           *Buffer;
    337     UINTN                   BufferSize;
    338 
    339     //
    340     // Initialize for GrowBuffer loop
    341     //
    342 
    343     Status = EFI_SUCCESS;
    344     Buffer = NULL;
    345     BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
    346 
    347     //
    348     // Call the real function
    349     //
    350 
    351     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    352         Status = uefi_call_wrapper(
    353 		    FHand->GetInfo,
    354 			4,
    355                     FHand,
    356                     &GenericFileInfo,
    357                     &BufferSize,
    358                     Buffer
    359                     );
    360     }
    361 
    362     return Buffer;
    363 }
    364 
    365 
    366 EFI_FILE_SYSTEM_INFO *
    367 LibFileSystemInfo (
    368     IN EFI_FILE_HANDLE      FHand
    369     )
    370 {
    371     EFI_STATUS              Status;
    372     EFI_FILE_SYSTEM_INFO    *Buffer;
    373     UINTN                   BufferSize;
    374 
    375     //
    376     // Initialize for GrowBuffer loop
    377     //
    378 
    379     Status = EFI_SUCCESS;
    380     Buffer = NULL;
    381     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + 200;
    382 
    383     //
    384     // Call the real function
    385     //
    386 
    387     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    388         Status = uefi_call_wrapper(
    389 		    FHand->GetInfo,
    390 			4,
    391                     FHand,
    392                     &FileSystemInfo,
    393                     &BufferSize,
    394                     Buffer
    395                     );
    396     }
    397 
    398     return Buffer;
    399 }
    400 
    401 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *
    402 LibFileSystemVolumeLabelInfo (
    403     IN EFI_FILE_HANDLE      FHand
    404     )
    405 {
    406     EFI_STATUS                        Status;
    407     EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;
    408     UINTN                             BufferSize;
    409 
    410     //
    411     // Initialize for GrowBuffer loop
    412     //
    413 
    414     Status = EFI_SUCCESS;
    415     Buffer = NULL;
    416     BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;
    417 
    418     //
    419     // Call the real function
    420     //
    421 
    422     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    423         Status = uefi_call_wrapper(
    424 		    FHand->GetInfo,
    425 			4,
    426                     FHand,
    427                     &FileSystemVolumeLabelInfo,
    428                     &BufferSize,
    429                     Buffer
    430                     );
    431     }
    432 
    433     return Buffer;
    434 }
    435 
    436 
    437 
    438 EFI_STATUS
    439 LibInstallProtocolInterfaces (
    440     IN OUT EFI_HANDLE           *Handle,
    441     ...
    442     )
    443 {
    444     va_list         args;
    445     EFI_STATUS      Status;
    446     EFI_GUID        *Protocol;
    447     VOID            *Interface;
    448     EFI_TPL         OldTpl;
    449     UINTN           Index;
    450     EFI_HANDLE      OldHandle;
    451 
    452     //
    453     // Syncronize with notifcations
    454     //
    455 
    456     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
    457     OldHandle = *Handle;
    458 
    459     //
    460     // Install the protocol interfaces
    461     //
    462 
    463     Index = 0;
    464     Status = EFI_SUCCESS;
    465     va_start (args, Handle);
    466 
    467     while (!EFI_ERROR(Status)) {
    468 
    469         //
    470         // If protocol is NULL, then it's the end of the list
    471         //
    472 
    473         Protocol = va_arg(args, EFI_GUID *);
    474         if (!Protocol) {
    475             break;
    476         }
    477 
    478         Interface = va_arg(args, VOID *);
    479 
    480         //
    481         // Install it
    482         //
    483 
    484         DEBUG((D_INFO, "LibInstallProtocolInterface: %d %x\n", Protocol, Interface));
    485         Status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
    486         if (EFI_ERROR(Status)) {
    487             break;
    488         }
    489 
    490         Index += 1;
    491     }
    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     }
    511 
    512     //
    513     // Done
    514     //
    515 
    516     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
    517     return Status;
    518 }
    519 
    520 
    521 VOID
    522 LibUninstallProtocolInterfaces (
    523     IN EFI_HANDLE           Handle,
    524     ...
    525     )
    526 {
    527     va_list         args;
    528     EFI_STATUS      Status;
    529     EFI_GUID        *Protocol;
    530     VOID            *Interface;
    531 
    532 
    533     va_start (args, Handle);
    534     for (; ;) {
    535 
    536         //
    537         // If protocol is NULL, then it's the end of the list
    538         //
    539 
    540         Protocol = va_arg(args, EFI_GUID *);
    541         if (!Protocol) {
    542             break;
    543         }
    544 
    545         Interface = va_arg(args, VOID *);
    546 
    547         //
    548         // Uninstall it
    549         //
    550 
    551         Status = uefi_call_wrapper(BS->UninstallProtocolInterface, 3, Handle, Protocol, Interface);
    552         if (EFI_ERROR(Status)) {
    553             DEBUG((D_ERROR, "LibUninstallProtocolInterfaces: failed %g, %r\n", Protocol, Handle));
    554         }
    555     }
    556 }
    557 
    558 
    559 EFI_STATUS
    560 LibReinstallProtocolInterfaces (
    561     IN OUT EFI_HANDLE           *Handle,
    562     ...
    563     )
    564 {
    565     va_list         args;
    566     EFI_STATUS      Status;
    567     EFI_GUID        *Protocol;
    568     VOID            *OldInterface, *NewInterface;
    569     EFI_TPL         OldTpl;
    570     UINTN           Index;
    571 
    572     //
    573     // Syncronize with notifcations
    574     //
    575 
    576     OldTpl = uefi_call_wrapper(BS->RaiseTPL, 1, TPL_NOTIFY);
    577 
    578     //
    579     // Install the protocol interfaces
    580     //
    581 
    582     Index = 0;
    583     Status = EFI_SUCCESS;
    584     va_start (args, Handle);
    585 
    586     while (!EFI_ERROR(Status)) {
    587 
    588         //
    589         // If protocol is NULL, then it's the end of the list
    590         //
    591 
    592         Protocol = va_arg(args, EFI_GUID *);
    593         if (!Protocol) {
    594             break;
    595         }
    596 
    597         OldInterface = va_arg(args, VOID *);
    598         NewInterface = va_arg(args, VOID *);
    599 
    600         //
    601         // Reinstall it
    602         //
    603 
    604         Status = uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, OldInterface, NewInterface);
    605         if (EFI_ERROR(Status)) {
    606             break;
    607         }
    608 
    609         Index += 1;
    610     }
    611 
    612     //
    613     // If there was an error, undo all the interfaces that were
    614     // reinstalled without any errors
    615     //
    616 
    617     if (EFI_ERROR(Status)) {
    618         va_start (args, Handle);
    619         while (Index) {
    620 
    621             Protocol = va_arg(args, EFI_GUID *);
    622             OldInterface = va_arg(args, VOID *);
    623             NewInterface = va_arg(args, VOID *);
    624 
    625             uefi_call_wrapper(BS->ReinstallProtocolInterface, 4, Handle, Protocol, NewInterface, OldInterface);
    626 
    627             Index -= 1;
    628         }
    629     }
    630 
    631     //
    632     // Done
    633     //
    634 
    635     uefi_call_wrapper(BS->RestoreTPL, 1, OldTpl);
    636     return Status;
    637 }
    638