Home | History | Annotate | Download | only in lib
      1 /*++
      2 
      3 Copyright (c) 1998  Intel Corporation
      4 
      5 Module Name:
      6 
      7     misc.c
      8 
      9 Abstract:
     10 
     11 
     12 
     13 
     14 Revision History
     15 
     16 --*/
     17 
     18 #include "lib.h"
     19 
     20 
     21 //
     22 //
     23 //
     24 
     25 VOID *
     26 AllocatePool (
     27     IN UINTN                Size
     28     )
     29 {
     30     EFI_STATUS              Status;
     31     VOID                    *p;
     32 
     33     Status = uefi_call_wrapper(BS->AllocatePool, 3, PoolAllocationType, Size, &p);
     34     if (EFI_ERROR(Status)) {
     35         DEBUG((D_ERROR, "AllocatePool: out of pool  %x\n", Status));
     36         p = NULL;
     37     }
     38     return p;
     39 }
     40 
     41 VOID *
     42 AllocateZeroPool (
     43     IN UINTN                Size
     44     )
     45 {
     46     VOID                    *p;
     47 
     48     p = AllocatePool (Size);
     49     if (p) {
     50         ZeroMem (p, Size);
     51     }
     52 
     53     return p;
     54 }
     55 
     56 VOID *
     57 ReallocatePool (
     58     IN VOID                 *OldPool,
     59     IN UINTN                OldSize,
     60     IN UINTN                NewSize
     61     )
     62 {
     63     VOID                    *NewPool;
     64 
     65     NewPool = NULL;
     66     if (NewSize) {
     67         NewPool = AllocatePool (NewSize);
     68     }
     69 
     70     if (OldPool) {
     71         if (NewPool) {
     72             CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
     73         }
     74 
     75         FreePool (OldPool);
     76     }
     77 
     78     return NewPool;
     79 }
     80 
     81 
     82 VOID
     83 FreePool (
     84     IN VOID                 *Buffer
     85     )
     86 {
     87     uefi_call_wrapper(BS->FreePool, 1, Buffer);
     88 }
     89 
     90 
     91 
     92 VOID
     93 ZeroMem (
     94     IN VOID     *Buffer,
     95     IN UINTN    Size
     96     )
     97 {
     98     RtZeroMem (Buffer, Size);
     99 }
    100 
    101 VOID
    102 SetMem (
    103     IN VOID     *Buffer,
    104     IN UINTN    Size,
    105     IN UINT8    Value
    106     )
    107 {
    108     RtSetMem (Buffer, Size, Value);
    109 }
    110 
    111 VOID
    112 CopyMem (
    113     IN VOID     *Dest,
    114     IN CONST VOID     *Src,
    115     IN UINTN    len
    116     )
    117 {
    118     RtCopyMem (Dest, Src, len);
    119 }
    120 
    121 INTN
    122 CompareMem (
    123     IN CONST VOID     *Dest,
    124     IN CONST VOID     *Src,
    125     IN UINTN    len
    126     )
    127 {
    128     return RtCompareMem (Dest, Src, len);
    129 }
    130 
    131 BOOLEAN
    132 GrowBuffer(
    133     IN OUT EFI_STATUS   *Status,
    134     IN OUT VOID         **Buffer,
    135     IN UINTN            BufferSize
    136     )
    137 /*++
    138 
    139 Routine Description:
    140 
    141     Helper function called as part of the code needed
    142     to allocate the proper sized buffer for various
    143     EFI interfaces.
    144 
    145 Arguments:
    146 
    147     Status      - Current status
    148 
    149     Buffer      - Current allocated buffer, or NULL
    150 
    151     BufferSize  - Current buffer size needed
    152 
    153 Returns:
    154 
    155     TRUE - if the buffer was reallocated and the caller
    156     should try the API again.
    157 
    158 --*/
    159 {
    160     BOOLEAN         TryAgain;
    161 
    162     //
    163     // If this is an initial request, buffer will be null with a new buffer size
    164     //
    165 
    166     if (!*Buffer && BufferSize) {
    167         *Status = EFI_BUFFER_TOO_SMALL;
    168     }
    169 
    170     //
    171     // If the status code is "buffer too small", resize the buffer
    172     //
    173 
    174     TryAgain = FALSE;
    175     if (*Status == EFI_BUFFER_TOO_SMALL) {
    176 
    177         if (*Buffer) {
    178             FreePool (*Buffer);
    179         }
    180 
    181         *Buffer = AllocatePool (BufferSize);
    182 
    183         if (*Buffer) {
    184             TryAgain = TRUE;
    185         } else {
    186             *Status = EFI_OUT_OF_RESOURCES;
    187         }
    188     }
    189 
    190     //
    191     // If there's an error, free the buffer
    192     //
    193 
    194     if (!TryAgain && EFI_ERROR(*Status) && *Buffer) {
    195         FreePool (*Buffer);
    196         *Buffer = NULL;
    197     }
    198 
    199     return TryAgain;
    200 }
    201 
    202 
    203 EFI_MEMORY_DESCRIPTOR *
    204 LibMemoryMap (
    205     OUT UINTN               *NoEntries,
    206     OUT UINTN               *MapKey,
    207     OUT UINTN               *DescriptorSize,
    208     OUT UINT32              *DescriptorVersion
    209     )
    210 {
    211     EFI_STATUS              Status;
    212     EFI_MEMORY_DESCRIPTOR   *Buffer;
    213     UINTN                   BufferSize;
    214 
    215     //
    216     // Initialize for GrowBuffer loop
    217     //
    218 
    219     Status = EFI_SUCCESS;
    220     Buffer = NULL;
    221     BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
    222 
    223     //
    224     // Call the real function
    225     //
    226 
    227     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
    228         Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
    229     }
    230 
    231     //
    232     // Convert buffer size to NoEntries
    233     //
    234 
    235     if (!EFI_ERROR(Status)) {
    236         *NoEntries = BufferSize / *DescriptorSize;
    237     }
    238 
    239     return Buffer;
    240 }
    241 
    242 VOID *
    243 LibGetVariableAndSize (
    244     IN CHAR16               *Name,
    245     IN EFI_GUID             *VendorGuid,
    246     OUT UINTN               *VarSize
    247     )
    248 {
    249     EFI_STATUS              Status;
    250     VOID                    *Buffer;
    251     UINTN                   BufferSize;
    252 
    253     //
    254     // Initialize for GrowBuffer loop
    255     //
    256 
    257     Buffer = NULL;
    258     BufferSize = 100;
    259 
    260     //
    261     // Call the real function
    262     //
    263 
    264     while (GrowBuffer (&Status, &Buffer, BufferSize)) {
    265         Status = uefi_call_wrapper(
    266 		    RT->GetVariable,
    267 			5,
    268                     Name,
    269                     VendorGuid,
    270                     NULL,
    271                     &BufferSize,
    272                     Buffer
    273                     );
    274     }
    275     if (Buffer) {
    276         *VarSize = BufferSize;
    277     } else {
    278         *VarSize = 0;
    279     }
    280     return Buffer;
    281 }
    282 
    283 VOID *
    284 LibGetVariable (
    285     IN CHAR16               *Name,
    286     IN EFI_GUID             *VendorGuid
    287     )
    288 {
    289     UINTN   VarSize;
    290 
    291     return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
    292 }
    293 
    294 EFI_STATUS
    295 LibDeleteVariable (
    296     IN CHAR16   *VarName,
    297     IN EFI_GUID *VarGuid
    298     )
    299 {
    300     VOID        *VarBuf;
    301     EFI_STATUS  Status;
    302 
    303     VarBuf = LibGetVariable(VarName,VarGuid);
    304 
    305     Status = EFI_NOT_FOUND;
    306 
    307     if (VarBuf) {
    308         //
    309         // Delete variable from Storage
    310         //
    311         Status = uefi_call_wrapper(
    312 		    RT->SetVariable,
    313 			5,
    314                     VarName, VarGuid,
    315                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    316                     0, NULL
    317                  );
    318         ASSERT (!EFI_ERROR(Status));
    319         FreePool(VarBuf);
    320     }
    321 
    322     return (Status);
    323 }
    324 
    325 EFI_STATUS
    326 LibSetNVVariable (
    327     IN CHAR16   *VarName,
    328     IN EFI_GUID *VarGuid,
    329     IN UINTN	 DataSize,
    330     IN VOID     *Data
    331     )
    332 {
    333     EFI_STATUS  Status;
    334 
    335     Status = uefi_call_wrapper(
    336 	    RT->SetVariable,
    337 	    5,
    338 	    VarName, VarGuid,
    339 	    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    340 	    DataSize, Data
    341 	    );
    342     ASSERT (!EFI_ERROR(Status));
    343     return (Status);
    344 }
    345 
    346 EFI_STATUS
    347 LibSetVariable (
    348     IN CHAR16   *VarName,
    349     IN EFI_GUID *VarGuid,
    350     IN UINTN	 DataSize,
    351     IN VOID     *Data
    352     )
    353 {
    354     EFI_STATUS  Status;
    355 
    356     Status = uefi_call_wrapper(
    357 	    RT->SetVariable,
    358 	    5,
    359 	    VarName, VarGuid,
    360 	    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
    361 	    DataSize, Data
    362 	    );
    363     ASSERT (!EFI_ERROR(Status));
    364     return (Status);
    365 }
    366 
    367 EFI_STATUS
    368 LibInsertToTailOfBootOrder (
    369     IN  UINT16  BootOption,
    370     IN  BOOLEAN OnlyInsertIfEmpty
    371     )
    372 {
    373     UINT16      *BootOptionArray;
    374     UINT16      *NewBootOptionArray;
    375     UINTN       VarSize;
    376     UINTN       Index;
    377     EFI_STATUS  Status;
    378 
    379     BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
    380     if (VarSize != 0 && OnlyInsertIfEmpty) {
    381         if (BootOptionArray) {
    382             FreePool (BootOptionArray);
    383         }
    384         return EFI_UNSUPPORTED;
    385     }
    386 
    387     VarSize += sizeof(UINT16);
    388     NewBootOptionArray = AllocatePool (VarSize);
    389 
    390     for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
    391         NewBootOptionArray[Index] = BootOptionArray[Index];
    392     }
    393     //
    394     // Insert in the tail of the array
    395     //
    396     NewBootOptionArray[Index] = BootOption;
    397 
    398     Status = uefi_call_wrapper(
    399 		RT->SetVariable,
    400 		5,
    401                 VarBootOrder, &EfiGlobalVariable,
    402                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    403                 VarSize, (VOID*) NewBootOptionArray
    404                 );
    405 
    406     if (NewBootOptionArray) {
    407         FreePool (NewBootOptionArray);
    408     }
    409     if (BootOptionArray) {
    410         FreePool (BootOptionArray);
    411     }
    412     return Status;
    413 }
    414 
    415 
    416 BOOLEAN
    417 ValidMBR(
    418     IN  MASTER_BOOT_RECORD  *Mbr,
    419     IN  EFI_BLOCK_IO        *BlkIo
    420     )
    421 {
    422     UINT32      StartingLBA, EndingLBA;
    423     UINT32      NewEndingLBA;
    424     INTN        i, j;
    425     BOOLEAN     ValidMbr;
    426 
    427     if (Mbr->Signature != MBR_SIGNATURE) {
    428         //
    429         // The BPB also has this signature, so it can not be used alone.
    430         //
    431         return FALSE;
    432     }
    433 
    434     ValidMbr = FALSE;
    435     for (i=0; i<MAX_MBR_PARTITIONS; i++) {
    436         if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
    437             continue;
    438         }
    439         ValidMbr = TRUE;
    440         StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
    441         EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
    442         if (EndingLBA > BlkIo->Media->LastBlock) {
    443             //
    444             // Compatability Errata:
    445             //  Some systems try to hide drive space with thier INT 13h driver
    446             //  This does not hide space from the OS driver. This means the MBR
    447             //  that gets created from DOS is smaller than the MBR created from
    448             //  a real OS (NT & Win98). This leads to BlkIo->LastBlock being
    449             //  wrong on some systems FDISKed by the OS.
    450             //
    451             //
    452             if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
    453                 //
    454                 // If this is a very small device then trust the BlkIo->LastBlock
    455                 //
    456                 return FALSE;
    457             }
    458 
    459             if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
    460                 return FALSE;
    461             }
    462 
    463         }
    464         for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
    465             if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
    466                 continue;
    467             }
    468             if (   EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
    469                    EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA       ) {
    470                 //
    471                 // The Start of this region overlaps with the i'th region
    472                 //
    473                 return FALSE;
    474             }
    475             NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
    476             if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
    477                 //
    478                 // The End of this region overlaps with the i'th region
    479                 //
    480                 return FALSE;
    481             }
    482         }
    483     }
    484     //
    485     // Non of the regions overlapped so MBR is O.K.
    486     //
    487     return ValidMbr;
    488 }
    489 
    490 
    491 UINT8
    492 DecimaltoBCD(
    493     IN  UINT8 DecValue
    494     )
    495 {
    496     return RtDecimaltoBCD (DecValue);
    497 }
    498 
    499 
    500 UINT8
    501 BCDtoDecimal(
    502     IN  UINT8 BcdValue
    503     )
    504 {
    505     return RtBCDtoDecimal (BcdValue);
    506 }
    507 
    508 EFI_STATUS
    509 LibGetSystemConfigurationTable(
    510     IN EFI_GUID *TableGuid,
    511     IN OUT VOID **Table
    512     )
    513 
    514 {
    515     UINTN Index;
    516 
    517     for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
    518         if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
    519             *Table = ST->ConfigurationTable[Index].VendorTable;
    520             return EFI_SUCCESS;
    521         }
    522     }
    523     return EFI_NOT_FOUND;
    524 }
    525 
    526 
    527 CHAR16 *
    528 LibGetUiString (
    529     IN  EFI_HANDLE      Handle,
    530     IN  UI_STRING_TYPE  StringType,
    531     IN  ISO_639_2       *LangCode,
    532     IN  BOOLEAN         ReturnDevicePathStrOnMismatch
    533     )
    534 {
    535     UI_INTERFACE    *Ui;
    536     UI_STRING_TYPE  Index;
    537     UI_STRING_ENTRY *Array;
    538     EFI_STATUS      Status;
    539 
    540     Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
    541     if (EFI_ERROR(Status)) {
    542         return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
    543     }
    544 
    545     //
    546     // Skip the first strings
    547     //
    548     for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
    549         while (Array->LangCode) {
    550             Array++;
    551         }
    552     }
    553 
    554     //
    555     // Search for the match
    556     //
    557     while (Array->LangCode) {
    558         if (strcmpa (Array->LangCode, LangCode) == 0) {
    559             return Array->UiString;
    560         }
    561     }
    562     return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
    563 }
    564