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 .
*/
2020-08-17 21:40:52 +02:00
# include <Platform.h> // Only use angled for Platform, else, xcode project won't compile
2021-02-06 18:16:46 +01:00
# include <Efi.h>
# include "../include/OSTypes.h"
2020-10-22 15:55:30 +02:00
# include "lib.h"
2020-04-16 11:09:22 +02:00
# include "screen.h"
2021-04-05 10:57:55 +02:00
# include "../Platform/BasicIO.h"
2021-02-06 18:16:46 +01:00
# include "../Platform/BootLog.h"
2020-08-07 10:23:46 +02:00
# include "../Platform/guid.h"
# include "../Platform/APFS.h"
2020-08-17 21:40:52 +02:00
# include "../refit/lib.h"
# include "../Platform/Settings.h"
2021-04-28 20:30:34 +02:00
# include "../Settings/Self.h"
# include "../Settings/SelfOem.h"
2021-02-04 15:04:31 +01:00
# include "../Platform/Volumes.h"
2021-02-06 18:16:46 +01:00
# include "../libeg/XTheme.h"
# include "../include/OC.h"
2019-09-03 11:58:42 +02:00
# 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
2020-03-20 18:48:19 +01:00
2020-10-03 19:02:31 +02:00
//XStringW ThemePath;
2021-09-28 15:54:31 +02:00
//XBool gBootArgsChanged = false;
XBool gThemeOptionsChanged = false ;
2019-09-03 11:58:42 +02:00
//
// Unicode collation protocol interface
//
EFI_UNICODE_COLLATION_PROTOCOL * mUnicodeCollation = NULL ;
// functions
2020-10-03 19:02:31 +02:00
static void UninitVolumes ( void ) ;
2019-09-03 11:58:42 +02:00
// 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 ;
}
2021-09-28 10:28:45 +02:00
XBool 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
) ;
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 ) ;
2020-03-25 19:32:44 +01:00
// DBG("volume handle found =%X\n", NewHandle);
2019-09-03 11:58:42 +02:00
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 )
{
2020-09-28 17:57:50 +02:00
self . initialize ( ImageHandle ) ;
2022-08-01 21:34:35 +02:00
DBG ( " SelfDirPath = %ls \n " , self . getCloverDirFullPath ( ) . wc_str ( ) ) ;
2020-10-03 19:02:31 +02:00
return EFI_SUCCESS ;
2019-09-03 11:58:42 +02:00
}
2020-10-03 19:02:31 +02:00
void UninitRefitLib ( void )
2019-09-03 11:58:42 +02:00
{
// called before running external programs to close open file handles
2020-10-03 19:02:31 +02:00
selfOem . closeHandle ( ) ;
2020-10-17 15:01:33 +02:00
self . closeHandle ( ) ;
2019-09-03 11:58:42 +02:00
2020-10-17 15:01:33 +02:00
closeDebugLog ( ) ;
2019-09-03 11:58:42 +02:00
UninitVolumes ( ) ;
}
2020-10-03 19:02:31 +02:00
EFI_STATUS ReinitRefitLib ( void )
2019-09-03 11:58:42 +02:00
{
// called after reconnect drivers to re-open file handles
2020-10-03 19:02:31 +02:00
self . reInitialize ( ) ;
selfOem . reInitialize ( ) ;
2019-09-03 11:58:42 +02:00
2020-10-12 13:51:08 +02:00
ReinitVolumes ( ) ;
2019-09-03 11:58:42 +02:00
2020-10-03 19:02:31 +02:00
return EFI_SUCCESS ;
2020-03-29 18:17:27 +02:00
}
2019-09-03 11:58:42 +02:00
2020-04-10 12:04:21 +02:00
2019-09-03 11:58:42 +02:00
//
// firmware device path discovery
//
2020-04-05 20:56:36 +02:00
//looks like not used anywhere
2019-09-03 11:58:42 +02:00
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 ;
2021-09-28 15:54:31 +02:00
XBool Seen ;
2019-09-03 11:58:42 +02:00
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 ] ;
2020-10-03 19:02:31 +02:00
Status = gBS - > HandleProtocol ( Handle , & gEfiLoadedImageProtocolGuid , ( void * * ) & LoadedImage ) ;
2019-09-03 11:58:42 +02:00
if ( EFI_ERROR ( Status ) )
continue ; // This can only happen if the firmware scewed up, ignore it.
2020-10-03 19:02:31 +02:00
Status = gBS - > HandleProtocol ( LoadedImage - > DeviceHandle , & gEfiDevicePathProtocolGuid , ( void * * ) & DevicePath ) ;
2019-09-03 11:58:42 +02:00
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!
2021-09-28 10:28:45 +02:00
Seen = false ;
2019-09-03 11:58:42 +02:00
for ( PathIndex = 0 ; PathIndex < PathCount ; PathIndex + + ) {
if ( DevicePathNodeLength ( DevicePath ) ! = DevicePathNodeLength ( PathList [ PathIndex ] ) )
continue ;
if ( CompareMem ( DevicePath , PathList [ PathIndex ] , DevicePathNodeLength ( DevicePath ) ) = = 0 ) {
2021-09-28 10:28:45 +02:00
Seen = true ;
2019-09-03 11:58:42 +02:00
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
//
2021-09-28 10:28:45 +02:00
static void ScanVolumeBootcode ( IN OUT REFIT_VOLUME * Volume , OUT XBool * Bootable )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
2021-09-28 15:54:31 +02:00
UINT8 * SectorBuffer ;
2019-09-03 11:58:42 +02:00
UINTN i ;
2021-09-28 15:54:31 +02:00
//MBR_PARTITION_INFO *MbrTable;
2021-09-28 10:28:45 +02:00
//XBool MbrTableFound;
2021-09-28 15:54:31 +02:00
UINTN BlockSize = 0 ;
CHAR16 volumeName [ 255 ] ;
CHAR8 tmp [ 64 ] ;
UINT32 VCrc32 ;
//CHAR16 *kind = NULL;
2019-09-03 11:58:42 +02:00
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = false ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName . setEmpty ( ) ;
Volume - > LegacyOS . Name . setEmpty ( ) ;
2019-09-03 11:58:42 +02:00
// Volume->BootType = BOOTING_BY_MBR; //default value
Volume - > BootType = BOOTING_BY_EFI ;
2021-09-28 10:28:45 +02:00
* Bootable = false ;
2019-09-03 11:58:42 +02:00
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
2021-09-28 10:28:45 +02:00
* Bootable = true ;
Volume - > HasBootCode = true ; //we assume that all CD are bootable
2019-09-03 11:58:42 +02:00
/* DBG("check SectorBuffer\n");
for ( i = 0 ; i < 32 ; i + + ) {
2020-04-17 15:14:24 +02:00
DBG ( " %2hhX " , SectorBuffer [ i ] ) ;
2019-09-03 11:58:42 +02:00
}
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 ;
}
2020-04-17 15:14:24 +02:00
DBG ( " Volume kind=%ls CRC=0x%hhX \n " , kind , VCrc32 ) ; */
2019-09-03 11:58:42 +02:00
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 ) ;
// }
2020-03-25 19:32:44 +01:00
DBG ( " Detected name %ls \n " , volumeName ) ;
2020-08-09 17:55:30 +02:00
Volume - > VolName . takeValueFrom ( volumeName ) ;
2019-09-03 11:58:42 +02:00
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 " ) ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . Type = OSTYPE_OSX ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_CD ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " mac " _XSW ;
2019-09-03 11:58:42 +02:00
break ;
}
} else if ( SectorBuffer [ i ] = = ' M ' ) {
if ( AsciiStrStr ( ( CHAR8 * ) & SectorBuffer [ i ] , " MICROSOFT " ) ) {
// StrCpy(Volume->VolName, volumeName);
DBG ( " Found Windows DVD \n " ) ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . Type = OSTYPE_WIN ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_CD ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " win " _XSW ;
2019-09-03 11:58:42 +02:00
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 " ) ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . Type = OSTYPE_LIN ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_CD ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " linux " _XSW ;
2019-09-03 11:58:42 +02:00
break ;
}
}
}
}
//else HDD
else { //HDD
/*
// apianti - does this detect every partition as legacy?
if ( * ( ( UINT16 * ) ( SectorBuffer + 510 ) ) = = 0xaa55 & & SectorBuffer [ 0 ] ! = 0 ) {
2021-09-28 10:28:45 +02:00
* Bootable = true ;
Volume - > HasBootCode = true ;
2019-09-03 11:58:42 +02:00
// DBG("The volume has bootcode\n");
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " legacy " ;
Volume - > LegacyOS . Name = L " Legacy " ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
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 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " linux " _XSW ;
Volume - > LegacyOS . Name = L " Linux " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_LIN ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " Geom \0 Hard Disk \0 Read \0 Error " , 26 ) > = 0 ) { // GRUB
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " grub,linux " _XSW ;
Volume - > LegacyOS . Name = L " Linux " _XSW ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
/*
} else if ( ( * ( ( UINT32 * ) ( SectorBuffer ) ) = = 0x4d0062e9 & &
* ( ( UINT16 * ) ( SectorBuffer + 510 ) ) = = 0xaa55 ) | |
FindMem ( SectorBuffer , 2048 , " BOOT " , 10 ) > = 0 ) { //reboot Clover
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " clover " ;
Volume - > LegacyOS . Name = L " Clover " ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
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 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " freebsd,linux " _XSW ;
Volume - > LegacyOS . Name = L " FreeBSD " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " !Loading " , 8 ) > = 0 | |
FindMem ( SectorBuffer , 2048 , " /cdboot \0 /CDBOOT \0 " , 16 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " openbsd,linux " _XSW ;
Volume - > LegacyOS . Name = L " OpenBSD " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " Not a bootxx image " , 18 ) > = 0 | |
* ( ( UINT32 * ) ( SectorBuffer + 1028 ) ) = = 0x7886b6d1 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " netbsd,linux " _XSW ;
Volume - > LegacyOS . Name = L " NetBSD " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 2048 , " NTLDR " , 5 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " win " _XSW ;
Volume - > LegacyOS . Name = L " Windows " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_WIN ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 2048 , " BOOTMGR " , 7 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " vista,win " _XSW ;
Volume - > LegacyOS . Name = L " Windows " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_WIN ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " CPUBOOT SYS " , 11 ) > = 0 | |
FindMem ( SectorBuffer , 512 , " KERNEL SYS " , 11 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " freedos,win " _XSW ;
Volume - > LegacyOS . Name = L " FreeDOS " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
2021-04-23 14:20:48 +02:00
2019-09-03 11:58:42 +02:00
} else if ( FindMem ( SectorBuffer , 512 , " OS2LDR " , 6 ) > = 0 | |
FindMem ( SectorBuffer , 512 , " OS2BOOT " , 7 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " ecomstation " _XSW ;
Volume - > LegacyOS . Name = L " eComStation " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " Be Boot Loader " , 14 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " beos " _XSW ;
Volume - > LegacyOS . Name = L " BeOS " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
} else if ( FindMem ( SectorBuffer , 512 , " yT Boot Loader " , 14 ) > = 0 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " zeta " _XSW ;
Volume - > LegacyOS . Name = L " ZETA " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
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 ) {
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = true ;
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . IconName = L " haiku " _XSW ;
Volume - > LegacyOS . Name = L " Haiku " _XSW ;
Volume - > LegacyOS . Type = OSTYPE_VAR ;
2019-09-03 11:58:42 +02:00
Volume - > BootType = BOOTING_BY_PBR ;
2021-04-23 14:20:48 +02:00
2019-09-03 11:58:42 +02:00
}
}
// 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
2020-03-25 19:32:44 +01:00
DBG ( " Result of bootcode detection: %ls %ls (%ls) \n " ,
2019-09-03 11:58:42 +02:00
Volume - > HasBootCode ? L " bootable " : L " non-bootable " ,
2023-11-18 11:04:54 +01:00
Volume - > LegacyOS . Name . notEmpty ( ) ? Volume - > LegacyOS . Name . wc_str ( ) : L " unknown " ,
Volume - > LegacyOS . IconName . notEmpty ( ) ? Volume - > LegacyOS . IconName . wc_str ( ) : L " legacy " ) ;
2019-09-03 11:58:42 +02:00
# 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
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = false ;
2020-02-21 04:54:01 +01:00
2020-03-04 20:19:44 +01:00
# ifdef JIEF_DEBUG
2021-09-28 10:28:45 +02:00
////*Bootable = true;
//Volume->HasBootCode = true;
2023-11-18 11:04:54 +01:00
//Volume->LegacyOS.IconName = L"win"_XSW;
//Volume->LegacyOS.Name = L"Windows"_XSW;
//Volume->LegacyOS.Type = OSTYPE_WIN;
2020-08-07 15:17:30 +02:00
//Volume->BootType = BOOTING_BY_PBR;
2020-03-04 20:19:44 +01:00
# endif
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 ) {
2021-09-28 10:28:45 +02:00
MbrTableFound = false ;
2019-09-03 11:58:42 +02:00
MbrTable = ( MBR_PARTITION_INFO * ) ( SectorBuffer + 446 ) ;
for ( i = 0 ; i < 4 ; i + + )
if ( MbrTable [ i ] . StartLBA & & MbrTable [ i ] . Size )
2021-09-28 10:28:45 +02:00
MbrTableFound = true ;
2019-09-03 11:58:42 +02:00
for ( i = 0 ; i < 4 ; i + + )
if ( MbrTable [ i ] . Flags ! = 0x00 & & MbrTable [ i ] . Flags ! = 0x80 )
2021-09-28 10:28:45 +02:00
MbrTableFound = false ;
2019-09-03 11:58:42 +02:00
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);
2020-10-03 19:02:31 +02:00
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 ;
HARDDRIVE_DEVICE_PATH * HdPath = NULL ;
EFI_HANDLE WholeDiskHandle ;
UINTN PartialLength = 0 ;
UINTN DevicePathSize ;
// UINTN BufferSize = 255;
EFI_FILE_SYSTEM_INFO * FileSystemInfoPtr ;
EFI_FILE_INFO * RootInfo = NULL ;
2021-09-28 15:54:31 +02:00
XBool Bootable ;
2019-09-03 11:58:42 +02:00
// EFI_INPUT_KEY Key;
2023-11-18 11:04:54 +01:00
{
// get device path
EFI_DEVICE_PATH * DiskDevicePath = DevicePathFromHandle ( Volume - > DeviceHandle ) ;
//Volume->DevicePath = DuplicateDevicePath(DevicePathFromHandle(Volume->DeviceHandle));
DevicePathSize = GetDevicePathSize ( DiskDevicePath ) ;
Volume - > DevicePath = ( __typeof__ ( Volume - > DevicePath ) ) AllocateAlignedPages ( EFI_SIZE_TO_PAGES ( DevicePathSize ) , 64 ) ;
CopyMem ( Volume - > DevicePath , DiskDevicePath , DevicePathSize ) ;
Volume - > DevicePathString = FileDevicePathToXStringW ( Volume - > DevicePath ) ;
}
2019-09-03 11:58:42 +02:00
if ( Volume - > DevicePath ! = NULL ) {
2020-08-09 17:55:30 +02:00
DBG ( " %ls \n " , FileDevicePathToXStringW ( Volume - > DevicePath ) . wc_str ( ) ) ;
2020-08-07 10:23:46 +02:00
}
2019-09-03 11:58:42 +02:00
2022-04-26 00:55:56 +02:00
Volume - > ApfsFileSystemUUID = APFSPartitionUUIDExtract ( Volume - > DevicePath ) ; // NullXString8 if it's not an APFS volume
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = DISK_KIND_INTERNAL ; // default
// get block i/o
2020-10-03 19:02:31 +02:00
Status = gBS - > HandleProtocol ( Volume - > DeviceHandle , & gEfiBlockIoProtocolGuid , ( void * * ) & ( Volume - > BlockIO ) ) ;
2019-09-03 11:58:42 +02:00
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 ;
}
2021-09-28 10:28:45 +02:00
Bootable = false ;
2019-09-03 11:58:42 +02:00
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
2023-11-18 11:04:54 +01:00
apd < EFI_DEVICE_PATH * > DevicePath = DuplicateDevicePath ( Volume - > DevicePath ) ;
EFI_DEVICE_PATH * NextDevicePath = NextDevicePathNode ( DevicePath ) ;
while ( NextDevicePath ! = NULL & & ! IsDevicePathEndType ( NextDevicePath ) )
{
if ( ( DevicePathType ( NextDevicePath ) = = MESSAGING_DEVICE_PATH ) & &
( ( DevicePathSubType ( NextDevicePath ) = = MSG_SATA_DP ) | |
( DevicePathSubType ( NextDevicePath ) = = MSG_NVME_NAMESPACE_DP ) | |
( DevicePathSubType ( NextDevicePath ) = = 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 ;
}
2023-11-18 11:04:54 +01:00
if ( DevicePathType ( NextDevicePath ) = = MESSAGING_DEVICE_PATH & &
( DevicePathSubType ( NextDevicePath ) = = MSG_USB_DP | | DevicePathSubType ( NextDevicePath ) = = 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
2023-11-18 11:04:54 +01:00
if ( DevicePathType ( NextDevicePath ) = = MESSAGING_DEVICE_PATH & &
( DevicePathSubType ( NextDevicePath ) = = MSG_1394_DP | | DevicePathSubType ( NextDevicePath ) = = MSG_FIBRECHANNEL_DP ) ) {
2019-09-03 11:58:42 +02:00
// DBG(" FireWire volume\n");
Volume - > DiskKind = DISK_KIND_FIREWIRE ;
break ;
}
// CD-ROM Devices
2023-11-18 11:04:54 +01:00
if ( DevicePathType ( NextDevicePath ) = = MEDIA_DEVICE_PATH & &
DevicePathSubType ( NextDevicePath ) = = MEDIA_CDROM_DP ) {
2019-09-03 11:58:42 +02:00
// DBG(" CD-ROM volume\n");
Volume - > DiskKind = DISK_KIND_OPTICAL ; //it's impossible
break ;
}
// VENDOR Specific Path
2023-11-18 11:04:54 +01:00
if ( DevicePathType ( NextDevicePath ) = = MEDIA_DEVICE_PATH & &
DevicePathSubType ( NextDevicePath ) = = MEDIA_VENDOR_DP ) {
2020-02-21 04:54:01 +01:00
// DBG(" Vendor volume\n");
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . isNull ( ) ) {
2020-08-08 08:26:31 +02:00
Volume - > DiskKind = DISK_KIND_NODISK ; // Jief, don't know why DISK_KIND_NODISK in that case. That prevents Recovery badge to appear. If it's not APFS, let's do it like it was before.
}
2019-09-03 11:58:42 +02:00
break ;
}
// LEGACY CD-ROM
2023-11-18 11:04:54 +01:00
if ( DevicePathType ( NextDevicePath ) = = BBS_DEVICE_PATH & &
( DevicePathSubType ( NextDevicePath ) = = BBS_BBS_DP | | DevicePathSubType ( NextDevicePath ) = = BBS_TYPE_CDROM ) ) {
2019-09-03 11:58:42 +02:00
// DBG(" Legacy CD-ROM volume\n");
Volume - > DiskKind = DISK_KIND_OPTICAL ;
break ;
}
// LEGACY HARDDISK
2023-11-18 11:04:54 +01:00
if ( DevicePathType ( NextDevicePath ) = = BBS_DEVICE_PATH & &
( DevicePathSubType ( NextDevicePath ) = = BBS_BBS_DP | | DevicePathSubType ( NextDevicePath ) = = 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
2023-11-18 11:04:54 +01:00
NextDevicePath = NextDevicePathNode ( NextDevicePath ) ;
2019-09-03 11:58:42 +02:00
}
/* what is the bread?
2021-09-28 10:28:45 +02:00
// Bootable = true;
2019-09-03 11:58:42 +02:00
if ( DevicePathType ( DevicePath ) = = MEDIA_DEVICE_PATH & &
DevicePathSubType ( DevicePath ) = = MEDIA_VENDOR_DP ) {
2021-09-28 10:28:45 +02:00
Volume - > IsAppleLegacy = true ; // legacy BIOS device entry
2022-04-26 00:55:56 +02:00
// TODO: also check for Boot Camp EFI_GUID
2019-09-03 11:58:42 +02:00
//gEfiPartTypeSystemPartGuid
2021-09-28 10:28:45 +02:00
Bootable = false ; // this handle's BlockIO is just an alias for the whole device
2020-03-28 07:36:07 +01:00
DBG ( " AppleLegacy device \n " ) ;
2019-09-03 11:58:42 +02:00
}
*/
}
2023-11-18 11:04:54 +01:00
{
apd < EFI_DEVICE_PATH * > DevicePath = DuplicateDevicePath ( Volume - > DevicePath ) ;
EFI_DEVICE_PATH * walkDevicePath = DevicePath ; //initial value
//
// find the partition device path node
//
while ( walkDevicePath & & ! IsDevicePathEnd ( walkDevicePath ) ) {
if ( ( DevicePathType ( walkDevicePath ) = = MEDIA_DEVICE_PATH ) & &
( DevicePathSubType ( walkDevicePath ) = = MEDIA_HARDDRIVE_DP ) ) {
HdPath = ( HARDDRIVE_DEVICE_PATH * ) walkDevicePath ;
// break;
}
walkDevicePath = NextDevicePathNode ( walkDevicePath ) ;
2019-09-03 11:58:42 +02:00
}
2023-11-18 11:04:54 +01:00
// DBG("DevicePath scanned\n");
if ( HdPath ) {
// printf("Partition found %s\n", DevicePathToStr((EFI_DEVICE_PATH *)HdPath));
PartialLength = ( UINTN ) ( ( UINT8 * ) HdPath - ( UINT8 * ) ( DevicePath . get ( ) ) ) ;
if ( PartialLength > 0x1000 ) {
PartialLength = sizeof ( EFI_DEVICE_PATH ) ; //something wrong here but I don't want to be freezed
// return EFI_SUCCESS;
}
apd < EFI_DEVICE_PATH * > DiskDevicePath = ( EFI_DEVICE_PATH * ) AllocatePool ( PartialLength + sizeof ( EFI_DEVICE_PATH ) ) ;
CopyMem ( DiskDevicePath , Volume - > DevicePath , PartialLength ) ;
CopyMem ( ( UINT8 * ) DiskDevicePath . get ( ) + PartialLength , walkDevicePath , sizeof ( EFI_DEVICE_PATH ) ) ; //EndDevicePath
// DBG("WholeDevicePath %ls\n", DevicePathToStr(DiskDevicePath));
EFI_DEVICE_PATH * RemainingDevicePath = DiskDevicePath ;
Status = gBS - > LocateDevicePath ( & gEfiDevicePathProtocolGuid , & RemainingDevicePath , & WholeDiskHandle ) ;
if ( EFI_ERROR ( Status ) ) {
DBG ( " Can't find WholeDevicePath: %s \n " , efiStrError ( Status ) ) ;
2019-09-03 11:58:42 +02:00
} else {
2023-11-18 11:04:54 +01:00
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 %hhX 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 ;
// DBG("no WholeDiskBlockIO: %s\n", efiStrError(Status));
//CheckError(Status, L"from HandleProtocol");
}
2019-09-03 11:58:42 +02:00
}
}
}
/* else {
DBG ( " HD path is not found \n " ) ; //master volume!
} */
2021-02-02 10:02:21 +01:00
// if (GlobalConfig.isFastBoot()) {
2019-09-03 11:58:42 +02:00
// 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
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = false ;
2019-09-03 11:58:42 +02:00
}
// 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 ) {
2020-08-09 17:55:30 +02:00
Volume - > VolName = SWPrintf ( " Legacy HD%d " , HdPath - > PartitionNumber ) ;
} else if ( Volume - > VolName . isEmpty ( ) ) {
Volume - > VolName = L " Whole Disc Boot " _XSW ;
2019-09-03 11:58:42 +02:00
}
2023-11-18 11:04:54 +01:00
if ( Volume - > LegacyOS . IconName . isEmpty ( ) )
Volume - > LegacyOS . IconName = L " legacy " _XSW ;
2019-09-03 11:58:42 +02:00
return EFI_SUCCESS ;
}
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . notNull ( ) ) {
2023-11-18 11:04:54 +01:00
apd < APPLE_APFS_CONTAINER_INFO * > ApfsContainerInfo ;
apd < APPLE_APFS_VOLUME_INFO * > ApfsVolumeInfo ;
Status = InternalGetApfsSpecialFileInfo ( Volume - > RootDir , & ApfsVolumeInfo . get ( ) , & ApfsContainerInfo . get ( ) ) ;
2020-10-22 15:55:30 +02:00
if ( ! EFI_ERROR ( Status ) ) {
//DBG("Status : %s, APFS role : %x\n", efiStrError(Status), ApfsVolumeInfo->Role);
Volume - > ApfsRole = ApfsVolumeInfo - > Role ;
2022-04-26 00:55:56 +02:00
Volume - > ApfsContainerUUID = ApfsContainerInfo - > Uuid ;
2020-10-22 15:55:30 +02:00
} else {
MsgLog ( " Status : %s, APFS role : %x \n " , efiStrError ( Status ) , ApfsVolumeInfo - > Role ) ;
}
}
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . notNull ( ) ) {
DBG ( " apfsFileSystemUUID=%s, ApfsContainerUUID=%s, ApfsRole=0x%x \n " , Volume - > ApfsFileSystemUUID . toXString8 ( ) . c_str ( ) , Volume - > ApfsContainerUUID . toXString8 ( ) . c_str ( ) , Volume - > ApfsRole ) ;
2020-10-22 15:55:30 +02:00
}
2020-01-15 08:58:18 +01:00
if ( FileExists ( Volume - > RootDir , L " \\ .VolumeLabel.txt " ) ) {
2020-10-03 19:02:31 +02:00
EFI_FILE * FileHandle ;
2020-01-15 08:58:18 +01:00
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 ) ) {
2022-03-08 16:09:22 +01:00
// strip line endings
while ( BufferSize > 0 & & ( Buffer [ BufferSize - 1 ] = = ' \n ' | | Buffer [ BufferSize - 1 ] = = ' \r ' ) ) {
Buffer [ - - BufferSize ] = ' \0 ' ;
}
Volume - > VolLabel = SWPrintf ( " %s " , Buffer ) ;
2020-01-15 08:58:18 +01:00
}
}
}
2019-09-03 11:58:42 +02:00
// get volume name
2020-08-09 17:55:30 +02:00
if ( Volume - > VolName . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
FileSystemInfoPtr = EfiLibFileSystemInfo ( Volume - > RootDir ) ;
if ( FileSystemInfoPtr ) {
2020-03-25 19:32:44 +01:00
//DBG(" Volume name from FileSystem: '%ls'\n", FileSystemInfoPtr->VolumeLabel);
2020-08-09 17:55:30 +02:00
Volume - > VolName . takeValueFrom ( FileSystemInfoPtr - > VolumeLabel ) ;
2019-09-03 11:58:42 +02:00
FreePool ( FileSystemInfoPtr ) ;
}
}
2020-08-09 17:55:30 +02:00
if ( Volume - > VolName . isEmpty ( ) ) {
Volume - > VolName = EfiLibFileSystemVolumeLabelInfo ( Volume - > RootDir ) ;
//DBG(" Volume name from VolumeLabel: '%ls'\n", Volume->VolName.wc_str());
2019-09-03 11:58:42 +02:00
}
2020-08-09 17:55:30 +02:00
if ( Volume - > VolName . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
RootInfo = EfiLibFileInfo ( Volume - > RootDir ) ;
if ( RootInfo ) {
2020-03-25 19:32:44 +01:00
//DBG(" Volume name from RootFile: '%ls'\n", RootInfo->FileName);
2020-08-09 17:55:30 +02:00
Volume - > VolName . takeValueFrom ( RootInfo - > FileName ) ;
2019-09-03 11:58:42 +02:00
FreePool ( RootInfo ) ;
}
}
2021-04-11 07:18:52 +02:00
if ( Volume - > VolName . isEmpty ( ) | | Volume - > VolName . isEqual ( " \\ " ) | | Volume - > VolName . isEqual ( L " / " ) )
2019-09-03 11:58:42 +02:00
{
2020-10-03 19:02:31 +02:00
void * Instance ;
2020-04-23 11:08:10 +02:00
if ( ! EFI_ERROR ( gBS - > HandleProtocol ( Volume - > DeviceHandle , & gEfiPartTypeSystemPartGuid , & Instance ) ) ) {
2020-10-22 15:55:30 +02:00
Volume - > VolName = L " EFI " _XSW ;
2019-09-03 11:58:42 +02:00
}
}
2020-08-09 17:55:30 +02:00
if ( Volume - > VolName . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// DBG("Create unknown name\n");
// WaitForSingleEvent (gST->ConIn->WaitForKey, 0);
// gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if ( HdPath ) {
2020-08-09 17:55:30 +02:00
Volume - > VolName . SWPrintf ( " Unknown HD%d " , HdPath - > PartitionNumber ) ;
2019-09-03 11:58:42 +02:00
// NOTE: this is normal for Apple's VenMedia device paths
} else {
2020-08-09 17:55:30 +02:00
Volume - > VolName = L " Unknown HD " _XSW ; //To be able to free it
2019-09-03 11:58:42 +02:00
}
}
2020-08-07 15:17:30 +02:00
// Browse all folders under root that looks like an UUID
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . notNull ( ) )
2020-08-07 15:17:30 +02:00
{
REFIT_DIR_ITER DirIter ;
EFI_FILE_INFO * DirEntry = NULL ;
DirIterOpen ( Volume - > RootDir , L " \\ " , & DirIter ) ;
while ( DirIterNext ( & DirIter , 1 , L " * " , & DirEntry ) ) {
if ( DirEntry - > FileName [ 0 ] = = ' . ' ) {
//DBG("Skip dot entries: %ls\n", DirEntry->FileName);
continue ;
}
2022-04-26 00:55:56 +02:00
if ( EFI_GUID : : IsValidGuidString ( LStringW ( DirEntry - > FileName ) ) ) {
EFI_GUID * guid_ptr = new EFI_GUID ;
guid_ptr - > takeValueFrom ( DirEntry - > FileName , wcslen ( DirEntry - > FileName ) ) ;
if ( guid_ptr - > notNull ( ) ) Volume - > ApfsTargetUUIDArray . AddReference ( guid_ptr , true ) ;
else delete guid_ptr ;
2020-08-07 15:17:30 +02:00
}
}
DirIterClose ( & DirIter ) ;
}
2020-10-22 15:55:30 +02:00
DBG ( " label : %ls \n " , Volume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
//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 ;
}
2020-10-03 19:02:31 +02:00
static void ScanExtendedPartition ( REFIT_VOLUME * WholeDiskVolume , MBR_PARTITION_INFO * MbrEntry )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
2021-09-28 15:54:31 +02:00
REFIT_VOLUME * Volume ;
2019-09-03 11:58:42 +02:00
UINT32 ExtBase , ExtCurrent , NextExtCurrent ;
UINTN i ;
UINTN LogicalPartitionIndex = 4 ;
2021-09-28 15:54:31 +02:00
UINT8 * SectorBuffer ;
XBool Bootable ;
MBR_PARTITION_INFO * EMbrTable ;
2019-09-03 11:58:42 +02:00
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-08-09 17:55:30 +02:00
Volume = new REFIT_VOLUME ;
2019-09-03 11:58:42 +02:00
Volume - > DiskKind = WholeDiskVolume - > DiskKind ;
2021-09-28 10:28:45 +02:00
Volume - > IsMbrPartition = true ;
2019-09-03 11:58:42 +02:00
Volume - > MbrPartitionIndex = LogicalPartitionIndex + + ;
2020-08-09 17:55:30 +02:00
Volume - > VolName = SWPrintf ( " Partition %llu " , Volume - > MbrPartitionIndex + 1 ) ;
2019-09-03 11:58:42 +02:00
Volume - > BlockIO = WholeDiskVolume - > BlockIO ;
Volume - > BlockIOOffset = ExtCurrent + EMbrTable [ i ] . StartLBA ;
Volume - > WholeDiskBlockIO = WholeDiskVolume - > BlockIO ;
Volume - > WholeDiskDeviceHandle = WholeDiskVolume - > DeviceHandle ;
2021-09-28 10:28:45 +02:00
Bootable = false ;
2019-09-03 11:58:42 +02:00
ScanVolumeBootcode ( Volume , & Bootable ) ;
if ( ! Bootable )
2021-09-28 10:28:45 +02:00
Volume - > HasBootCode = false ;
2019-09-03 11:58:42 +02:00
2020-04-15 14:34:03 +02:00
Volumes . AddReference ( Volume , false ) ;
2020-10-03 19:02:31 +02:00
// AddListElement((void ***) &Volumes, &VolumesCount, Volume);
2019-09-03 11:58:42 +02:00
}
}
}
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) SectorBuffer , 1 ) ;
}
2020-10-03 19:02:31 +02:00
void ScanVolumes ( void )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
UINTN HandleCount = 0 ;
2022-03-08 16:09:22 +01:00
// UINTN HandleIndex;
2019-09-03 11:58:42 +02:00
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;
// DBG("Scanning volumes...\n");
DbgHeader ( " ScanVolumes " ) ;
// get all BlockIo handles
Status = gBS - > LocateHandleBuffer ( ByProtocol , & gEfiBlockIoProtocolGuid , NULL , & HandleCount , & Handles ) ;
if ( Status = = EFI_NOT_FOUND )
return ;
2020-03-25 19:32:44 +01:00
DBG ( " Found %llu volumes with blockIO \n " , HandleCount ) ;
2019-09-03 11:58:42 +02:00
// first pass: collect information about all handles
2022-03-08 17:48:52 +01:00
for ( UINTN HandleIndex = 0 ; HandleIndex < HandleCount ; HandleIndex + + ) {
2019-09-03 11:58:42 +02:00
2020-08-09 17:55:30 +02:00
REFIT_VOLUME * Volume = new REFIT_VOLUME ;
2019-09-03 11:58:42 +02:00
Volume - > DeviceHandle = Handles [ HandleIndex ] ;
2020-09-28 17:57:50 +02:00
if ( Volume - > DeviceHandle = = self . getSelfDeviceHandle ( ) ) {
2019-09-03 11:58:42 +02:00
SelfVolume = Volume ;
}
2020-03-25 19:32:44 +01:00
DBG ( " - [%02llu]: Volume: " , HandleIndex ) ;
2019-09-03 11:58:42 +02:00
2021-09-28 10:28:45 +02:00
Volume - > Hidden = false ; // default to not hidden
2019-09-03 11:58:42 +02:00
Status = ScanVolume ( Volume ) ;
2024-01-19 04:14:17 +01:00
# ifdef JIEF_DEBUG
DBG ( " kind=%d \n " , Volume - > DiskKind ) ;
# endif
2019-09-03 11:58:42 +02:00
if ( ! EFI_ERROR ( Status ) ) {
2022-03-08 16:09:22 +01:00
Volume - > Index = HandleIndex ;
2023-11-18 11:04:54 +01:00
Volumes . AddReference ( Volume , true ) ;
2021-03-19 21:32:42 +01:00
for ( size_t HVi = 0 ; HVi < gSettings . GUI . HVHideStrings . size ( ) ; HVi + + ) {
if ( Volume - > DevicePathString . containsIC ( gSettings . GUI . HVHideStrings [ HVi ] ) | |
Volume - > VolName . containsIC ( gSettings . GUI . HVHideStrings [ HVi ] )
2020-08-15 22:39:25 +02:00
) {
2021-09-28 10:28:45 +02:00
Volume - > Hidden = true ;
2020-08-15 22:39:25 +02:00
DBG ( " hiding this volume \n " ) ;
2019-09-03 11:58:42 +02:00
}
}
// Guid = FindGPTPartitionGuidInDevicePath(Volume->DevicePath);
2023-11-18 11:04:54 +01:00
if ( Volume - > LegacyOS . IconName . isEmpty ( ) ) {
Volume - > LegacyOS . IconName = L " legacy " _XSW ;
2019-09-03 11:58:42 +02:00
}
2022-04-26 00:55:56 +02:00
// DBG(" Volume '%ls', LegacyOS '%ls', LegacyIcon(s) '%ls', EFI_GUID = %s\n",
2023-11-18 11:04:54 +01:00
// Volume->VolName, Volume->LegacyOS.Name ? Volume->LegacyOS.Name : L"", Volume->LegacyOS.IconName, Guid.toXString8().c_str());
2019-09-03 11:58:42 +02:00
if ( SelfVolume = = Volume ) {
DBG ( " This is SelfVolume !! \n " ) ;
}
} else {
2020-03-25 19:32:44 +01:00
DBG ( " wrong volume Nr%llu?! \n " , HandleIndex ) ;
2019-09-03 11:58:42 +02:00
FreePool ( Volume ) ;
}
}
2024-01-08 11:28:32 +01:00
gBS - > FreePool ( Handles ) ; // use gBS->FreePool instead of FreePool to avoid message from MemoryTracker
2019-09-03 11:58:42 +02:00
// DBG("Found %d volumes\n", VolumesCount);
if ( SelfVolume = = NULL ) {
DBG ( " WARNING: SelfVolume not found " ) ; //Slice - and what?
2020-08-09 17:55:30 +02:00
SelfVolume = new REFIT_VOLUME ;
2020-09-28 17:57:50 +02:00
SelfVolume - > DeviceHandle = self . getSelfDeviceHandle ( ) ;
SelfVolume - > DevicePath = DuplicateDevicePath ( & self . getSelfDevicePath ( ) ) ;
2020-10-03 19:02:31 +02:00
SelfVolume - > RootDir = const_cast < EFI_FILE * > ( & self . getSelfVolumeRootDir ( ) ) ; // TODO : SelfVolume->RootDir should be const ! we should duplicate ?
2019-09-03 11:58:42 +02:00
SelfVolume - > DiskKind = DISK_KIND_BOOTER ;
2020-08-09 17:55:30 +02:00
SelfVolume - > VolName = L " Clover " _XSW ;
2023-11-18 11:04:54 +01:00
SelfVolume - > LegacyOS . Type = OSTYPE_EFI ;
2021-09-28 10:28:45 +02:00
SelfVolume - > HasBootCode = true ;
2019-09-03 11:58:42 +02:00
SelfVolume - > BootType = BOOTING_BY_PBR ;
2020-10-03 19:02:31 +02:00
// AddListElement((void ***) &Volumes, &VolumesCount, SelfVolume);
2019-09-03 11:58:42 +02:00
// 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 ) {
2020-12-13 09:51:50 +01:00
DBG ( " Volume %llu has MBR \n " , VolumeIndex ) ;
2019-09-03 11:58:42 +02:00
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...
2021-09-28 10:28:45 +02:00
Volume - > IsMbrPartition = true ;
2019-09-03 11:58:42 +02:00
Volume - > MbrPartitionTable = MbrTable ;
Volume - > MbrPartitionIndex = PartitionIndex ;
2020-08-09 17:55:30 +02:00
if ( Volume - > VolName . isEmpty ( ) )
Volume - > VolName = SWPrintf ( " Partition %llu " , PartitionIndex + 1 ) ;
2019-09-03 11:58:42 +02:00
break ;
}
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) SectorBuffer1 , 1 ) ;
gBS - > FreePages ( ( EFI_PHYSICAL_ADDRESS ) ( UINTN ) SectorBuffer2 , 1 ) ;
}
}
}
2020-10-03 19:02:31 +02:00
static void UninitVolumes ( void )
2019-09-03 11:58:42 +02:00
{
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-08-12 17:15:47 +02:00
Volumes . setEmpty ( ) ;
2019-09-03 11:58:42 +02:00
}
2020-10-03 19:02:31 +02:00
void ReinitVolumes ( void )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
REFIT_VOLUME * Volume ;
UINTN VolumeIndex ;
2023-11-06 21:53:57 +01:00
//UINTN VolumesFound = 0; // Jief not sure what this is, see my comment at the end of this function
2020-09-28 17:57:50 +02:00
const EFI_DEVICE_PATH * RemainingDevicePath ;
2019-09-03 11:58:42 +02:00
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 ;
}
2020-03-25 19:32:44 +01:00
DBG ( " Volume %llu at reinit found: \n " , VolumeIndex ) ;
2020-08-09 17:55:30 +02:00
DBG ( " Volume->DevicePath=%ls \n " , FileDevicePathToXStringW ( Volume - > DevicePath ) . wc_str ( ) ) ;
2023-11-06 21:53:57 +01:00
//olumesFound++;
2019-09-03 11:58:42 +02:00
if ( Volume - > DevicePath ! = NULL ) {
// get the handle for that path
RemainingDevicePath = Volume - > DevicePath ;
2020-09-28 17:57:50 +02:00
Status = gBS - > LocateDevicePath ( & gEfiBlockIoProtocolGuid , const_cast < EFI_DEVICE_PATH * * > ( & RemainingDevicePath ) , & DeviceHandle ) ;
2019-09-03 11:58:42 +02:00
if ( ! EFI_ERROR ( Status ) ) {
Volume - > DeviceHandle = DeviceHandle ;
// get the root directory
Volume - > RootDir = EfiLibOpenRoot ( Volume - > DeviceHandle ) ;
}
//else
// CheckError(Status, L"from LocateDevicePath");
}
2023-11-18 11:04:54 +01:00
if ( Volume - > WholeDiskDevicePath . notNull ( ) ) {
2019-09-03 11:58:42 +02:00
// get the handle for that path
RemainingDevicePath = DuplicateDevicePath ( Volume - > WholeDiskDevicePath ) ;
2020-09-28 17:57:50 +02:00
Status = gBS - > LocateDevicePath ( & gEfiBlockIoProtocolGuid , const_cast < EFI_DEVICE_PATH * * > ( & RemainingDevicePath ) , & WholeDiskHandle ) ;
2019-09-03 11:58:42 +02:00
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
2020-10-03 19:02:31 +02:00
Status = gBS - > HandleProtocol ( WholeDiskHandle , & gEfiBlockIoProtocolGuid , ( void * * ) & Volume - > WholeDiskBlockIO ) ;
2019-09-03 11:58:42 +02:00
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
}
2020-08-09 17:55:30 +02:00
REFIT_VOLUME * FindVolumeByName ( IN CONST CHAR16 * VolName )
2019-09-03 11:58:42 +02:00
{
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 ;
}
2021-04-11 07:18:52 +02:00
if ( Volume - > VolName . isEqual ( VolName ) = = 0 ) {
2019-09-03 11:58:42 +02:00
return Volume ;
}
}
return NULL ;
}
//
// file and dir functions
//
2021-09-28 10:28:45 +02:00
XBool 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 ) ;
}
2021-09-28 10:28:45 +02:00
return true ;
2019-09-03 11:58:42 +02:00
}
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
}
2021-09-28 10:28:45 +02:00
XBool FileExists ( const EFI_FILE * Root , const XStringW & RelativePath )
2020-04-27 11:50:49 +02:00
{
return FileExists ( Root , RelativePath . wc_str ( ) ) ;
}
2021-09-28 10:28:45 +02:00
XBool FileExists ( const EFI_FILE & Root , const XStringW & RelativePath )
2020-10-17 15:01:33 +02:00
{
return FileExists ( & Root , RelativePath . wc_str ( ) ) ;
}
2021-02-06 18:16:46 +01:00
EFI_DEVICE_PATH_PROTOCOL * FileDevicePath ( IN EFI_HANDLE Device , IN CONST XStringW & FileName )
{
return FileDevicePath ( Device , FileName . wc_str ( ) ) ;
}
2021-09-28 10:28:45 +02:00
XBool DeleteFile ( const 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 ;
2020-03-25 19:32:44 +01:00
//DBG("DeleteFile: %ls\n", RelativePath);
2019-09-03 11:58:42 +02:00
// 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 ) ;
2020-08-25 17:35:19 +02:00
//DBG(" Open: %s\n", efiStrError(Status));
2019-09-03 11:58:42 +02:00
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 ) ;
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
}
2020-04-17 15:14:24 +02:00
//DBG(" FileInfo attr: %hhX\n", FileInfo->Attribute);
2019-09-03 11:58:42 +02:00
if ( ( FileInfo - > Attribute & EFI_FILE_DIRECTORY ) = = EFI_FILE_DIRECTORY ) {
// it's directory - return error
//DBG(" File is DIR\n");
FreePool ( FileInfo ) ;
File - > Close ( File ) ;
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
}
FreePool ( FileInfo ) ;
// it's a file - delete it
//DBG(" File is file\n");
Status = File - > Delete ( File ) ;
2020-08-25 17:35:19 +02:00
//DBG(" Delete: %s\n", efiStrError(Status));
2019-09-03 11:58:42 +02:00
return Status = = EFI_SUCCESS ;
}
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
}
2020-10-03 19:02:31 +02:00
EFI_STATUS DirNextEntry ( const EFI_FILE * Directory , IN OUT EFI_FILE_INFO * * DirEntry , IN UINTN FilterMode )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
2020-10-03 19:02:31 +02:00
void * Buffer ;
2019-09-03 11:58:42 +02:00
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 ;
2020-08-15 15:47:56 +02: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 ) {
2020-03-25 19:32:44 +01:00
DBG ( " FS Driver requests bad buffer size %llu (was %llu), using %llu instead \n " , BufferSize , LastBufferSize , LastBufferSize * 2 ) ;
2019-09-03 11:58:42 +02:00
BufferSize = LastBufferSize * 2 ;
# if REFIT_DEBUG > 0
} else {
2020-03-25 19:32:44 +01:00
DBG ( " Reallocating buffer from %llu to %llu \n " , LastBufferSize , BufferSize ) ;
2019-09-03 11:58:42 +02:00
# 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-10-03 19:02:31 +02:00
void DirIterOpen ( const 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 ;
2021-09-28 10:28:45 +02:00
DirIter - > CloseDirHandle = false ;
2019-09-03 11:58:42 +02:00
} else {
2020-10-03 19:02:31 +02:00
DirIter - > LastStatus = BaseDir - > Open ( BaseDir , const_cast < EFI_FILE * * > ( & ( DirIter - > DirHandle ) ) , RelativePath , EFI_FILE_MODE_READ , 0 ) ;
2021-09-28 10:28:45 +02:00
DirIter - > CloseDirHandle = EFI_ERROR ( DirIter - > LastStatus ) ? false : true ;
2019-09-03 11:58:42 +02:00
}
DirIter - > LastFileInfo = NULL ;
}
2021-09-28 10:28:45 +02:00
XBool 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 ) )
2021-09-28 10:28:45 +02:00
return false ; // stop iteration
2019-09-03 11:58:42 +02:00
for ( ; ; ) {
DirIter - > LastStatus = DirNextEntry ( DirIter - > DirHandle , & ( DirIter - > LastFileInfo ) , FilterMode ) ;
if ( EFI_ERROR ( DirIter - > LastStatus ) )
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
if ( DirIter - > LastFileInfo = = NULL ) // end of listing
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
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 ;
2021-09-28 10:28:45 +02:00
return true ;
2019-09-03 11:58:42 +02:00
}
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
//
2021-09-28 10:28:45 +02:00
XBool
2019-09-03 11:58:42 +02:00
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
2021-09-28 10:28:45 +02:00
//return false;
return true ; //this is wrong anyway
2019-09-03 11:58:42 +02:00
}
2021-09-28 10:28:45 +02:00
return mUnicodeCollation - > MetaiMatch ( mUnicodeCollation , String , Pattern ) = = TRUE ;
2019-09-03 11:58:42 +02:00
}
EFI_STATUS
2020-10-03 19:02:31 +02:00
InitializeUnicodeCollationProtocol ( void )
2019-09-03 11:58:42 +02:00
{
EFI_STATUS Status ;
if ( mUnicodeCollation ! = NULL ) {
return EFI_SUCCESS ;
}
//
2022-08-01 21:34:35 +02:00
// BUGBUG: Proper implementation is to locate all Unicode Collation Protocol
2019-09-03 11:58:42 +02:00
// instances first and then select one which support English language.
// Current implementation just pick the first instance.
//
Status = gBS - > LocateProtocol (
2022-04-26 00:55:56 +02:00
gEfiUnicodeCollation2ProtocolGuid ,
2019-09-03 11:58:42 +02:00
NULL ,
2020-10-03 19:02:31 +02:00
( void * * ) & mUnicodeCollation
2019-09-03 11:58:42 +02:00
) ;
if ( EFI_ERROR ( Status ) ) {
Status = gBS - > LocateProtocol (
2022-04-26 00:55:56 +02:00
gEfiUnicodeCollationProtocolGuid ,
2019-09-03 11:58:42 +02:00
NULL ,
2020-10-03 19:02:31 +02:00
( void * * ) & mUnicodeCollation
2019-09-03 11:58:42 +02:00
) ;
}
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 ;
}
2020-10-03 19:02:31 +02:00
void ReplaceExtension ( IN OUT CHAR16 * Path , IN CHAR16 * Extension )
2019-09-03 11:58:42 +02:00
{
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
//
2020-10-03 19:02:31 +02: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 ;
}
2020-08-09 17:55:30 +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 .
* */
XStringW DevicePathToXStringW (
2020-09-28 17:57:50 +02:00
const EFI_DEVICE_PATH_PROTOCOL * DevPath
2020-08-09 17:55:30 +02:00
)
{
2021-09-28 10:28:45 +02:00
CHAR16 * DevicePathStr = ConvertDevicePathToText ( DevPath , true , true ) ;
2020-08-09 17:55:30 +02:00
XStringW returnValue ;
returnValue . stealValueFrom ( DevicePathStr ) ; // do not FreePool FilePath, it's now owned by returnValue
return returnValue ;
}
2019-09-03 11:58:42 +02:00
//
// Aptio UEFI returns File DevPath as 2 nodes (dir, file)
// and DevicePathToStr connects them with /, but we need '\\'
2020-09-28 17:57:50 +02:00
XStringW FileDevicePathToXStringW ( const EFI_DEVICE_PATH_PROTOCOL * DevPath )
2019-09-03 11:58:42 +02:00
{
CHAR16 * FilePath ;
CHAR16 * Char ;
2020-02-17 21:41:09 +01:00
CONST CHAR16 * Tail ;
2019-09-03 11:58:42 +02:00
2021-09-28 10:28:45 +02:00
FilePath = ConvertDevicePathToText ( DevPath , true , true ) ;
2019-09-03 11:58:42 +02:00
// 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 ;
2020-03-30 01:21:38 +02:00
while ( * Char ! = 0 ) {
2019-09-03 11:58:42 +02:00
* ( 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
}
2020-08-09 17:55:30 +02:00
XStringW returnValue ;
returnValue . stealValueFrom ( FilePath ) ; // do not FreePool FilePath, it's now owned by returnValue
return returnValue ;
2019-09-03 11:58:42 +02:00
}
2020-09-28 17:57:50 +02:00
XStringW FileDevicePathFileToXStringW ( const EFI_DEVICE_PATH_PROTOCOL * DevPath )
2019-09-03 11:58:42 +02:00
{
EFI_DEVICE_PATH_PROTOCOL * Node ;
if ( DevPath = = NULL ) {
2020-08-09 17:55:30 +02:00
return NullXStringW ;
2019-09-03 11:58:42 +02:00
}
Node = ( EFI_DEVICE_PATH_PROTOCOL * ) DevPath ;
while ( ! IsDevicePathEnd ( Node ) ) {
if ( ( Node - > Type = = MEDIA_DEVICE_PATH ) & &
( Node - > SubType = = MEDIA_FILEPATH_DP ) ) {
2020-08-09 17:55:30 +02:00
return FileDevicePathToXStringW ( Node ) ;
2019-09-03 11:58:42 +02:00
}
Node = NextDevicePathNode ( Node ) ;
}
2020-08-09 17:55:30 +02:00
return NullXStringW ;
2019-09-03 11:58:42 +02:00
}
2022-04-26 00:55:56 +02:00
XBool DumpVariable ( CHAR16 * Name , const EFI_GUID & Guid , INTN DevicePathAt )
2019-09-03 11:58:42 +02:00
{
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 ) {
2020-08-15 15:47:56 +02: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 ) ) {
2020-03-25 19:32:44 +01:00
DBG ( " Can't get %ls, size=%llu \n " , Name , dataSize ) ;
2019-09-03 11:58:42 +02:00
FreePool ( data ) ;
data = NULL ;
} else {
2020-03-25 19:32:44 +01:00
DBG ( " %ls var size=%llu \n " , Name , dataSize ) ;
2019-09-03 11:58:42 +02:00
for ( i = 0 ; i < dataSize ; i + + ) {
2020-04-17 15:14:24 +02:00
DBG ( " %02hhX " , data [ i ] ) ;
2019-09-03 11:58:42 +02:00
}
DBG ( " \n " ) ;
if ( DevicePathAt > = 0 ) {
2020-08-09 17:55:30 +02:00
DBG ( " %ls: %ls \n " , Name , FileDevicePathToXStringW ( ( EFI_DEVICE_PATH_PROTOCOL * ) & data [ DevicePathAt ] ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
}
}
}
if ( data ) {
FreePool ( data ) ;
2021-09-28 10:28:45 +02:00
return true ;
2019-09-03 11:58:42 +02:00
}
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
}
// EOF