CloverBootloader/rEFIt_UEFI/Settings/Self.cpp
2021-09-28 16:54:31 +03:00

282 lines
11 KiB
C++

/*
* Self.cpp
*
* Created on: Sep 28, 2020
* Author: jief
*/
#include <Platform.h>
#include "../Settings/Self.h"
#include "../refit/lib.h"
#ifndef DEBUG_ALL
#define DEBUG_SELF 1
#else
#define DEBUG_SELF DEBUG_ALL
#endif
#if DEBUG_SELF == 0
#define DBG(...)
#else
#define DBG(...) DebugLog(DEBUG_SELF, __VA_ARGS__)
#endif
EFI_STATUS Self::__initialize(XBool debugMsg, EFI_HANDLE SelfImageHandle, EFI_LOADED_IMAGE** SelfLoadedImagePtr, EFI_SIMPLE_FILE_SYSTEM_PROTOCOL** SelfSimpleVolumePtr, EFI_FILE** SelfVolumeRootDirPtr, XStringW* CloverDirFullPathPtr, XStringW* efiFileNamePtr, EFI_FILE** CloverDirPtr)
{
EFI_STATUS Status;
Status = gBS->HandleProtocol(SelfImageHandle, &gEfiLoadedImageProtocolGuid, (void **)SelfLoadedImagePtr);
if ( EFI_ERROR(Status) ) {
*SelfLoadedImagePtr = NULL;
return RETURN_LOAD_ERROR;
}
EFI_LOADED_IMAGE* SelfLoadedImage = *SelfLoadedImagePtr;
if ( SelfLoadedImage->DeviceHandle == NULL ) {
*SelfLoadedImagePtr = NULL;
return RETURN_LOAD_ERROR;
}
Status = gBS->HandleProtocol(SelfLoadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (void**)SelfSimpleVolumePtr);
if ( EFI_ERROR(Status) ) {
*SelfSimpleVolumePtr = NULL;
return RETURN_LOAD_ERROR;
}
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* SelfSimpleVolume = *SelfSimpleVolumePtr;
Status = SelfSimpleVolume->OpenVolume(SelfSimpleVolume, SelfVolumeRootDirPtr);
if ( EFI_ERROR(Status) ) {
*SelfVolumeRootDirPtr = NULL;
return RETURN_LOAD_ERROR;
}
EFI_FILE* SelfVolumeRootDir = *SelfVolumeRootDirPtr;
#ifdef JIEF_DEBUG
if ( debugMsg ) DBG("SelfVolumeRootDir = %lld\n", uintptr_t(SelfVolumeRootDir));
#endif
// find the current directory
*CloverDirFullPathPtr = FileDevicePathToXStringW(SelfLoadedImage->FilePath);
if ( CloverDirFullPathPtr->isEmpty() ) {
return RETURN_LOAD_ERROR;
}
XStringW& CloverDirFullPath = *CloverDirFullPathPtr;
// Do this before the next check.
if ( !CloverDirFullPath.startWith('\\') ) {
// Some firmware seems to not put a '\' at the begining. Do not panic anymore, just add it.
CloverDirFullPath.insertAtPos('\\', 0);
}
*efiFileNamePtr = CloverDirFullPath.basename();
#ifdef JIEF_DEBUG
if ( debugMsg ) {
XStringW& efiFileName = *efiFileNamePtr;
DBG("efiFileName=%ls\n", efiFileName.wc_str());
}
#endif
// History : if this Clover was started as BootX64.efi, redirect to /EFI/CLOVER
if ( CloverDirFullPath.isEqualIC("\\EFI\\Boot\\BootX64.efi") ) { // keep getCloverDir() in sync !
CloverDirFullPath.takeValueFrom("\\EFI\\CLOVER\\CloverX64.efi"); // keep getCloverDir() in sync !
}
if ( CloverDirFullPath.lastChar() == U'\\' ) { // keep getCloverDir() in sync !
log_technical_bug("CloverDirFullPath.lastChar() == U'\\'"); // Just to see if that happens.
CloverDirFullPath.deleteCharsAtPos(CloverDirFullPath.length()-1, 1);
}
size_t i = CloverDirFullPath.rindexOf(U'\\', SIZE_T_MAX-1); // keep getCloverDir() in sync !
if ( i != SIZE_T_MAX && i > 0 ) CloverDirFullPath.deleteCharsAtPos(i, SIZE_T_MAX); // keep getCloverDir() in sync !
#ifdef JIEF_DEBUG
if ( debugMsg ) {
DBG("SelfDirPath = %ls\n", CloverDirFullPath.wc_str());
}
#endif
Status = SelfVolumeRootDir->Open(SelfVolumeRootDir, CloverDirPtr, CloverDirFullPath.wc_str(), EFI_FILE_MODE_READ, 0);
if ( EFI_ERROR(Status) ) {
*CloverDirPtr = NULL;
return RETURN_LOAD_ERROR;
}
#ifdef JIEF_DEBUG
if ( debugMsg ) {
EFI_FILE* CloverDir = *CloverDirPtr;
DBG("CloverDir = %lld\n", uintptr_t(CloverDir));
}
#endif
return EFI_SUCCESS;
}
const EFI_FILE_PROTOCOL* Self::getCloverDirAndEfiFileName(EFI_HANDLE ImageHandle, XStringW* efiFileName)
{
EFI_LOADED_IMAGE* SelfLoadedImage; // this efi.
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* SelfSimpleVolume; // Volume containing this efi.
EFI_FILE* SelfVolumeRootDir; // Root dir of the volume containing this efi.
XStringW CloverDirFullPath; // full path of folder containing this efi.
EFI_FILE* CloverDir; // opened folder containing this efi
/*EFI_STATUS Status = */__initialize(false, ImageHandle, &SelfLoadedImage, &SelfSimpleVolume, &SelfVolumeRootDir, &CloverDirFullPath, efiFileName, &CloverDir);
if ( efiFileName->isEmpty() ) {
if ( CloverDir != NULL ) CloverDir->Close(CloverDir);
return NULL;
}
return CloverDir;
}
Self self;
constexpr const LStringW THEMES_DIRNAME = L"Themes"_XSW;
EFI_STATUS Self::_openDir(const XStringW& path, XBool* b, EFI_FILE** efiDir)
{
EFI_STATUS Status;
Status = m_CloverDir->Open(m_CloverDir, efiDir, path.wc_str(), EFI_FILE_MODE_READ, 0);
if ( EFI_ERROR(Status) ) {
DBG("Error when opening dir '%ls\\%ls' : %s\n", m_CloverDirFullPath.wc_str(), path.wc_str(), efiStrError(Status));
*efiDir = NULL;
*b = false;
}else{
*b = true;
}
return Status;
}
EFI_STATUS Self::_initialize()
{
// EFI_STATUS Status;
/*Status = */__initialize(true, m_SelfImageHandle, &m_SelfLoadedImage, &m_SelfSimpleVolume, &m_SelfVolumeRootDir, &m_CloverDirFullPath, &m_efiFileName, &m_CloverDir);
if ( m_SelfLoadedImage == NULL ) log_technical_bug("Cannot get SelfLoadedImage");
if ( m_SelfLoadedImage->DeviceHandle == NULL ) log_technical_bug("m_SelfLoadedImage->DeviceHandle == NULL");
if ( m_SelfSimpleVolume == NULL ) log_technical_bug("Cannot get m_SelfSimpleVolume");
if ( m_SelfVolumeRootDir == NULL ) log_technical_bug("Cannot get m_SelfVolumeRootDir");
if ( m_CloverDirFullPath.isEmpty() ) log_technical_bug("Cannot get m_CloverDirFullPath");
m_CloverDirFullPath4Display = m_CloverDirFullPath;
m_CloverDirFullPath4Display.replaceAll('\\', '/');
if ( m_efiFileName.isEmpty() ) log_technical_bug("Cannot get m_efiFileName");
if ( m_CloverDir == NULL ) panic("Cannot open getSelfRootDir()"); // We have to panic, nothing would work without m_CloverDir
m_SelfDevicePath = NULL;
if ( m_SelfLoadedImage && m_SelfLoadedImage->DeviceHandle ) {
m_SelfDevicePath = FileDevicePath(m_SelfLoadedImage->DeviceHandle, m_CloverDirFullPath + '\\' + m_efiFileName);
}
if ( m_SelfDevicePath == NULL ) {
log_technical_bug("m_SelfDevicePath == NULL"); // not sure what can work without m_SelfDevicePath
}else{
#ifdef JIEF_DEBUG
DBG("Self DevicePath()=%ls @%llX\n", FileDevicePathToXStringW(m_SelfDevicePath).wc_str(), (uintptr_t)m_SelfLoadedImage->DeviceHandle);
#endif
}
// m_SelfDevicePathAsXStringW = FileDevicePathToXStringW(m_SelfDevicePath);
_openDir(THEMES_DIRNAME, &m_ThemesDirExists, &m_ThemesDir); // don't need to check returned status as it's ok to not have a themes dir.
return EFI_SUCCESS;
//
//
// Status = gBS->HandleProtocol(m_SelfImageHandle, &gEfiLoadedImageProtocolGuid, (void **)&m_SelfLoadedImage);
// if ( EFI_ERROR(Status) ) panic("Cannot get SelfLoadedImage"); // We have to panic, nothing would work without m_CloverDir, and m_SelfImageHandle is needed to get it
// if ( m_SelfLoadedImage->DeviceHandle == NULL ) panic("m_SelfLoadedImage->DeviceHandle == NULL"); // We have to panic, nothing would work without m_CloverDir, and m_SelfLoadedImage->DeviceHandle is needed to get it
// m_SelfDevicePath = DuplicateDevicePath(DevicePathFromHandle(m_SelfLoadedImage->DeviceHandle));
// if ( m_SelfDevicePath == NULL ) {
// log_technical_bug("m_SelfDevicePath == NULL"); // not sure what can work without m_SelfDevicePath
// }
//
//#ifdef JIEF_DEBUG
// DBG("Self DevicePath()=%ls @%llX\n", FileDevicePathToXStringW(m_SelfDevicePath).wc_str(), (uintptr_t)m_SelfLoadedImage->DeviceHandle);
//#endif
//
// Status = gBS->HandleProtocol(m_SelfLoadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (void**)&m_SelfSimpleVolume);
// if ( EFI_ERROR(Status) ) panic("Cannot get m_SelfSimpleVolume"); // We have to panic, nothing would work without m_CloverDir, and m_SelfSimpleVolume is needed to get it
// Status = m_SelfSimpleVolume->OpenVolume(m_SelfSimpleVolume, &m_SelfVolumeRootDir);
// if ( EFI_ERROR(Status) ) panic("Cannot get m_SelfVolumeRootDir"); // We have to panic, nothing would work without m_CloverDir, and m_SelfVolumeRootDir is needed to get it
//
//#ifdef JIEF_DEBUG
// DBG("m_SelfVolumeRootDir = %lld\n", uintptr_t(m_SelfVolumeRootDir));
//#endif
//
// // find the current directory
// m_CloverDirFullPath = FileDevicePathToXStringW(m_SelfLoadedImage->FilePath);
//
// // Do this before the next check.
// if ( !m_CloverDirFullPath.startWith('\\') ) {
// //CHAR16* f = ConvertDevicePathToText(m_SelfLoadedImage->FilePath, true, true);
// //panic("Bad format for m_CloverDirFullPath(%ls). It must start with a '\\'.\nConvertDevicePathToText=%ls", m_CloverDirFullPath.wc_str(), f);
// //
// // Some firmware seems to not put a '\' at the begining. Do not panic anymore, just add it.
// m_CloverDirFullPath.insertAtPos('\\', 0);
// }
//
// m_efiFileName = m_CloverDirFullPath.basename();
//#ifdef JIEF_DEBUG
// DBG("m_efiFileName=%ls\n", m_efiFileName.wc_str());
//#endif
//
// // Code to find m_CloverDirFullPath is duplicated in BootLog.cpp in case USE_SELF_INSTANCE is not defined
//
// // History : if this Clover was started as BootX64.efi, redirect to /EFI/CLOVER
// if ( m_CloverDirFullPath.isEqualIC("\\EFI\\Boot\\BootX64.efi") ) { // keep getCloverDir() in sync !
// m_CloverDirFullPath.takeValueFrom("\\EFI\\CLOVER\\CloverX64.efi"); // keep getCloverDir() in sync !
// }
// if ( m_CloverDirFullPath.isEmpty() ) log_technical_bug("m_CloverDirFullPath.isEmpty()");
// m_SelfDevicePath = FileDevicePath(m_SelfLoadedImage->DeviceHandle, m_CloverDirFullPath);
//// m_SelfDevicePathAsXStringW = FileDevicePathToXStringW(m_SelfDevicePath);
//
// if ( m_CloverDirFullPath.lastChar() == U'\\' ) { // keep getCloverDir() in sync !
// log_technical_bug("m_CloverDirFullPath.lastChar() == U'\\'"); // Just to see if that happens.
// m_CloverDirFullPath.deleteCharsAtPos(m_CloverDirFullPath.length()-1, 1);
// }
//
// size_t i = m_CloverDirFullPath.rindexOf(U'\\', SIZE_T_MAX-1); // keep getCloverDir() in sync !
// if ( i != SIZE_T_MAX && i > 0 ) m_CloverDirFullPath.deleteCharsAtPos(i, SIZE_T_MAX); // keep getCloverDir() in sync !
//
//#ifdef JIEF_DEBUG
// DBG("SelfDirPath = %ls\n", m_CloverDirFullPath.wc_str());
//#endif
// Status = m_SelfVolumeRootDir->Open(m_SelfVolumeRootDir, &m_CloverDir, m_CloverDirFullPath.wc_str(), EFI_FILE_MODE_READ, 0);
// if ( EFI_ERROR(Status) ) panic("Cannot open getSelfRootDir()"); // We have to panic, nothing would work without m_CloverDir
//#ifdef JIEF_DEBUG
// DBG("m_CloverDir = %lld\n", uintptr_t(m_CloverDir));
//#endif
//
//
// _openDir(THEMES_DIRNAME, &m_ThemesDirExists, &m_ThemesDir); // don't need to check returned status as it's ok to not have a themes dir.
//
// return EFI_SUCCESS;
}
EFI_STATUS Self::initialize(EFI_HANDLE ImageHandle)
{
m_SelfImageHandle = ImageHandle;
return _initialize();
}
EFI_STATUS Self::reInitialize()
{
closeHandle();
return _initialize();
}
void Self::closeHandle(void)
{
// called before running external programs to close open file handles
if (m_CloverDir != NULL) {
m_CloverDir->Close(m_CloverDir);
m_CloverDir = NULL;
}
if (m_SelfVolumeRootDir != NULL) {
m_SelfVolumeRootDir->Close(m_SelfVolumeRootDir);
m_SelfVolumeRootDir = NULL;
}
}