0,0 → 1,514 |
/*++ |
|
Copyright (c) 1998 Intel Corporation |
|
Module Name: |
|
misc.c |
|
Abstract: |
|
|
|
|
Revision History |
|
--*/ |
|
#include "lib.h" |
|
|
// |
// |
// |
|
VOID * |
AllocatePool ( |
IN UINTN Size |
) |
{ |
EFI_STATUS Status; |
VOID *p; |
|
Status = BS->AllocatePool (PoolAllocationType, Size, &p); |
if (EFI_ERROR(Status)) { |
DEBUG((D_ERROR, "AllocatePool: out of pool %x\n", Status)); |
p = NULL; |
} |
return p; |
} |
|
VOID * |
AllocateZeroPool ( |
IN UINTN Size |
) |
{ |
VOID *p; |
|
p = AllocatePool (Size); |
if (p) { |
ZeroMem (p, Size); |
} |
|
return p; |
} |
|
VOID * |
ReallocatePool ( |
IN VOID *OldPool, |
IN UINTN OldSize, |
IN UINTN NewSize |
) |
{ |
VOID *NewPool; |
|
NewPool = NULL; |
if (NewSize) { |
NewPool = AllocatePool (NewSize); |
} |
|
if (OldPool) { |
if (NewPool) { |
CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); |
} |
|
FreePool (OldPool); |
} |
|
return NewPool; |
} |
|
|
VOID |
FreePool ( |
IN VOID *Buffer |
) |
{ |
BS->FreePool (Buffer); |
} |
|
|
|
VOID |
ZeroMem ( |
IN VOID *Buffer, |
IN UINTN Size |
) |
{ |
RtZeroMem (Buffer, Size); |
} |
|
VOID |
SetMem ( |
IN VOID *Buffer, |
IN UINTN Size, |
IN UINT8 Value |
) |
{ |
RtSetMem (Buffer, Size, Value); |
} |
|
VOID |
CopyMem ( |
IN VOID *Dest, |
IN VOID *Src, |
IN UINTN len |
) |
{ |
RtCopyMem (Dest, Src, len); |
} |
|
INTN |
CompareMem ( |
IN VOID *Dest, |
IN VOID *Src, |
IN UINTN len |
) |
{ |
return RtCompareMem (Dest, Src, len); |
} |
|
BOOLEAN |
GrowBuffer( |
IN OUT EFI_STATUS *Status, |
IN OUT VOID **Buffer, |
IN UINTN BufferSize |
) |
/*++ |
|
Routine Description: |
|
Helper function called as part of the code needed |
to allocate the proper sized buffer for various |
EFI interfaces. |
|
Arguments: |
|
Status - Current status |
|
Buffer - Current allocated buffer, or NULL |
|
BufferSize - Current buffer size needed |
|
Returns: |
|
TRUE - if the buffer was reallocated and the caller |
should try the API again. |
|
--*/ |
{ |
BOOLEAN TryAgain; |
|
// |
// If this is an initial request, buffer will be null with a new buffer size |
// |
|
if (!*Buffer && BufferSize) { |
*Status = EFI_BUFFER_TOO_SMALL; |
} |
|
// |
// If the status code is "buffer too small", resize the buffer |
// |
|
TryAgain = FALSE; |
if (*Status == EFI_BUFFER_TOO_SMALL) { |
|
if (*Buffer) { |
FreePool (*Buffer); |
} |
|
*Buffer = AllocatePool (BufferSize); |
|
if (*Buffer) { |
TryAgain = TRUE; |
} else { |
*Status = EFI_OUT_OF_RESOURCES; |
} |
} |
|
// |
// If there's an error, free the buffer |
// |
|
if (!TryAgain && EFI_ERROR(*Status) && *Buffer) { |
FreePool (*Buffer); |
*Buffer = NULL; |
} |
|
return TryAgain; |
} |
|
|
EFI_MEMORY_DESCRIPTOR * |
LibMemoryMap ( |
OUT UINTN *NoEntries, |
OUT UINTN *MapKey, |
OUT UINTN *DescriptorSize, |
OUT UINT32 *DescriptorVersion |
) |
{ |
EFI_STATUS Status; |
EFI_MEMORY_DESCRIPTOR *Buffer; |
UINTN BufferSize; |
|
// |
// Initialize for GrowBuffer loop |
// |
|
Buffer = NULL; |
BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR); |
|
// |
// Call the real function |
// |
|
while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { |
Status = BS->GetMemoryMap (&BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion); |
} |
|
// |
// Convert buffer size to NoEntries |
// |
|
if (!EFI_ERROR(Status)) { |
*NoEntries = BufferSize / *DescriptorSize; |
} |
|
return Buffer; |
} |
|
VOID * |
LibGetVariableAndSize ( |
IN CHAR16 *Name, |
IN EFI_GUID *VendorGuid, |
OUT UINTN *VarSize |
) |
{ |
EFI_STATUS Status; |
VOID *Buffer; |
UINTN BufferSize; |
|
// |
// Initialize for GrowBuffer loop |
// |
|
Buffer = NULL; |
BufferSize = 100; |
|
// |
// Call the real function |
// |
|
while (GrowBuffer (&Status, &Buffer, BufferSize)) { |
Status = RT->GetVariable ( |
Name, |
VendorGuid, |
NULL, |
&BufferSize, |
Buffer |
); |
} |
if (Buffer) { |
*VarSize = BufferSize; |
} else { |
*VarSize = 0; |
} |
return Buffer; |
} |
|
VOID * |
LibGetVariable ( |
IN CHAR16 *Name, |
IN EFI_GUID *VendorGuid |
) |
{ |
UINTN VarSize; |
|
return LibGetVariableAndSize (Name, VendorGuid, &VarSize); |
} |
|
EFI_STATUS |
LibDeleteVariable ( |
IN CHAR16 *VarName, |
IN EFI_GUID *VarGuid |
) |
{ |
VOID *VarBuf; |
EFI_STATUS Status; |
|
VarBuf = LibGetVariable(VarName,VarGuid); |
|
Status = EFI_NOT_FOUND; |
|
if (VarBuf) { |
// |
// Delete variable from Storage |
// |
Status = RT->SetVariable ( |
VarName, VarGuid, |
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, |
0, NULL |
); |
ASSERT (!EFI_ERROR(Status)); |
FreePool(VarBuf); |
} |
|
return (Status); |
} |
|
EFI_STATUS |
LibInsertToTailOfBootOrder ( |
IN UINT16 BootOption, |
IN BOOLEAN OnlyInsertIfEmpty |
) |
{ |
UINT16 *BootOptionArray; |
UINT16 *NewBootOptionArray; |
UINTN VarSize; |
UINTN Index; |
EFI_STATUS Status; |
|
BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize); |
if (VarSize != 0 && OnlyInsertIfEmpty) { |
if (BootOptionArray) { |
FreePool (BootOptionArray); |
} |
return EFI_UNSUPPORTED; |
} |
|
VarSize += sizeof(UINT16); |
NewBootOptionArray = AllocatePool (VarSize); |
|
for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) { |
NewBootOptionArray[Index] = BootOptionArray[Index]; |
} |
// |
// Insert in the tail of the array |
// |
NewBootOptionArray[Index] = BootOption; |
|
Status = RT->SetVariable ( |
VarBootOrder, &EfiGlobalVariable, |
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, |
VarSize, (VOID*) NewBootOptionArray |
); |
|
if (NewBootOptionArray) { |
FreePool (NewBootOptionArray); |
} |
if (BootOptionArray) { |
FreePool (BootOptionArray); |
} |
return Status; |
} |
|
|
BOOLEAN |
ValidMBR( |
IN MASTER_BOOT_RECORD *Mbr, |
IN EFI_BLOCK_IO *BlkIo |
) |
{ |
UINT32 StartingLBA, EndingLBA; |
UINT32 NewEndingLBA; |
INTN i, j; |
BOOLEAN ValidMbr; |
|
if (Mbr->Signature != MBR_SIGNATURE) { |
// |
// The BPB also has this signature, so it can not be used alone. |
// |
return FALSE; |
} |
|
ValidMbr = FALSE; |
for (i=0; i<MAX_MBR_PARTITIONS; i++) { |
if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) { |
continue; |
} |
ValidMbr = TRUE; |
StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA); |
EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1; |
if (EndingLBA > BlkIo->Media->LastBlock) { |
// |
// Compatability Errata: |
// Some systems try to hide drive space with thier INT 13h driver |
// This does not hide space from the OS driver. This means the MBR |
// that gets created from DOS is smaller than the MBR created from |
// a real OS (NT & Win98). This leads to BlkIo->LastBlock being |
// wrong on some systems FDISKed by the OS. |
// |
// |
if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) { |
// |
// If this is a very small device then trust the BlkIo->LastBlock |
// |
return FALSE; |
} |
|
if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) { |
return FALSE; |
} |
|
} |
for (j=i+1; j<MAX_MBR_PARTITIONS; j++) { |
if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) { |
continue; |
} |
if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA && |
EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) { |
// |
// The Start of this region overlaps with the i'th region |
// |
return FALSE; |
} |
NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1; |
if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) { |
// |
// The End of this region overlaps with the i'th region |
// |
return FALSE; |
} |
} |
} |
// |
// Non of the regions overlapped so MBR is O.K. |
// |
return ValidMbr; |
} |
|
|
UINT8 |
DecimaltoBCD( |
IN UINT8 DecValue |
) |
{ |
return RtDecimaltoBCD (DecValue); |
} |
|
|
UINT8 |
BCDtoDecimal( |
IN UINT8 BcdValue |
) |
{ |
return RtBCDtoDecimal (BcdValue); |
} |
|
EFI_STATUS |
LibGetSystemConfigurationTable( |
IN EFI_GUID *TableGuid, |
IN OUT VOID **Table |
) |
|
{ |
UINTN Index; |
|
for(Index=0;Index<ST->NumberOfTableEntries;Index++) { |
if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) { |
*Table = ST->ConfigurationTable[Index].VendorTable; |
return EFI_SUCCESS; |
} |
} |
return EFI_NOT_FOUND; |
} |
|
|
CHAR16 * |
LibGetUiString ( |
IN EFI_HANDLE Handle, |
IN UI_STRING_TYPE StringType, |
IN ISO_639_2 *LangCode, |
IN BOOLEAN ReturnDevicePathStrOnMismatch |
) |
{ |
UI_INTERFACE *Ui; |
UI_STRING_TYPE Index; |
UI_STRING_ENTRY *Array; |
EFI_STATUS Status; |
|
Status = BS->HandleProtocol (Handle, &UiProtocol, (VOID *)&Ui); |
if (EFI_ERROR(Status)) { |
return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL; |
} |
|
// |
// Skip the first strings |
// |
for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) { |
while (Array->LangCode) { |
Array++; |
} |
} |
|
// |
// Search for the match |
// |
while (Array->LangCode) { |
if (strcmpa (Array->LangCode, LangCode) == 0) { |
return Array->UiString; |
} |
} |
return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL; |
} |