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