2019-09-03 11:58:42 +02:00
/*
* refit / lib . c
* General library functions
*
* Copyright ( c ) 2006 - 2009 Christoph Pfisterer
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are
* met :
*
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
*
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the
* distribution .
*
* * Neither the name of Christoph Pfisterer nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "Platform.h"
# ifndef DEBUG_ALL
# define DEBUG_LIB 1
# else
# define DEBUG_LIB DEBUG_ALL
# endif
# if DEBUG_LIB == 0
# define DBG(...)
# else
# define DBG(...) DebugLog(DEBUG_LIB, __VA_ARGS__)
# endif
// variables
EFI_HANDLE SelfImageHandle ;
EFI_HANDLE SelfDeviceHandle ;
EFI_LOADED_IMAGE * SelfLoadedImage ;
EFI_FILE * SelfRootDir ;
EFI_FILE * SelfDir ;
CHAR16 * SelfDirPath ;
EFI_DEVICE_PATH * SelfDevicePath ;
EFI_DEVICE_PATH * SelfFullDevicePath ;
EFI_FILE * ThemeDir = NULL ;
CHAR16 * ThemePath ;
BOOLEAN gThemeChanged = FALSE ;
//BOOLEAN gBootArgsChanged = FALSE;
BOOLEAN gBootChanged = FALSE ;
BOOLEAN gThemeOptionsChanged = FALSE ;
EFI_FILE * OEMDir ;
2020-02-20 17:24:30 +01:00
CHAR16 * OEMPath ;
2019-09-03 11:58:42 +02:00
EFI_FILE * OemThemeDir = NULL ;
REFIT_VOLUME * SelfVolume = NULL ;
2020-02-27 15:34:29 +01:00
//REFIT_VOLUME **Volumes = NULL;
//UINTN VolumesCount = 0;
XObjArray < REFIT_VOLUME > Volumes ;
2019-09-03 11:58:42 +02:00
//
// Unicode collation protocol interface
//
EFI_UNICODE_COLLATION_PROTOCOL * mUnicodeCollation = NULL ;
// functions
static EFI_STATUS FinishInitRefitLib ( VOID ) ;
static VOID UninitVolumes ( VOID ) ;
// S. Mtr
/* Function for parsing nodes from device path
* IN : DevicePath , sizeof ( DevicePath )
* OUT : Size of cutted device path
* Description :
* Device path contains device nodes .
* From UEFI specification device node struct looks like :
* typedef struct {
* UINT8 Type ; ///< 0x01 Hardware Device Path.
* ///< 0x02 ACPI Device Path.
* ///< 0x03 Messaging Device Path.
* ///< 0x04 Media Device Path.
* ///< 0x05 BIOS Boot Specification Device Path.
* ///< 0x7F End of Hardware Device Path.
*
* UINT8 SubType ; ///< Varies by Type
* ///< 0xFF End Entire Device Path, or
* ///< 0x01 End This Instance of a Device Path and start a new
* ///< Device Path.
*
* UINT8 Length [ 2 ] ; ///< Specific Device Path data. Type and Sub-Type define
* ///< type of data. Size of data is included in Length.
*
* } EFI_DEVICE_PATH_PROTOCOL ;
*/
UINTN
NodeParser ( UINT8 * DevPath , UINTN PathSize , UINT8 Type )
{
UINTN i ;
for ( i = 0 ; i < PathSize + 1 ; ) {
if ( DevPath [ i ] = = Type )
{
//This type corresponds to Type
//So.. save position and exit from loop
PathSize = i ;
break ;
}
//Jump to the next device node type
i + = ( ( ( UINT16 ) DevPath [ i + 3 ] < < 8 ) | DevPath [ i + 2 ] ) ;
}
return PathSize ;
}
BOOLEAN MetaiMatch (
2020-02-17 21:41:09 +01:00
IN CONST CHAR16 * String ,
IN CONST CHAR16 * Pattern
2019-09-03 11:58:42 +02:00
) ;
/**
This function converts an input device structure to a Unicode string .
@ param DevPath A pointer to the device path structure .
@ return A new allocated Unicode string that represents the device path .
* */
CHAR16 *
EFIAPI
DevicePathToStr (
IN EFI_DEVICE_PATH_PROTOCOL * DevPath
)
{
return ConvertDevicePathToText ( DevPath , TRUE , TRUE ) ;
}
EFI_STATUS GetRootFromPath ( IN EFI_DEVICE_PATH_PROTOCOL * DevicePath , OUT EFI_FILE * * Root )
{
EFI_STATUS Status ;
EFI_HANDLE NewHandle ;
EFI_DEVICE_PATH_PROTOCOL * TmpDevicePath ;
// DBG("Try to duplicate DevicePath\n");
TmpDevicePath = DuplicateDevicePath ( DevicePath ) ;
// DBG("TmpDevicePath found\n");
NewHandle = NULL ;
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid ,
& TmpDevicePath ,
& NewHandle ) ;
// DBG("volume handle found =%x\n", NewHandle);
CheckError ( Status , L " while reopening volume handle " ) ;
* Root = EfiLibOpenRoot ( NewHandle ) ;
if ( * Root = = NULL ) {
// DBG("volume Root Dir can't be reopened\n");
return EFI_NOT_FOUND ;
}
if ( FileExists ( * Root , L " mach_kernel " ) ) {
DBG ( " mach_kernel exists \n " ) ;
} else {
DBG ( " mach_kernel not exists \n " ) ;
}
return Status ;
}
//
// self recognition stuff
//
EFI_STATUS InitRefitLib ( IN EFI_HANDLE ImageHandle )
{
EFI_STATUS Status ;
CHAR16 * FilePathAsString ;
UINTN i ;
UINTN DevicePathSize ;
EFI_DEVICE_PATH_PROTOCOL * TmpDevicePath ;
SelfImageHandle = ImageHandle ;
Status = gBS - > HandleProtocol ( SelfImageHandle , & gEfiLoadedImageProtocolGuid , ( VOID * * ) & SelfLoadedImage ) ;
if ( CheckFatalError ( Status , L " while getting a LoadedImageProtocol handle " ) )
return Status ;
SelfDeviceHandle = SelfLoadedImage - > DeviceHandle ;
TmpDevicePath = DevicePathFromHandle ( SelfDeviceHandle ) ;
DevicePathSize = GetDevicePathSize ( TmpDevicePath ) ;
2019-12-21 01:31:49 +01:00
SelfDevicePath = ( __typeof__ ( SelfDevicePath ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( DevicePathSize ) , 64 ) ;
2019-09-03 11:58:42 +02:00
CopyMem ( SelfDevicePath , TmpDevicePath , DevicePathSize ) ;
DBG ( " SelfDevicePath=%s @%x \n " , FileDevicePathToStr ( SelfDevicePath ) , SelfDeviceHandle ) ;
// find the current directory
FilePathAsString = FileDevicePathToStr ( SelfLoadedImage - > FilePath ) ;
if ( FilePathAsString ! = NULL ) {
SelfFullDevicePath = FileDevicePath ( SelfDeviceHandle , FilePathAsString ) ;
for ( i = StrLen ( FilePathAsString ) ; i > 0 & & FilePathAsString [ i ] ! = ' \\ ' ; i - - ) ;
if ( i > 0 ) {
FilePathAsString [ i ] = 0 ;
} else {
FilePathAsString [ 0 ] = L ' \\ ' ;
FilePathAsString [ 1 ] = 0 ;
}
} else {
2019-12-21 01:31:49 +01:00
FilePathAsString = ( __typeof__ ( FilePathAsString ) ) AllocateCopyPool ( StrSize ( L " \\ " ) , L " \\ " ) ;
2019-09-03 11:58:42 +02:00
}
SelfDirPath = FilePathAsString ;
DBG ( " SelfDirPath = %s \n " , SelfDirPath ) ;
return FinishInitRefitLib ( ) ;
}
VOID UninitRefitLib ( VOID )
{
// called before running external programs to close open file handles
if ( SelfDir ! = NULL ) {
SelfDir - > Close ( SelfDir ) ;
SelfDir = NULL ;
}
if ( OEMDir ! = NULL ) {
OEMDir - > Close ( OEMDir ) ;
OEMDir = NULL ;
}
if ( ThemeDir ! = NULL ) {
ThemeDir - > Close ( ThemeDir ) ;
ThemeDir = NULL ;
}
if ( SelfRootDir ! = NULL ) {
SelfRootDir - > Close ( SelfRootDir ) ;
SelfRootDir = NULL ;
}
UninitVolumes ( ) ;
}
EFI_STATUS ReinitRefitLib ( VOID )
{
// called after running external programs to re-open file handles
//
ReinitVolumes ( ) ;
if ( SelfVolume ! = NULL & & SelfVolume - > RootDir ! = NULL )
SelfRootDir = SelfVolume - > RootDir ;
return FinishInitRefitLib ( ) ;
}
EFI_STATUS ReinitSelfLib ( VOID )
{
// called after reconnect drivers to re-open file handles
EFI_STATUS Status ;
EFI_HANDLE NewSelfHandle ;
EFI_DEVICE_PATH_PROTOCOL * TmpDevicePath ;
// DbgHeader("ReinitSelfLib");
if ( ! SelfDevicePath ) {
return EFI_NOT_FOUND ;
}
TmpDevicePath = DuplicateDevicePath ( SelfDevicePath ) ;
DBG ( " reinit: self device path=%s \n " , FileDevicePathToStr ( TmpDevicePath ) ) ;
if ( TmpDevicePath = = NULL )
return EFI_NOT_FOUND ;
NewSelfHandle = NULL ;
Status = gBS - > LocateDevicePath ( & gEfiSimpleFileSystemProtocolGuid ,
& TmpDevicePath ,
& NewSelfHandle ) ;
CheckError ( Status , L " while reopening our self handle " ) ;
// DBG("new SelfHandle=%x\n", NewSelfHandle);
SelfRootDir = EfiLibOpenRoot ( NewSelfHandle ) ;
if ( SelfRootDir = = NULL ) {
DBG ( " SelfRootDir can't be reopened \n " ) ;
return EFI_NOT_FOUND ;
}
SelfDeviceHandle = NewSelfHandle ;
/*Status = */ SelfRootDir - > Open ( SelfRootDir , & ThemeDir , ThemePath , EFI_FILE_MODE_READ , 0 ) ;
/*Status = */ SelfRootDir - > Open ( SelfRootDir , & OEMDir , OEMPath , EFI_FILE_MODE_READ , 0 ) ;
Status = SelfRootDir - > Open ( SelfRootDir , & SelfDir , SelfDirPath , EFI_FILE_MODE_READ , 0 ) ;
CheckFatalError ( Status , L " while reopening our installation directory " ) ;
return Status ;
}
static
EFI_STATUS FinishInitRefitLib ( VOID )
{
EFI_STATUS Status ;
if ( SelfRootDir = = NULL ) {
SelfRootDir = EfiLibOpenRoot ( SelfLoadedImage - > DeviceHandle ) ;
if ( SelfRootDir ! = NULL ) {
SelfDeviceHandle = SelfLoadedImage - > DeviceHandle ;
} else {
return EFI_LOAD_ERROR ;
}
}
/*Status = */ SelfRootDir - > Open ( SelfRootDir , & ThemeDir , ThemePath , EFI_FILE_MODE_READ , 0 ) ;
/*Status = */ SelfRootDir - > Open ( SelfRootDir , & OEMDir , OEMPath , EFI_FILE_MODE_READ , 0 ) ;
Status = SelfRootDir - > Open ( SelfRootDir , & SelfDir , SelfDirPath , EFI_FILE_MODE_READ , 0 ) ;
CheckFatalError ( Status , L " while opening our installation directory " ) ;
return Status ;
}
BOOLEAN IsEmbeddedTheme ( )
{
if ( ! GlobalConfig . Theme | | ! StriCmp ( GlobalConfig . Theme , L " embedded " ) ) {
ThemeDir = NULL ;
}
return ThemeDir = = NULL ;
}
//
// list functions
//
2020-02-27 15:34:29 +01:00
//
//VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount)
//{
// UINTN AllocateCount;
//
// *ElementCount = InitialElementCount;
// if (*ElementCount > 0) {
// AllocateCount = (*ElementCount + 7) & ~7; // next multiple of 8
// *ListPtr = (__typeof_am__(*ListPtr))AllocatePool(sizeof(VOID *) * AllocateCount);
// } else {
// *ListPtr = NULL;
// }
//}
2020-02-28 21:28:33 +01:00
//
//VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement)
//{
// UINTN AllocateCount;
//
// if ((*ElementCount & 7) == 0) {
// AllocateCount = *ElementCount + 8;
// if (*ElementCount == 0)
// *ListPtr = (__typeof_am__(*ListPtr))AllocatePool(sizeof(VOID *) * AllocateCount);
// else
// *ListPtr = (__typeof_am__(*ListPtr))EfiReallocatePool((VOID *)*ListPtr, sizeof(VOID *) * (*ElementCount), sizeof(VOID *) * AllocateCount);
// }
// (*ListPtr)[*ElementCount] = NewElement;
// (*ElementCount)++;
//}
2019-09-03 11:58:42 +02:00
/*
VOID FreeList ( IN OUT VOID * * * ListPtr , IN OUT UINTN * ElementCount )
{
UINTN i ;
if ( * ElementCount > 0 ) {
for ( i = 0 ; i < * ElementCount ; i + + ) {
// TODO: call a user-provided routine for each element here
FreePool ( ( * ListPtr ) [ i ] ) ;
}
FreePool ( * ListPtr ) ;
}
}
*/
//
// firmware device path discovery
//
static UINT8 LegacyLoaderMediaPathData [ ] = {
0x04 , 0x06 , 0x14 , 0x00 , 0xEB , 0x85 , 0x05 , 0x2B ,
0xB8 , 0xD8 , 0xA9 , 0x49 , 0x8B , 0x8C , 0xE2 , 0x1B ,
0x01 , 0xAE , 0xF2 , 0xB7 , 0x7F , 0xFF , 0x04 , 0x00 ,
} ;
static EFI_DEVICE_PATH * LegacyLoaderMediaPath = ( EFI_DEVICE_PATH * ) LegacyLoaderMediaPathData ;
EFI_STATUS ExtractLegacyLoaderPaths ( EFI_DEVICE_PATH * * PathList , UINTN MaxPaths , EFI_DEVICE_PATH * * HardcodedPathList )
{
EFI_STATUS Status ;
UINTN HandleCount = 0 ;
UINTN HandleIndex , HardcodedIndex ;
EFI_HANDLE * Handles = NULL ;
EFI_HANDLE Handle ;
UINTN PathCount = 0 ;
UINTN PathIndex ;
EFI_LOADED_IMAGE * LoadedImage ;
EFI_DEVICE_PATH * DevicePath ;
BOOLEAN Seen ;
MaxPaths - - ; // leave space for the terminating NULL pointer
// get all LoadedImage handles
Status = gBS - > LocateHandleBuffer ( ByProtocol , & gEfiLoadedImageProtocolGuid , NULL ,
& HandleCount , & Handles ) ;
if ( CheckError ( Status , L " while listing LoadedImage handles " ) ) {
if ( HardcodedPathList ) {
for ( HardcodedIndex = 0 ; HardcodedPathList [ HardcodedIndex ] & & PathCount < MaxPaths ; HardcodedIndex + + )
PathList [ PathCount + + ] = HardcodedPathList [ HardcodedIndex ] ;
}
PathList [ PathCount ] = NULL ;
return Status ;
}
for ( HandleIndex = 0 ; HandleIndex < HandleCount & & PathCount < MaxPaths ; HandleIndex + + ) {
Handle = Handles [ HandleIndex ] ;
Status = gBS - > HandleProtocol ( Handle , & gEfiLoadedImageProtocolGuid , ( VOID * * ) & LoadedImage ) ;
if ( EFI_ERROR ( Status ) )
continue ; // This can only happen if the firmware scewed up, ignore it.
Status = gBS - > HandleProtocol ( LoadedImage - > DeviceHandle , & gEfiDevicePathProtocolGuid , ( VOID * * ) & DevicePath ) ;
if ( EFI_ERROR ( Status ) )
continue ; // This happens, ignore it.
// Only grab memory range nodes
if ( DevicePathType ( DevicePath ) ! = HARDWARE_DEVICE_PATH | | DevicePathSubType ( DevicePath ) ! = HW_MEMMAP_DP )
continue ;
// Check if we have this device path in the list already
// WARNING: This assumes the first node in the device path is unique!
Seen = FALSE ;
for ( PathIndex = 0 ; PathIndex < PathCount ; PathIndex + + ) {
if ( DevicePathNodeLength ( DevicePath ) ! = DevicePathNodeLength ( PathList [ PathIndex ] ) )
continue ;
if ( CompareMem ( DevicePath , PathList [ PathIndex ] , DevicePathNodeLength ( DevicePath ) ) = = 0 ) {
Seen = TRUE ;
break ;
}
}
if ( Seen )
continue ;
PathList [ PathCount + + ] = AppendDevicePath ( DevicePath , LegacyLoaderMediaPath ) ;
}
FreePool ( Handles ) ;
if ( HardcodedPathList ) {
for ( HardcodedIndex = 0 ; HardcodedPathList [ HardcodedIndex ] & & PathCount < MaxPaths ; HardcodedIndex + + )
PathList [ PathCount + + ] = HardcodedPathList [ HardcodedIndex ] ;
}
PathList [ PathCount ] = NULL ;
return ( PathCount > 0 ) ? EFI_SUCCESS : EFI_NOT_FOUND ;
}
//
// volume functions
//
static VOID ScanVolumeBootcode ( IN OUT REFIT_VOLUME * Volume , OUT BOOLEAN * Bootable )
{
EFI_STATUS Status ;
UINT8 * SectorBuffer ;
UINTN i ;
//MBR_PARTITION_INFO *MbrTable;
//BOOLEAN MbrTableFound;
UINTN BlockSize = 0 ;
CHAR16 volumeName [ 255 ] ;
CHAR8 tmp [ 64 ] ;
UINT32 VCrc32 ;
// CHAR16 *kind = NULL;
Volume - > HasBootCode = FALSE ;
Volume - > LegacyOS - > IconName = NULL ;
Volume - > LegacyOS - > Name = NULL ;
// Volume->BootType = BOOTING_BY_MBR; //default value
Volume - > BootType = BOOTING_BY_EFI ;
* Bootable = FALSE ;
if ( ( Volume - > BlockIO = = NULL ) | | ( ! Volume - > BlockIO - > Media - > MediaPresent ) )
return ;
ZeroMem ( ( CHAR8 * ) & tmp [ 0 ] , 64 ) ;
BlockSize = Volume - > BlockIO - > Media - > BlockSize ;
if ( BlockSize > 2048 )
return ; // our buffer is too small... the bred of thieve of cable
2019-12-21 01:31:49 +01:00
SectorBuffer = ( __typeof__ ( SectorBuffer ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( 2048 ) , 16 ) ; //align to 16 byte?! Poher
2019-09-03 11:58:42 +02:00
ZeroMem ( ( CHAR8 * ) & SectorBuffer [ 0 ] , 2048 ) ;
// look at the boot sector (this is used for both hard disks and El Torito images!)
Status = Volume - > BlockIO - > ReadBlocks ( Volume - > BlockIO , Volume - > BlockIO - > Media - > MediaId ,
Volume - > BlockIOOffset /*start lba*/ ,
2048 , SectorBuffer ) ;
if ( ! EFI_ERROR ( Status ) & & ( SectorBuffer [ 1 ] ! = 0 ) ) {
// calc crc checksum of first 2 sectors - it's used later for legacy boot BIOS drive num detection
// note: possible future issues with AF 4K disks
* Bootable = TRUE ;
Volume - > HasBootCode = TRUE ; //we assume that all CD are bootable
/* DBG("check SectorBuffer\n");
for ( i = 0 ; i < 32 ; i + + ) {
DBG ( " %2x " , SectorBuffer [ i ] ) ;
}
DBG ( " \n " ) ; */
VCrc32 = GetCrc32 ( SectorBuffer , 512 * 2 ) ;
Volume - > DriveCRC32 = VCrc32 ;
//gBS->CalculateCrc32 (SectorBuffer, 2 * 512, &Volume->DriveCRC32);
/* switch (Volume->DiskKind ) {
case DISK_KIND_OPTICAL :
kind = L " DVD " ;
break ;
case DISK_KIND_INTERNAL :
kind = L " HDD " ;
break ;
case DISK_KIND_EXTERNAL :
kind = L " USB " ;
break ;
default :
break ;
}
DBG ( " Volume kind=%s CRC=0x%x \n " , kind , VCrc32 ) ; */
if ( Volume - > DiskKind = = DISK_KIND_OPTICAL ) { //CDROM
CHAR8 * p = ( CHAR8 * ) & SectorBuffer [ 8 ] ;
while ( * p = = 0x20 ) {
p + + ;
}
for ( i = 0 ; i < 30 & & ( * p > = 0x20 ) & & ( * p < = ' z ' ) ; i + + , p + + ) {
tmp [ i ] = * p ;
}
tmp [ i ] = 0 ;
while ( ( i > 0 ) & & ( tmp [ - - i ] = = 0x20 ) ) { }
tmp [ i + 1 ] = 0 ;
// if (*p != 0) {
AsciiStrToUnicodeStrS ( ( CHAR8 * ) & tmp [ 0 ] , volumeName , 255 ) ;
// }
DBG ( " Detected name %s \n " , volumeName ) ;
Volume - > VolName = PoolPrint ( L " %s " , volumeName ) ;
for ( i = 8 ; i < 2000 ; i + + ) { //vendor search
if ( SectorBuffer [ i ] = = ' A ' ) {
if ( AsciiStrStr ( ( CHAR8 * ) & SectorBuffer [ i ] , " APPLE " ) ) {
// StrCpy(Volume->VolName, volumeName);
DBG ( " Found AppleDVD \n " ) ;
Volume - > LegacyOS - > Type = OSTYPE_OSX ;
Volume - > BootType = BOOTING_BY_CD ;
Volume - > LegacyOS - > IconName = L " mac " ;
break ;
}
} else if ( SectorBuffer [ i ] = = ' M ' ) {
if ( AsciiStrStr ( ( CHAR8 * ) & SectorBuffer [ i ] , " MICROSOFT " ) ) {
// StrCpy(Volume->VolName, volumeName);
DBG ( " Found Windows DVD \n " ) ;
Volume - > LegacyOS - > Type = OSTYPE_WIN ;
Volume - > BootType = BOOTING_BY_CD ;
Volume - > LegacyOS - > IconName = L " win " ;
break ;
}
} else if ( SectorBuffer [ i ] = = ' L ' ) {
if ( AsciiStrStr ( ( CHAR8 * ) & SectorBuffer [ i ] , " LINUX " ) ) {
// Volume->DevicePath = DuplicateDevicePath(DevicePath);
// StrCpy(Volume->VolName, volumeName);
DBG ( " Found Linux DVD \n " ) ;
Volume - > LegacyOS - > Type = OSTYPE_LIN ;
Volume - > BootType = BOOTING_BY_CD ;
Volume - > LegacyOS - > IconName = L " linux " ;
break ;
}
}
}
}
//else HDD
else { //HDD
/*
// apianti - does this detect every partition as legacy?
if ( * ( ( UINT16 * ) ( SectorBuffer + 510 ) ) = = 0xaa55 & & SectorBuffer [ 0 ] ! = 0 ) {
* Bootable = TRUE ;
Volume - > HasBootCode = TRUE ;
// DBG("The volume has bootcode\n");
Volume - > LegacyOS - > IconName = L " legacy " ;
Volume - > LegacyOS - > Name = L " Legacy " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
}
// */
// detect specific boot codes
if ( CompareMem ( SectorBuffer + 2 , " LILO " , 4 ) = = 0 | |
CompareMem ( SectorBuffer + 6 , " LILO " , 4 ) = = 0 | |
CompareMem ( SectorBuffer + 3 , " SYSLINUX " , 8 ) = = 0 | |
FindMem ( SectorBuffer , 2048 , " ISOLINUX " , 8 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " linux " ;
Volume - > LegacyOS - > Name = L " Linux " ;
Volume - > LegacyOS - > Type = OSTYPE_LIN ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " Geom \0 Hard Disk \0 Read \0 Error " , 26 ) > = 0 ) { // GRUB
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " grub,linux " ;
Volume - > LegacyOS - > Name = L " Linux " ;
Volume - > BootType = BOOTING_BY_PBR ;
/*
} else if ( ( * ( ( UINT32 * ) ( SectorBuffer ) ) = = 0x4d0062e9 & &
* ( ( UINT16 * ) ( SectorBuffer + 510 ) ) = = 0xaa55 ) | |
FindMem ( SectorBuffer , 2048 , " BOOT " , 10 ) > = 0 ) { //reboot Clover
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " clover " ;
Volume - > LegacyOS - > Name = L " Clover " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
// DBG("Detected Clover FAT32 bootcode\n");
*/
} else if ( ( * ( ( UINT32 * ) ( SectorBuffer + 502 ) ) = = 0 & &
* ( ( UINT32 * ) ( SectorBuffer + 506 ) ) = = 50000 & &
* ( ( UINT16 * ) ( SectorBuffer + 510 ) ) = = 0xaa55 ) | |
FindMem ( SectorBuffer , 2048 , " Starting the BTX loader " , 23 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " freebsd " ;
Volume - > LegacyOS - > Name = L " FreeBSD " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " !Loading " , 8 ) > = 0 | |
FindMem ( SectorBuffer , 2048 , " /cdboot \0 /CDBOOT \0 " , 16 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " openbsd " ;
Volume - > LegacyOS - > Name = L " OpenBSD " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " Not a bootxx image " , 18 ) > = 0 | |
* ( ( UINT32 * ) ( SectorBuffer + 1028 ) ) = = 0x7886b6d1 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " netbsd " ;
Volume - > LegacyOS - > Name = L " NetBSD " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 2048 , " NTLDR " , 5 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " win " ;
Volume - > LegacyOS - > Name = L " Windows " ;
Volume - > LegacyOS - > Type = OSTYPE_WIN ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 2048 , " BOOTMGR " , 7 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " vista,win " ;
Volume - > LegacyOS - > Name = L " Windows " ;
Volume - > LegacyOS - > Type = OSTYPE_WIN ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " CPUBOOT SYS " , 11 ) > = 0 | |
FindMem ( SectorBuffer , 512 , " KERNEL SYS " , 11 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " freedos " ;
Volume - > LegacyOS - > Name = L " FreeDOS " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
/*
} else if ( FindMem ( SectorBuffer , 512 , " OS2LDR " , 6 ) > = 0 | |
FindMem ( SectorBuffer , 512 , " OS2BOOT " , 7 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " ecomstation " ;
Volume - > LegacyOS - > Name = L " eComStation " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " Be Boot Loader " , 14 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " beos " ;
Volume - > LegacyOS - > Name = L " BeOS " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " yT Boot Loader " , 14 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " zeta " ;
Volume - > LegacyOS - > Name = L " ZETA " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " \x04 " " beos \x06 " " system \x05 " " zbeos " , 18 ) > = 0 | |
FindMem ( SectorBuffer , 512 , " haiku_loader " , 12 ) > = 0 ) {
Volume - > HasBootCode = TRUE ;
Volume - > LegacyOS - > IconName = L " haiku " ;
Volume - > LegacyOS - > Name = L " Haiku " ;
Volume - > LegacyOS - > Type = OSTYPE_VAR ;
Volume - > BootType = BOOTING_BY_PBR ;
*/
}
}
// NOTE: If you add an operating system with a name that starts with 'W' or 'L', you
// need to fix AddLegacyEntry in main.c.
# if REFIT_DEBUG > 0
DBG ( " Result of bootcode detection: %s %s (%s) \n " ,
Volume - > HasBootCode ? L " bootable " : L " non-bootable " ,
Volume - > LegacyOS - > Name ? Volume - > LegacyOS - > Name : L " unknown " ,
Volume - > LegacyOS - > IconName ? Volume - > LegacyOS - > IconName : L " legacy " ) ;
# endif
2020-02-21 04:54:01 +01:00
2019-09-03 11:58:42 +02:00
if ( FindMem ( SectorBuffer , 512 , " Non-system disk " , 15 ) > = 0 ) // dummy FAT boot sector
Volume - > HasBootCode = FALSE ;
2020-02-21 04:54:01 +01:00
2019-09-03 11:58:42 +02:00
// check for MBR partition table
/*
// apianti - this is littered with bugs and probably not needed lol
if ( * ( ( UINT16 * ) ( SectorBuffer + 510 ) ) = = 0xaa55 ) {
MbrTableFound = FALSE ;
MbrTable = ( MBR_PARTITION_INFO * ) ( SectorBuffer + 446 ) ;
for ( i = 0 ; i < 4 ; i + + )
if ( MbrTable [ i ] . StartLBA & & MbrTable [ i ] . Size )
MbrTableFound = TRUE ;
for ( i = 0 ; i < 4 ; i + + )
if ( MbrTable [ i ] . Flags ! = 0x00 & & MbrTable [ i ] . Flags ! = 0x80 )
MbrTableFound = FALSE ;
if ( MbrTableFound ) {
2019-12-21 01:31:49 +01:00
Volume - > MbrPartitionTable = ( __typeof__ ( Volume - > MbrPartitionTable ) ) AllocatePool ( 4 * 16 ) ;
2019-09-03 11:58:42 +02:00
CopyMem ( Volume - > MbrPartitionTable , MbrTable , 4 * 16 ) ;
Volume - > BootType = BOOTING_BY_MBR ;
}
}
// */
}
2020-02-21 04:54:01 +01:00
// gBS->FreePages((EFI_PHYSICAL_ADDRESS)(UINTN)SectorBuffer, 1);
// FreeAlignedPages((EFI_PHYSICAL_ADDRESS)(UINTN)SectorBuffer, 1);
FreeAlignedPages ( ( VOID * ) SectorBuffer , EFI_SIZE_TO_PAGES ( 2048 ) ) ;
2019-09-03 11:58:42 +02:00
}
//at start we have only Volume->DeviceHandle
static EFI_STATUS ScanVolume ( IN OUT REFIT_VOLUME * Volume )
{
EFI_STATUS Status ;
EFI_DEVICE_PATH * DevicePath , * NextDevicePath ;
EFI_DEVICE_PATH * DiskDevicePath , * RemainingDevicePath = NULL ;
HARDDRIVE_DEVICE_PATH * HdPath = NULL ;
EFI_HANDLE WholeDiskHandle ;
UINTN PartialLength = 0 ;
UINTN DevicePathSize ;
// UINTN BufferSize = 255;
EFI_FILE_SYSTEM_VOLUME_LABEL * VolumeInfo ;
EFI_FILE_SYSTEM_INFO * FileSystemInfoPtr ;
EFI_FILE_INFO * RootInfo = NULL ;
BOOLEAN Bootable ;
// EFI_INPUT_KEY Key;
CHAR16 * tmpName ;
// get device path
DiskDevicePath = DevicePathFromHandle ( Volume - > DeviceHandle ) ;
DevicePathSize = GetDevicePathSize ( DiskDevicePath ) ;
2019-12-21 01:31:49 +01:00
Volume - > DevicePath = ( __typeof__ ( Volume - > DevicePath ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( DevicePathSize ) , 64 ) ;
2019-09-03 11:58:42 +02:00
CopyMem ( Volume - > DevicePath , DiskDevicePath , DevicePathSize ) ;
Volume - > DevicePathString = FileDevicePathToStr ( Volume - > DevicePath ) ;
// Volume->DevicePath = DuplicateDevicePath(DevicePathFromHandle(Volume->DeviceHandle));
# if REFIT_DEBUG > 0
if ( Volume - > DevicePath ! = NULL ) {
DBG ( " %s \n " , FileDevicePathToStr ( Volume - > DevicePath ) ) ;
//#if REFIT_DEBUG >= 2
// DumpHex(1, 0, GetDevicePathSize(Volume->DevicePath), Volume->DevicePath);
//#endif
}
# else
DBG ( " \n " ) ;
# endif
Volume - > DiskKind = DISK_KIND_INTERNAL ; // default
// get block i/o
Status = gBS - > HandleProtocol ( Volume - > DeviceHandle , & gEfiBlockIoProtocolGuid , ( VOID * * ) & ( Volume - > BlockIO ) ) ;
if ( EFI_ERROR ( Status ) ) {
Volume - > BlockIO = NULL ;
2020-02-21 04:54:01 +01:00
// DBG(" Warning: Can't get BlockIO protocol.\n");
2019-09-03 11:58:42 +02:00
// WaitForSingleEvent (gST->ConIn->WaitForKey, 0);
// gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
return Status ;
}
Bootable = FALSE ;
if ( Volume - > BlockIO - > Media - > BlockSize = = 2048 ) {
2020-02-21 04:54:01 +01:00
// DBG(" Found optical drive\n");
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = DISK_KIND_OPTICAL ;
Volume - > BlockIOOffset = 0x10 ; // offset already applied for FS but not for blockio
ScanVolumeBootcode ( Volume , & Bootable ) ;
} else {
// DBG(" Found HD drive\n");
Volume - > BlockIOOffset = 0 ;
// scan for bootcode and MBR table
ScanVolumeBootcode ( Volume , & Bootable ) ;
2020-02-21 04:54:01 +01:00
// DBG(" ScanVolumeBootcode success\n");
2019-09-03 11:58:42 +02:00
// detect device type
DevicePath = DuplicateDevicePath ( Volume - > DevicePath ) ;
while ( DevicePath ! = NULL & & ! IsDevicePathEndType ( DevicePath ) ) {
NextDevicePath = NextDevicePathNode ( DevicePath ) ;
if ( ( DevicePathType ( DevicePath ) = = MESSAGING_DEVICE_PATH ) & &
( ( DevicePathSubType ( DevicePath ) = = MSG_SATA_DP ) | |
( DevicePathSubType ( DevicePath ) = = MSG_NVME_NAMESPACE_DP ) | |
( DevicePathSubType ( DevicePath ) = = MSG_ATAPI_DP ) ) ) {
2020-02-21 04:54:01 +01:00
// DBG(" HDD volume\n");
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = DISK_KIND_INTERNAL ;
break ;
}
if ( DevicePathType ( DevicePath ) = = MESSAGING_DEVICE_PATH & &
( DevicePathSubType ( DevicePath ) = = MSG_USB_DP | | DevicePathSubType ( DevicePath ) = = MSG_USB_CLASS_DP ) ) {
2020-02-21 04:54:01 +01:00
// DBG(" USB volume\n");
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = DISK_KIND_EXTERNAL ;
// break;
}
// FIREWIRE Devices
if ( DevicePathType ( DevicePath ) = = MESSAGING_DEVICE_PATH & &
( DevicePathSubType ( DevicePath ) = = MSG_1394_DP | | DevicePathSubType ( DevicePath ) = = MSG_FIBRECHANNEL_DP ) ) {
// DBG(" FireWire volume\n");
Volume - > DiskKind = DISK_KIND_FIREWIRE ;
break ;
}
// CD-ROM Devices
if ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH & &
DevicePathSubType ( DevicePath ) = = MEDIA_CDROM_DP ) {
// DBG(" CD-ROM volume\n");
Volume - > DiskKind = DISK_KIND_OPTICAL ; //it's impossible
break ;
}
// VENDOR Specific Path
if ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH & &
DevicePathSubType ( DevicePath ) = = MEDIA_VENDOR_DP ) {
2020-02-21 04:54:01 +01:00
// DBG(" Vendor volume\n");
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = DISK_KIND_NODISK ;
break ;
}
// LEGACY CD-ROM
if ( DevicePathType ( DevicePath ) = = BBS_DEVICE_PATH & &
( DevicePathSubType ( DevicePath ) = = BBS_BBS_DP | | DevicePathSubType ( DevicePath ) = = BBS_TYPE_CDROM ) ) {
// DBG(" Legacy CD-ROM volume\n");
Volume - > DiskKind = DISK_KIND_OPTICAL ;
break ;
}
// LEGACY HARDDISK
if ( DevicePathType ( DevicePath ) = = BBS_DEVICE_PATH & &
( DevicePathSubType ( DevicePath ) = = BBS_BBS_DP | | DevicePathSubType ( DevicePath ) = = BBS_TYPE_HARDDRIVE ) ) {
2020-02-21 04:54:01 +01:00
// DBG(" Legacy HDD volume\n");
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = DISK_KIND_INTERNAL ;
break ;
}
//one more we must take into account
// subtype = MSG_NVME_NAMESPACE_DP
// diskKind = NVME
//#define MSG_NVME_NAMESPACE_DP 0x17
DevicePath = NextDevicePath ;
}
/* what is the bread?
// Bootable = TRUE;
if ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH & &
DevicePathSubType ( DevicePath ) = = MEDIA_VENDOR_DP ) {
Volume - > IsAppleLegacy = TRUE ; // legacy BIOS device entry
// TODO: also check for Boot Camp GUID
//gEfiPartTypeSystemPartGuid
Bootable = FALSE ; // this handle's BlockIO is just an alias for the whole device
Print ( L " AppleLegacy device \n " ) ;
}
*/
}
DevicePath = DuplicateDevicePath ( Volume - > DevicePath ) ;
RemainingDevicePath = DevicePath ; //initial value
//
// find the partition device path node
//
while ( DevicePath & & ! IsDevicePathEnd ( DevicePath ) ) {
if ( ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH ) & &
( DevicePathSubType ( DevicePath ) = = MEDIA_HARDDRIVE_DP ) ) {
HdPath = ( HARDDRIVE_DEVICE_PATH * ) DevicePath ;
// break;
}
DevicePath = NextDevicePathNode ( DevicePath ) ;
}
2020-02-21 04:54:01 +01:00
// DBG("DevicePath scanned\n");
2019-09-03 11:58:42 +02:00
if ( HdPath ) {
// Print(L"Partition found %s\n", DevicePathToStr((EFI_DEVICE_PATH *)HdPath));
PartialLength = ( UINTN ) ( ( UINT8 * ) HdPath - ( UINT8 * ) ( RemainingDevicePath ) ) ;
if ( PartialLength > 0x1000 ) {
PartialLength = sizeof ( EFI_DEVICE_PATH ) ; //something wrong here but I don't want to be freezed
// return EFI_SUCCESS;
}
DiskDevicePath = ( EFI_DEVICE_PATH * ) AllocatePool ( PartialLength + sizeof ( EFI_DEVICE_PATH ) ) ;
CopyMem ( DiskDevicePath , Volume - > DevicePath , PartialLength ) ;
CopyMem ( ( UINT8 * ) DiskDevicePath + PartialLength , DevicePath , sizeof ( EFI_DEVICE_PATH ) ) ; //EndDevicePath
// Print(L"WholeDevicePath %s\n", DevicePathToStr(DiskDevicePath));
2020-02-21 04:54:01 +01:00
// DBG("WholeDevicePath %s\n", DevicePathToStr(DiskDevicePath));
2019-09-03 11:58:42 +02:00
RemainingDevicePath = DiskDevicePath ;
Status = gBS - > LocateDevicePath ( & gEfiDevicePathProtocolGuid , & RemainingDevicePath , & WholeDiskHandle ) ;
if ( EFI_ERROR ( Status ) ) {
DBG ( " Can't find WholeDevicePath: %r \n " , Status ) ;
} else {
Volume - > WholeDiskDeviceHandle = WholeDiskHandle ;
Volume - > WholeDiskDevicePath = DuplicateDevicePath ( RemainingDevicePath ) ;
// look at the BlockIO protocol
Status = gBS - > HandleProtocol ( WholeDiskHandle , & gEfiBlockIoProtocolGuid , ( VOID * * ) & Volume - > WholeDiskBlockIO ) ;
if ( ! EFI_ERROR ( Status ) ) {
// DBG("WholeDiskBlockIO %x BlockSize=%d\n", Volume->WholeDiskBlockIO, Volume->WholeDiskBlockIO->Media->BlockSize);
// check the media block size
if ( Volume - > WholeDiskBlockIO - > Media - > BlockSize = = 2048 )
Volume - > DiskKind = DISK_KIND_OPTICAL ;
} else {
Volume - > WholeDiskBlockIO = NULL ;
2020-02-21 04:54:01 +01:00
// DBG("no WholeDiskBlockIO: %r\n", Status);
2019-09-03 11:58:42 +02:00
//CheckError(Status, L"from HandleProtocol");
}
}
FreePool ( DiskDevicePath ) ;
}
/* else {
DBG ( " HD path is not found \n " ) ; //master volume!
} */
// if (GlobalConfig.FastBoot) {
// return EFI_SUCCESS;
// }
if ( ! Bootable ) {
# if REFIT_DEBUG > 0
if ( Volume - > HasBootCode ) {
DBG ( " Volume considered non-bootable, but boot code is present \n " ) ;
// WaitForSingleEvent (gST->ConIn->WaitForKey, 0);
// gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
}
# endif
Volume - > HasBootCode = FALSE ;
}
// open the root directory of the volume
Volume - > RootDir = EfiLibOpenRoot ( Volume - > DeviceHandle ) ;
// DBG("Volume->RootDir OK\n");
if ( Volume - > RootDir = = NULL ) {
//Print(L"Error: Can't open volume.\n");
// TODO: signal that we had an error
//Slice - there is LegacyBoot volume
//properties are set before
// DBG("LegacyBoot volume\n");
if ( HdPath ) {
tmpName = ( CHAR16 * ) AllocateZeroPool ( 60 ) ;
UnicodeSPrint ( tmpName , 60 , L " Legacy HD%d " , HdPath - > PartitionNumber ) ;
Volume - > VolName = EfiStrDuplicate ( tmpName ) ;
FreePool ( tmpName ) ;
} else if ( ! Volume - > VolName ) {
Volume - > VolName = EfiStrDuplicate ( L " Whole Disc Boot " ) ;
}
if ( ! Volume - > LegacyOS - > IconName )
Volume - > LegacyOS - > IconName = EfiStrDuplicate ( L " legacy " ) ;
return EFI_SUCCESS ;
}
2020-01-15 08:58:18 +01:00
if ( FileExists ( Volume - > RootDir , L " \\ .VolumeLabel.txt " ) ) {
EFI_FILE_HANDLE FileHandle ;
Status = Volume - > RootDir - > Open ( Volume - > RootDir , & FileHandle , L " \\ .VolumeLabel.txt " , EFI_FILE_MODE_READ , 0 ) ;
if ( ! EFI_ERROR ( Status ) ) {
CHAR8 Buffer [ 32 + 1 ] ;
UINTN BufferSize = sizeof ( Buffer ) - sizeof ( CHAR8 ) ;
SetMem ( Buffer , BufferSize + sizeof ( CHAR8 ) , 0 ) ;
Status = FileHandle - > Read ( FileHandle , & BufferSize , Buffer ) ;
FileHandle - > Close ( FileHandle ) ;
if ( ! EFI_ERROR ( Status ) ) {
Volume - > VolLabel = PoolPrint ( L " %a " , Buffer ) ;
}
}
}
2019-09-03 11:58:42 +02:00
// get volume name
if ( ! Volume - > VolName ) {
FileSystemInfoPtr = EfiLibFileSystemInfo ( Volume - > RootDir ) ;
if ( FileSystemInfoPtr ) {
//DBG(" Volume name from FileSystem: '%s'\n", FileSystemInfoPtr->VolumeLabel);
Volume - > VolName = EfiStrDuplicate ( FileSystemInfoPtr - > VolumeLabel ) ;
FreePool ( FileSystemInfoPtr ) ;
}
}
if ( ! Volume - > VolName ) {
VolumeInfo = EfiLibFileSystemVolumeLabelInfo ( Volume - > RootDir ) ;
if ( VolumeInfo ) {
//DBG(" Volume name from VolumeLabel: '%s'\n", VolumeInfo->VolumeLabel);
Volume - > VolName = EfiStrDuplicate ( VolumeInfo - > VolumeLabel ) ;
FreePool ( VolumeInfo ) ;
}
}
if ( ! Volume - > VolName ) {
RootInfo = EfiLibFileInfo ( Volume - > RootDir ) ;
if ( RootInfo ) {
//DBG(" Volume name from RootFile: '%s'\n", RootInfo->FileName);
Volume - > VolName = EfiStrDuplicate ( RootInfo - > FileName ) ;
FreePool ( RootInfo ) ;
}
}
if (
Volume - > VolName = = NULL
| | Volume - > VolName [ 0 ] = = 0
| | ( Volume - > VolName [ 0 ] = = L ' \\ ' & & Volume - > VolName [ 1 ] = = 0 )
| | ( Volume - > VolName [ 0 ] = = L ' / ' & & Volume - > VolName [ 1 ] = = 0 )
)
{
VOID * Instance ;
if ( ! EFI_ERROR ( gBS - > HandleProtocol ( Volume - > DeviceHandle , & gEfiPartTypeSystemPartGuid , & Instance ) ) ) {
2020-02-21 10:44:15 +01:00
Volume - > VolName = L " EFI " ; \
2019-09-03 11:58:42 +02:00
}
}
if ( ! Volume - > VolName ) {
// DBG("Create unknown name\n");
// WaitForSingleEvent (gST->ConIn->WaitForKey, 0);
// gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if ( HdPath ) {
tmpName = ( CHAR16 * ) AllocateZeroPool ( 128 ) ;
UnicodeSPrint ( tmpName , 128 , L " Unknown HD%d " , HdPath - > PartitionNumber ) ;
Volume - > VolName = EfiStrDuplicate ( tmpName ) ;
FreePool ( tmpName ) ;
// NOTE: this is normal for Apple's VenMedia device paths
} else {
Volume - > VolName = EfiStrDuplicate ( L " Unknown HD " ) ; //To be able to free it
}
}
//Status = GetOSVersion(Volume); NOTE: Sothor - We will find icon names later once we have found boot.efi on the volume //here we set Volume->IconName (tiger,leo,snow,lion,cougar, etc)
return EFI_SUCCESS ;
}
static VOID ScanExtendedPartition ( REFIT_VOLUME * WholeDiskVolume , MBR_PARTITION_INFO * MbrEntry )
{
EFI_STATUS Status ;
REFIT_VOLUME * Volume ;
UINT32 ExtBase , ExtCurrent , NextExtCurrent ;
UINTN i ;
UINTN LogicalPartitionIndex = 4 ;
UINT8 * SectorBuffer ;
BOOLEAN Bootable ;
MBR_PARTITION_INFO * EMbrTable ;
ExtBase = MbrEntry - > StartLBA ;
2019-12-21 01:31:49 +01:00
SectorBuffer = ( __typeof__ ( SectorBuffer ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( 512 ) , WholeDiskVolume - > BlockIO - > Media - > IoAlign ) ;
2019-09-03 11:58:42 +02:00
for ( ExtCurrent = ExtBase ; ExtCurrent ; ExtCurrent = NextExtCurrent ) {
// read current EMBR
Status = WholeDiskVolume - > BlockIO - > ReadBlocks ( WholeDiskVolume - > BlockIO ,
WholeDiskVolume - > BlockIO - > Media - > MediaId ,
ExtCurrent , 512 , SectorBuffer ) ;
if ( EFI_ERROR ( Status ) )
break ;
if ( * ( ( UINT16 * ) ( SectorBuffer + 510 ) ) ! = 0xaa55 )
break ;
EMbrTable = ( MBR_PARTITION_INFO * ) ( SectorBuffer + 446 ) ;
// scan logical partitions in this EMBR
NextExtCurrent = 0 ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( ( EMbrTable [ i ] . Flags ! = 0x00 & & EMbrTable [ i ] . Flags ! = 0x80 ) | |
EMbrTable [ i ] . StartLBA = = 0 | | EMbrTable [ i ] . Size = = 0 )
break ;
if ( IS_EXTENDED_PART_TYPE ( EMbrTable [ i ] . Type ) ) {
// set next ExtCurrent
NextExtCurrent = ExtBase + EMbrTable [ i ] . StartLBA ;
break ;
} else {
// found a logical partition
2020-02-27 15:34:29 +01:00
Volume = ( __typeof__ ( Volume ) ) AllocateZeroPool ( sizeof ( * Volume ) ) ;
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = WholeDiskVolume - > DiskKind ;
Volume - > IsMbrPartition = TRUE ;
Volume - > MbrPartitionIndex = LogicalPartitionIndex + + ;
Volume - > VolName = PoolPrint ( L " Partition %d " , Volume - > MbrPartitionIndex + 1 ) ;
Volume - > BlockIO = WholeDiskVolume - > BlockIO ;
Volume - > BlockIOOffset = ExtCurrent + EMbrTable [ i ] . StartLBA ;
Volume - > WholeDiskBlockIO = WholeDiskVolume - > BlockIO ;
Volume - > WholeDiskDeviceHandle = WholeDiskVolume - > DeviceHandle ;
Bootable = FALSE ;
ScanVolumeBootcode ( Volume , & Bootable ) ;
if ( ! Bootable )
Volume - > HasBootCode = FALSE ;
2020-02-27 15:34:29 +01:00
Volumes . AddReference ( Volume , true ) ;
// AddListElement((VOID ***) &Volumes, &VolumesCount, Volume);
2019-09-03 11:58:42 +02:00
}
}
}
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) SectorBuffer , 1 ) ;
}
VOID ScanVolumes ( VOID )
{
EFI_STATUS Status ;
UINTN HandleCount = 0 ;
UINTN HandleIndex ;
EFI_HANDLE * Handles = NULL ;
2020-02-27 15:34:29 +01:00
REFIT_VOLUME * WholeDiskVolume ;
2019-09-03 11:58:42 +02:00
UINTN VolumeIndex , VolumeIndex2 ;
MBR_PARTITION_INFO * MbrTable ;
UINTN PartitionIndex ;
UINT8 * SectorBuffer1 , * SectorBuffer2 ;
UINTN SectorSum , i ;
// EFI_DEVICE_PATH_PROTOCOL *VolumeDevicePath;
// EFI_GUID *Guid; //for debug only
// EFI_INPUT_KEY Key;
INT32 HVi ;
// DBG("Scanning volumes...\n");
DbgHeader ( " ScanVolumes " ) ;
// get all BlockIo handles
Status = gBS - > LocateHandleBuffer ( ByProtocol , & gEfiBlockIoProtocolGuid , NULL , & HandleCount , & Handles ) ;
if ( Status = = EFI_NOT_FOUND )
return ;
DBG ( " Found %d volumes with blockIO \n " , HandleCount ) ;
// first pass: collect information about all handles
for ( HandleIndex = 0 ; HandleIndex < HandleCount ; HandleIndex + + ) {
2020-02-27 15:34:29 +01:00
REFIT_VOLUME * Volume = ( __typeof__ ( Volume ) ) AllocateZeroPool ( sizeof ( * Volume ) ) ;
2019-12-21 01:31:49 +01:00
Volume - > LegacyOS = ( __typeof__ ( Volume - > LegacyOS ) ) AllocateZeroPool ( sizeof ( LEGACY_OS ) ) ;
2019-09-03 11:58:42 +02:00
Volume - > DeviceHandle = Handles [ HandleIndex ] ;
if ( Volume - > DeviceHandle = = SelfDeviceHandle ) {
SelfVolume = Volume ;
}
DBG ( " - [%02d]: Volume: " , HandleIndex ) ;
Volume - > Hidden = FALSE ; // default to not hidden
Status = ScanVolume ( Volume ) ;
if ( ! EFI_ERROR ( Status ) ) {
2020-02-27 15:34:29 +01:00
Volumes . AddReference ( Volume , true ) ;
// AddListElement((VOID ***) &Volumes, &VolumesCount, Volume);
2019-09-03 11:58:42 +02:00
if ( ! gSettings . ShowHiddenEntries ) {
for ( HVi = 0 ; HVi < gSettings . HVCount ; HVi + + ) {
if ( StriStr ( Volume - > DevicePathString , gSettings . HVHideStrings [ HVi ] ) | |
( Volume - > VolName ! = NULL & & StriStr ( Volume - > VolName , gSettings . HVHideStrings [ HVi ] ) ) ) {
Volume - > Hidden = TRUE ;
DBG ( " hiding this volume \n " ) ;
break ;
}
}
}
// Guid = FindGPTPartitionGuidInDevicePath(Volume->DevicePath);
if ( ! Volume - > LegacyOS - > IconName ) {
Volume - > LegacyOS - > IconName = L " legacy " ;
}
// DBG(" Volume '%s', LegacyOS '%s', LegacyIcon(s) '%s', GUID = %g\n",
// Volume->VolName, Volume->LegacyOS->Name ? Volume->LegacyOS->Name : L"", Volume->LegacyOS->IconName, Guid);
if ( SelfVolume = = Volume ) {
DBG ( " This is SelfVolume !! \n " ) ;
}
} else {
DBG ( " wrong volume Nr%d?! \n " , HandleIndex ) ;
FreePool ( Volume ) ;
}
}
FreePool ( Handles ) ;
// DBG("Found %d volumes\n", VolumesCount);
if ( SelfVolume = = NULL ) {
DBG ( " WARNING: SelfVolume not found " ) ; //Slice - and what?
2019-12-21 01:31:49 +01:00
SelfVolume = ( __typeof__ ( SelfVolume ) ) AllocateZeroPool ( sizeof ( REFIT_VOLUME ) ) ;
2019-09-03 11:58:42 +02:00
SelfVolume - > DeviceHandle = SelfDeviceHandle ;
SelfVolume - > DevicePath = SelfDevicePath ;
SelfVolume - > RootDir = SelfRootDir ;
SelfVolume - > DiskKind = DISK_KIND_BOOTER ;
SelfVolume - > VolName = L " Clover " ;
SelfVolume - > LegacyOS - > Type = OSTYPE_EFI ;
SelfVolume - > HasBootCode = TRUE ;
SelfVolume - > BootType = BOOTING_BY_PBR ;
// AddListElement((VOID ***) &Volumes, &VolumesCount, SelfVolume);
// DBG("SelfVolume Nr %d created\n", VolumesCount);
}
// second pass: relate partitions and whole disk devices
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + ) {
REFIT_VOLUME * Volume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
// check MBR partition table for extended partitions
if ( Volume - > BlockIO ! = NULL & & Volume - > WholeDiskBlockIO ! = NULL & &
Volume - > BlockIO = = Volume - > WholeDiskBlockIO & & Volume - > BlockIOOffset = = 0 & &
Volume - > MbrPartitionTable ! = NULL ) {
DBG ( " Volume %d has MBR \n " , VolumeIndex ) ;
MbrTable = Volume - > MbrPartitionTable ;
for ( PartitionIndex = 0 ; PartitionIndex < 4 ; PartitionIndex + + ) {
if ( IS_EXTENDED_PART_TYPE ( MbrTable [ PartitionIndex ] . Type ) ) {
ScanExtendedPartition ( Volume , MbrTable + PartitionIndex ) ;
}
}
}
// search for corresponding whole disk volume entry
WholeDiskVolume = NULL ;
if ( Volume - > BlockIO ! = NULL & & Volume - > WholeDiskBlockIO ! = NULL & &
Volume - > BlockIO ! = Volume - > WholeDiskBlockIO ) {
2020-02-27 15:34:29 +01:00
for ( VolumeIndex2 = 0 ; VolumeIndex2 < Volumes . size ( ) ; VolumeIndex2 + + ) {
if ( Volumes [ VolumeIndex2 ] . BlockIO = = Volume - > WholeDiskBlockIO & &
Volumes [ VolumeIndex2 ] . BlockIOOffset = = 0 )
WholeDiskVolume = & Volumes [ VolumeIndex2 ] ;
2019-09-03 11:58:42 +02:00
}
}
if ( WholeDiskVolume ! = NULL & & WholeDiskVolume - > MbrPartitionTable ! = NULL ) {
// check if this volume is one of the partitions in the table
MbrTable = WholeDiskVolume - > MbrPartitionTable ;
2019-12-21 01:31:49 +01:00
SectorBuffer1 = ( __typeof__ ( SectorBuffer1 ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( 512 ) , 16 ) ;
SectorBuffer2 = ( __typeof__ ( SectorBuffer2 ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( 512 ) , 16 ) ;
2019-09-03 11:58:42 +02:00
for ( PartitionIndex = 0 ; PartitionIndex < 4 ; PartitionIndex + + ) {
// check size
if ( ( UINT64 ) ( MbrTable [ PartitionIndex ] . Size ) ! = Volume - > BlockIO - > Media - > LastBlock + 1 )
continue ;
// compare boot sector read through offset vs. directly
Status = Volume - > BlockIO - > ReadBlocks ( Volume - > BlockIO , Volume - > BlockIO - > Media - > MediaId ,
Volume - > BlockIOOffset , 512 , SectorBuffer1 ) ;
if ( EFI_ERROR ( Status ) )
break ;
Status = Volume - > WholeDiskBlockIO - > ReadBlocks ( Volume - > WholeDiskBlockIO , Volume - > WholeDiskBlockIO - > Media - > MediaId ,
MbrTable [ PartitionIndex ] . StartLBA , 512 , SectorBuffer2 ) ;
if ( EFI_ERROR ( Status ) )
break ;
if ( CompareMem ( SectorBuffer1 , SectorBuffer2 , 512 ) ! = 0 )
continue ;
SectorSum = 0 ;
for ( i = 0 ; i < 512 ; i + + )
SectorSum + = SectorBuffer1 [ i ] ;
if ( SectorSum < 1000 )
continue ;
// TODO: mark entry as non-bootable if it is an extended partition
// now we're reasonably sure the association is correct...
Volume - > IsMbrPartition = TRUE ;
Volume - > MbrPartitionTable = MbrTable ;
Volume - > MbrPartitionIndex = PartitionIndex ;
if ( Volume - > VolName = = NULL )
Volume - > VolName = PoolPrint ( L " Partition %d " , PartitionIndex + 1 ) ;
break ;
}
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) SectorBuffer1 , 1 ) ;
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) SectorBuffer2 , 1 ) ;
}
}
}
static VOID UninitVolumes ( VOID )
{
REFIT_VOLUME * Volume ;
UINTN VolumeIndex ;
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + ) {
Volume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
if ( Volume - > RootDir ! = NULL ) {
Volume - > RootDir - > Close ( Volume - > RootDir ) ;
Volume - > RootDir = NULL ;
}
Volume - > DeviceHandle = NULL ;
Volume - > BlockIO = NULL ;
Volume - > WholeDiskBlockIO = NULL ;
Volume - > WholeDiskDeviceHandle = NULL ;
FreePool ( Volume ) ;
}
2020-02-27 15:34:29 +01:00
Volumes . Empty ( ) ;
2019-09-03 11:58:42 +02:00
}
VOID ReinitVolumes ( VOID )
{
EFI_STATUS Status ;
REFIT_VOLUME * Volume ;
UINTN VolumeIndex ;
UINTN VolumesFound = 0 ;
EFI_DEVICE_PATH * RemainingDevicePath ;
EFI_HANDLE DeviceHandle , WholeDiskHandle ;
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + ) {
Volume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
if ( ! Volume ) {
continue ;
}
DBG ( " Volume %d at reinit found: \n " , VolumeIndex ) ;
DBG ( " Volume->DevicePath=%s \n " , FileDevicePathToStr ( Volume - > DevicePath ) ) ;
VolumesFound + + ;
if ( Volume - > DevicePath ! = NULL ) {
// get the handle for that path
RemainingDevicePath = Volume - > DevicePath ;
Status = gBS - > LocateDevicePath ( & gEfiBlockIoProtocolGuid , & RemainingDevicePath , & DeviceHandle ) ;
if ( ! EFI_ERROR ( Status ) ) {
Volume - > DeviceHandle = DeviceHandle ;
// get the root directory
Volume - > RootDir = EfiLibOpenRoot ( Volume - > DeviceHandle ) ;
}
//else
// CheckError(Status, L"from LocateDevicePath");
}
if ( Volume - > WholeDiskDevicePath ! = NULL ) {
// get the handle for that path
RemainingDevicePath = DuplicateDevicePath ( Volume - > WholeDiskDevicePath ) ;
Status = gBS - > LocateDevicePath ( & gEfiBlockIoProtocolGuid , & RemainingDevicePath , & WholeDiskHandle ) ;
if ( ! EFI_ERROR ( Status ) ) {
2019-12-27 18:01:40 +01:00
Volume - > WholeDiskBlockIO = ( __typeof__ ( Volume - > WholeDiskBlockIO ) ) WholeDiskHandle ;
2019-09-03 11:58:42 +02:00
// get the BlockIO protocol
Status = gBS - > HandleProtocol ( WholeDiskHandle , & gEfiBlockIoProtocolGuid , ( VOID * * ) & Volume - > WholeDiskBlockIO ) ;
if ( EFI_ERROR ( Status ) ) {
Volume - > WholeDiskBlockIO = NULL ;
CheckError ( Status , L " from HandleProtocol " ) ;
}
}
//else
// CheckError(Status, L"from LocateDevicePath");
}
}
2020-02-27 15:34:29 +01:00
// Jief : I'm not sure to understand the next line. Why would we change the count when we didn't change the array.
// This code is not currently not used.
// Beware if you want to reuse this.
// VolumesCount = VolumesFound;
2019-09-03 11:58:42 +02:00
}
REFIT_VOLUME * FindVolumeByName ( IN CHAR16 * VolName )
{
REFIT_VOLUME * Volume ;
UINTN VolumeIndex ;
if ( ! VolName ) {
return NULL ;
}
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + ) {
Volume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
if ( ! Volume ) {
continue ;
}
if ( Volume - > VolName & & StrCmp ( Volume - > VolName , VolName ) = = 0 ) {
return Volume ;
}
}
return NULL ;
}
//
// file and dir functions
//
2020-02-17 21:41:09 +01:00
BOOLEAN FileExists ( IN CONST EFI_FILE * Root , IN CONST CHAR16 * RelativePath )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
EFI_FILE * TestFile = NULL ;
2020-02-21 06:29:22 +01:00
Status = Root - > Open ( Root , & TestFile , RelativePath , EFI_FILE_MODE_READ , 0 ) ;
2019-09-03 11:58:42 +02:00
if ( Status = = EFI_SUCCESS ) {
if ( TestFile & & TestFile - > Close ) {
TestFile - > Close ( TestFile ) ;
}
return TRUE ;
}
return FALSE ;
}
2020-02-17 21:41:09 +01:00
BOOLEAN DeleteFile ( IN EFI_FILE * Root , IN CONST CHAR16 * RelativePath )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
EFI_FILE * File ;
EFI_FILE_INFO * FileInfo ;
//DBG("DeleteFile: %s\n", RelativePath);
// open file for read/write to see if it exists, need write for delete
2020-02-21 06:29:22 +01:00
Status = Root - > Open ( Root , & File , RelativePath , EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE , 0 ) ;
2019-09-03 11:58:42 +02:00
//DBG(" Open: %r\n", Status);
if ( Status = = EFI_SUCCESS ) {
// exists - check if it is a file
FileInfo = EfiLibFileInfo ( File ) ;
if ( FileInfo = = NULL ) {
// error
//DBG(" FileInfo is NULL\n");
File - > Close ( File ) ;
return FALSE ;
}
//DBG(" FileInfo attr: %x\n", FileInfo->Attribute);
if ( ( FileInfo - > Attribute & EFI_FILE_DIRECTORY ) = = EFI_FILE_DIRECTORY ) {
// it's directory - return error
//DBG(" File is DIR\n");
FreePool ( FileInfo ) ;
File - > Close ( File ) ;
return FALSE ;
}
FreePool ( FileInfo ) ;
// it's a file - delete it
//DBG(" File is file\n");
Status = File - > Delete ( File ) ;
//DBG(" Delete: %r\n", Status);
return Status = = EFI_SUCCESS ;
}
return FALSE ;
}
EFI_STATUS DirNextEntry ( IN EFI_FILE * Directory , IN OUT EFI_FILE_INFO * * DirEntry , IN UINTN FilterMode )
{
EFI_STATUS Status ;
VOID * Buffer ;
UINTN LastBufferSize , BufferSize ;
INTN IterCount ;
for ( ; ; ) {
// free pointer from last call
if ( * DirEntry ! = NULL ) {
FreePool ( * DirEntry ) ;
* DirEntry = NULL ;
}
// read next directory entry
LastBufferSize = BufferSize = 256 ;
2019-12-21 01:31:49 +01:00
Buffer = ( __typeof__ ( Buffer ) ) AllocateZeroPool ( BufferSize ) ;
2019-09-03 11:58:42 +02:00
for ( IterCount = 0 ; ; IterCount + + ) {
Status = Directory - > Read ( Directory , & BufferSize , Buffer ) ;
if ( Status ! = EFI_BUFFER_TOO_SMALL | | IterCount > = 4 )
break ;
if ( BufferSize < = LastBufferSize ) {
DBG ( " FS Driver requests bad buffer size %d (was %d), using %d instead \n " , BufferSize , LastBufferSize , LastBufferSize * 2 ) ;
BufferSize = LastBufferSize * 2 ;
# if REFIT_DEBUG > 0
} else {
DBG ( " Reallocating buffer from %d to %d \n " , LastBufferSize , BufferSize ) ;
# endif
}
2019-12-21 01:31:49 +01:00
Buffer = ( __typeof__ ( Buffer ) ) EfiReallocatePool ( Buffer , LastBufferSize , BufferSize ) ;
2019-09-03 11:58:42 +02:00
LastBufferSize = BufferSize ;
}
if ( EFI_ERROR ( Status ) ) {
FreePool ( Buffer ) ;
break ;
}
// check for end of listing
if ( BufferSize = = 0 ) { // end of directory listing
FreePool ( Buffer ) ;
break ;
}
// entry is ready to be returned
* DirEntry = ( EFI_FILE_INFO * ) Buffer ;
if ( * DirEntry ) {
// filter results
if ( FilterMode = = 1 ) { // only return directories
if ( ( ( * DirEntry ) - > Attribute & EFI_FILE_DIRECTORY ) )
break ;
} else if ( FilterMode = = 2 ) { // only return files
if ( ( ( * DirEntry ) - > Attribute & EFI_FILE_DIRECTORY ) = = 0 )
break ;
} else // no filter or unknown filter -> return everything
break ;
}
}
return Status ;
}
2020-02-17 21:41:09 +01:00
VOID DirIterOpen ( IN EFI_FILE * BaseDir , IN CONST CHAR16 * RelativePath OPTIONAL , OUT REFIT_DIR_ITER * DirIter )
2019-09-03 11:58:42 +02:00
{
if ( RelativePath = = NULL ) {
DirIter - > LastStatus = EFI_SUCCESS ;
DirIter - > DirHandle = BaseDir ;
DirIter - > CloseDirHandle = FALSE ;
} else {
2020-02-21 06:29:22 +01:00
DirIter - > LastStatus = BaseDir - > Open ( BaseDir , & ( DirIter - > DirHandle ) , RelativePath , EFI_FILE_MODE_READ , 0 ) ;
2019-09-03 11:58:42 +02:00
DirIter - > CloseDirHandle = EFI_ERROR ( DirIter - > LastStatus ) ? FALSE : TRUE ;
}
DirIter - > LastFileInfo = NULL ;
}
2020-02-17 21:41:09 +01:00
BOOLEAN DirIterNext ( IN OUT REFIT_DIR_ITER * DirIter , IN UINTN FilterMode , IN CONST CHAR16 * FilePattern OPTIONAL ,
2019-09-03 11:58:42 +02:00
OUT EFI_FILE_INFO * * DirEntry )
{
if ( DirIter - > LastFileInfo ! = NULL ) {
FreePool ( DirIter - > LastFileInfo ) ;
DirIter - > LastFileInfo = NULL ;
}
if ( EFI_ERROR ( DirIter - > LastStatus ) )
return FALSE ; // stop iteration
for ( ; ; ) {
DirIter - > LastStatus = DirNextEntry ( DirIter - > DirHandle , & ( DirIter - > LastFileInfo ) , FilterMode ) ;
if ( EFI_ERROR ( DirIter - > LastStatus ) )
return FALSE ;
if ( DirIter - > LastFileInfo = = NULL ) // end of listing
return FALSE ;
if ( FilePattern ! = NULL ) {
if ( ( DirIter - > LastFileInfo - > Attribute & EFI_FILE_DIRECTORY ) )
break ;
if ( MetaiMatch ( DirIter - > LastFileInfo - > FileName , FilePattern ) )
break ;
// else continue loop
} else
break ;
}
* DirEntry = DirIter - > LastFileInfo ;
return TRUE ;
}
EFI_STATUS DirIterClose ( IN OUT REFIT_DIR_ITER * DirIter )
{
if ( DirIter - > LastFileInfo ! = NULL ) {
FreePool ( DirIter - > LastFileInfo ) ;
DirIter - > LastFileInfo = NULL ;
}
if ( DirIter - > CloseDirHandle )
DirIter - > DirHandle - > Close ( DirIter - > DirHandle ) ;
return DirIter - > LastStatus ;
}
//
// file name manipulation
//
BOOLEAN
MetaiMatch (
2020-02-17 21:41:09 +01:00
IN CONST CHAR16 * String ,
IN CONST CHAR16 * Pattern
2019-09-03 11:58:42 +02:00
)
{
if ( ! mUnicodeCollation ) {
// quick fix for driver loading on UEFIs without UnicodeCollation
//return FALSE;
return TRUE ;
}
2020-02-21 06:29:22 +01:00
return mUnicodeCollation - > MetaiMatch ( mUnicodeCollation , String , Pattern ) ;
2019-09-03 11:58:42 +02:00
}
EFI_STATUS
InitializeUnicodeCollationProtocol ( VOID )
{
EFI_STATUS Status ;
if ( mUnicodeCollation ! = NULL ) {
return EFI_SUCCESS ;
}
//
// BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol
// instances first and then select one which support English language.
// Current implementation just pick the first instance.
//
Status = gBS - > LocateProtocol (
& gEfiUnicodeCollation2ProtocolGuid ,
NULL ,
( VOID * * ) & mUnicodeCollation
) ;
if ( EFI_ERROR ( Status ) ) {
Status = gBS - > LocateProtocol (
& gEfiUnicodeCollationProtocolGuid ,
NULL ,
( VOID * * ) & mUnicodeCollation
) ;
}
return Status ;
}
2020-02-17 21:41:09 +01:00
CONST CHAR16 * Basename ( IN CONST CHAR16 * Path )
2019-09-03 11:58:42 +02:00
{
2020-02-17 21:41:09 +01:00
CONST CHAR16 * FileName ;
2019-09-03 11:58:42 +02:00
UINTN i ;
FileName = Path ;
if ( Path ! = NULL ) {
for ( i = StrLen ( Path ) ; i > 0 ; i - - ) {
if ( Path [ i - 1 ] = = ' \\ ' | | Path [ i - 1 ] = = ' / ' ) {
FileName = Path + i ;
break ;
}
}
}
return FileName ;
}
VOID ReplaceExtension ( IN OUT CHAR16 * Path , IN CHAR16 * Extension )
{
INTN i ;
for ( i = StrLen ( Path ) ; i > = 0 ; i - - ) {
if ( Path [ i ] = = ' . ' ) {
Path [ i ] = 0 ;
break ;
}
if ( Path [ i ] = = ' \\ ' | | Path [ i ] = = ' / ' )
break ;
}
StrCatS ( Path , StrLen ( Path ) / sizeof ( CHAR16 ) + 1 , Extension ) ;
}
CHAR16 * egFindExtension ( IN CHAR16 * FileName )
{
INTN i ;
for ( i = StrLen ( FileName ) ; i > = 0 ; i - - ) {
if ( FileName [ i ] = = ' . ' )
return FileName + i + 1 ;
if ( FileName [ i ] = = ' / ' | | FileName [ i ] = = ' \\ ' )
break ;
}
return FileName + StrLen ( FileName ) ;
}
//
// memory string search
//
2019-12-27 17:12:28 +01:00
INTN FindMem ( IN CONST VOID * Buffer , IN UINTN BufferLength , IN CONST VOID * SearchString , IN UINTN SearchStringLength )
2019-09-03 11:58:42 +02:00
{
2019-12-27 17:12:28 +01:00
CONST UINT8 * BufferPtr ;
2019-09-03 11:58:42 +02:00
UINTN Offset ;
2019-12-27 17:12:28 +01:00
BufferPtr = ( CONST UINT8 * ) Buffer ;
2019-09-03 11:58:42 +02:00
BufferLength - = SearchStringLength ;
for ( Offset = 0 ; Offset < BufferLength ; Offset + + , BufferPtr + + ) {
if ( CompareMem ( BufferPtr , SearchString , SearchStringLength ) = = 0 )
return ( INTN ) Offset ;
}
return - 1 ;
}
//
// Aptio UEFI returns File DevPath as 2 nodes (dir, file)
// and DevicePathToStr connects them with /, but we need '\\'
CHAR16 * FileDevicePathToStr ( IN EFI_DEVICE_PATH_PROTOCOL * DevPath )
{
CHAR16 * FilePath ;
CHAR16 * Char ;
2020-02-17 21:41:09 +01:00
CONST CHAR16 * Tail ;
2019-09-03 11:58:42 +02:00
FilePath = DevicePathToStr ( DevPath ) ;
// fix / into '\\'
if ( FilePath ! = NULL ) {
for ( Char = FilePath ; * Char ! = L ' \0 ' ; Char + + ) {
if ( * Char = = L ' / ' ) {
* Char = L ' \\ ' ;
}
}
}
// "\\\\" into '\\'
2020-02-17 21:41:09 +01:00
Char = ( CHAR16 * ) StrStr ( FilePath , L " \\ \\ " ) ; // cast is ok because FilePath is not const, and we know that StrStr returns a pointer in FilePath. Will disappear when using a string object instead of CHAR16*
2019-09-03 11:58:42 +02:00
while ( Char ! = NULL ) {
// StrCpyS(Char, 4, Char + 1); //can't overlap
Tail = Char + 1 ;
while ( * Tail ! = 0 ) {
* ( Char + + ) = * ( Tail + + ) ;
}
2020-02-17 21:41:09 +01:00
Char = ( CHAR16 * ) StrStr ( FilePath , L " \\ \\ " ) ; // cast is ok because FilePath is not const, and we know that StrStr returns a pointer in FilePath. Will disappear when using a string object instead of CHAR16*
2019-09-03 11:58:42 +02:00
}
return FilePath ;
}
CHAR16 * FileDevicePathFileToStr ( IN EFI_DEVICE_PATH_PROTOCOL * DevPath )
{
EFI_DEVICE_PATH_PROTOCOL * Node ;
if ( DevPath = = NULL ) {
return NULL ;
}
Node = ( EFI_DEVICE_PATH_PROTOCOL * ) DevPath ;
while ( ! IsDevicePathEnd ( Node ) ) {
if ( ( Node - > Type = = MEDIA_DEVICE_PATH ) & &
( Node - > SubType = = MEDIA_FILEPATH_DP ) ) {
return FileDevicePathToStr ( Node ) ;
}
Node = NextDevicePathNode ( Node ) ;
}
return NULL ;
}
BOOLEAN DumpVariable ( CHAR16 * Name , EFI_GUID * Guid , INTN DevicePathAt )
{
UINTN dataSize = 0 ;
UINT8 * data = NULL ;
UINTN i ;
EFI_STATUS Status ;
Status = gRT - > GetVariable ( Name , Guid , NULL , & dataSize , data ) ;
if ( Status = = EFI_BUFFER_TOO_SMALL ) {
2019-12-21 01:31:49 +01:00
data = ( __typeof__ ( data ) ) AllocateZeroPool ( dataSize ) ;
2019-09-03 11:58:42 +02:00
Status = gRT - > GetVariable ( Name , Guid , NULL , & dataSize , data ) ;
if ( EFI_ERROR ( Status ) ) {
DBG ( " Can't get %s, size=%d \n " , Name , dataSize ) ;
FreePool ( data ) ;
data = NULL ;
} else {
DBG ( " %s var size=%d \n " , Name , dataSize ) ;
for ( i = 0 ; i < dataSize ; i + + ) {
DBG ( " %02x " , data [ i ] ) ;
}
DBG ( " \n " ) ;
if ( DevicePathAt > = 0 ) {
DBG ( " %s: %s \n " , Name , FileDevicePathToStr ( ( EFI_DEVICE_PATH_PROTOCOL * ) & data [ DevicePathAt ] ) ) ;
}
}
}
if ( data ) {
FreePool ( data ) ;
return TRUE ;
}
return FALSE ;
}
2020-02-17 21:41:09 +01:00
VOID DbgHeader ( CONST CHAR8 * str )
2019-09-03 11:58:42 +02:00
{
# if defined(ADVLOG)
INTN i , len = 50 - AsciiStrLen ( str ) ;
DebugLog ( 1 , " === [ %a ] " , str ) ;
for ( i = 0 ; i < len ; i + + ) DebugLog ( 1 , " = " ) ;
DebugLog ( 1 , " \n " ) ;
# else //ADVLOG
DebugLog ( 1 , " %a: \n " , str ) ;
# endif //ADVLOG
}
// EOF