* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
- * Modifications copyright (c) 2012-2015 Roderick W. Smith
+ * Modifications copyright (c) 2012-2016 Roderick W. Smith
*
* Modifications distributed under the terms of the GNU General Public
* License (GPL) version 3 (GPLv3), or (at your option) any later version.
#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_x64.efi"
#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi"
#define MEMTEST_NAMES L"memtest86.efi,memtest86_x64.efi,memtest86x64.efi,bootx64.efi"
-#define DRIVER_DIRS L"drivers,drivers_x64"
#define FALLBACK_FULLNAME L"EFI\\BOOT\\bootx64.efi"
#define FALLBACK_BASENAME L"bootx64.efi"
#define EFI_STUB_ARCH 0x8664
#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_ia32.efi"
#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi"
#define MEMTEST_NAMES L"memtest86.efi,memtest86_ia32.efi,memtest86ia32.efi,bootia32.efi"
-#define DRIVER_DIRS L"drivers,drivers_ia32"
#define FALLBACK_FULLNAME L"EFI\\BOOT\\bootia32.efi"
#define FALLBACK_BASENAME L"bootia32.efi"
#define EFI_STUB_ARCH 0x014c
EFI_GUID gFreedesktopRootGuid = { 0x44479540, 0xf297, 0x41b2, { 0x9a, 0xf7, 0xd1, 0x31, 0xd5, 0xf0, 0x45, 0x8a }};
+#elif defined (EFIAARCH64)
+#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellaa64.efi,\\shell.efi,\\shellaa64.efi"
+#define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi,\\EFI\\tools\\gptsync_aa64.efi"
+#define GDISK_NAMES L"\\EFI\\tools\\gdisk.efi,\\EFI\\tools\\gdisk_aa64.efi"
+#define NETBOOT_NAMES L"\\EFI\\tools\\ipxe.efi"
+#define MEMTEST_NAMES L"memtest86.efi,memtest86_aa64.efi,memtest86aa64.efi,bootaa64.efi"
+#define FALLBACK_FULLNAME L"EFI\\BOOT\\bootaa64.efi"
+#define FALLBACK_BASENAME L"bootaa64.efi"
+#define EFI_STUB_ARCH 0xaa64
+EFI_GUID gFreedesktopRootGuid = { 0xb921b045, 0x1df0, 0x41c3, { 0xaf, 0x44, 0x4c, 0x6f, 0x28, 0x0d, 0x3f, 0xae }};
#else
#define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shell.efi"
#define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi"
#define DRIVER_DIRS L"drivers"
#define FALLBACK_FULLNAME L"EFI\\BOOT\\boot.efi" /* Not really correct */
#define FALLBACK_BASENAME L"boot.efi" /* Not really correct */
-// Below is GUID for ARM64
-EFI_GUID gFreedesktopRootGuid = { 0xb921b045, 0x1df0, 0x41c3, { 0xaf, 0x44, 0x4c, 0x6f, 0x28, 0x0d, 0x3f, 0xae }};
+// Below is GUID for ARM32
+EFI_GUID gFreedesktopRootGuid = { 0x69dad710, 0x2ce4, 0x4e3c, { 0xb1, 0x6c, 0x21, 0xa1, 0xd4, 0x9a, 0xbe, 0xd3 }};
#endif
#define FAT_ARCH 0x0ef1fab9 /* ID for Apple "fat" binary */
#define IPXE_DISCOVER_NAME L"\\efi\\tools\\ipxe_discover.efi"
#define IPXE_NAME L"\\efi\\tools\\ipxe.efi"
-// Filename patterns that identify EFI boot loaders. Note that a single case (either L"*.efi" or
-// L"*.EFI") is fine for most systems; but Gigabyte's buggy Hybrid EFI does a case-sensitive
-// comparison when it should do a case-insensitive comparison, so I'm doubling this up. It does
-// no harm on other computers, AFAIK. In theory, every case variation should be done for
-// completeness, but that's ridiculous....
-#define LOADER_MATCH_PATTERNS L"*.efi,*.EFI"
-
// Patterns that identify Linux kernels. Added to the loader match pattern when the
// scan_all_linux_kernels option is set in the configuration file. Causes kernels WITHOUT
// a ".efi" extension to be found when scanning for boot loaders.
-#define LINUX_MATCH_PATTERNS L"vmlinuz*,bzImage*"
+#define LINUX_MATCH_PATTERNS L"vmlinuz*,bzImage*,kernel*"
// Maximum length of a text string in certain menus
#define MAX_LINE_LENGTH 65
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.10.0.1");
+ AddMenuInfoLine(&AboutMenu, PoolPrint(L"rEFInd Version %s", REFIND_VERSION));
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
- AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2015 Roderick W. Smith");
+ AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2016 Roderick W. Smith");
AddMenuInfoLine(&AboutMenu, L"Portions Copyright (c) Intel Corporation and others");
AddMenuInfoLine(&AboutMenu, L"Distributed under the terms of the GNU GPLv3 license");
AddMenuInfoLine(&AboutMenu, L"");
#elif defined(EFIX64)
AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: x86_64 (64 bit); Secure Boot %s",
secure_mode() ? L"active" : L"inactive"));
+#elif defined(EFIAARCH64)
+ AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: ARM (64 bit); Secure Boot %s",
+ secure_mode() ? L"active" : L"inactive"));
#else
AddMenuInfoLine(&AboutMenu, L" Platform: unknown");
#endif
// Returns TRUE if this file is a valid EFI loader file, and is proper ARCH
static BOOLEAN IsValidLoader(EFI_FILE *RootDir, CHAR16 *FileName) {
BOOLEAN IsValid = TRUE;
-#if defined (EFIX64) | defined (EFI32)
+#if defined (EFIX64) | defined (EFI32) | defined (EFIAARCH64)
EFI_STATUS Status;
EFI_FILE_HANDLE FileHandle;
CHAR8 Header[512];
if (ErrorInStep != NULL)
*ErrorInStep = 3;
}
+ if (IsDriver) {
+ // Below should have no effect on most systems, but works
+ // around bug with some EFIs that prevents filesystem drivers
+ // from binding to partitions.
+ ConnectFilesystemDriver(ChildImageHandle);
+ }
// re-open file handles
ReinitRefitLib();
return ReturnStatus;
} /* EFI_STATUS StartEFIImageList() */
-static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath,
- IN CHAR16 *LoadOptions, IN UINTN LoaderType,
- IN CHAR16 *ImageTitle, IN CHAR8 OSType,
- OUT UINTN *ErrorInStep,
- IN BOOLEAN Verbose,
- IN BOOLEAN IsDriver
- )
+EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath,
+ IN CHAR16 *LoadOptions, IN UINTN LoaderType,
+ IN CHAR16 *ImageTitle, IN CHAR8 OSType,
+ OUT UINTN *ErrorInStep,
+ IN BOOLEAN Verbose,
+ IN BOOLEAN IsDriver)
{
EFI_DEVICE_PATH *DevicePaths[2];
// for information on Intel VMX features
static VOID DoEnableAndLockVMX(VOID)
{
+#if defined (EFIX64) | defined (EFI32)
UINT32 msr = 0x3a;
UINT32 low_bits = 0, high_bits = 0;
low_bits = 0x05;
msr = 0x3a;
__asm__ volatile ("wrmsr" : : "c" (msr), "a" (low_bits), "d" (high_bits));
- }
+ }
+#endif
} // VOID DoEnableAndLockVMX()
static VOID StartLoader(LOADER_ENTRY *Entry, CHAR16 *SelectionName)
} // if/else network boot
// detect specific loaders
- if (StriSubCmp(L"bzImage", NameClues) || StriSubCmp(L"vmlinuz", NameClues)) {
+ if (StriSubCmp(L"bzImage", NameClues) || StriSubCmp(L"vmlinuz", NameClues) || StriSubCmp(L"kernel", NameClues)) {
if (Volume->DiskKind != DISK_KIND_NET) {
GuessLinuxDistribution(&OSIconName, Volume, LoaderPath);
Entry->LoadOptions = GetMainLinuxOptions(LoaderPath, Volume);
return 0;
} // INTN TimeComp()
-// Adds a loader list element, keeping it sorted by date. Returns the new
-// first element (the one with the most recent date).
+// Adds a loader list element, keeping it sorted by date. EXCEPTION: Fedora's rescue
+// kernel, which begins with "vmlinuz-0-rescue," should not be at the top of the list,
+// since that will make it the default if kernel folding is enabled, so float it to
+// the end.
+// Returns the new first element (the one with the most recent date).
static struct LOADER_LIST * AddLoaderListEntry(struct LOADER_LIST *LoaderList, struct LOADER_LIST *NewEntry) {
struct LOADER_LIST *LatestEntry, *CurrentEntry, *PrevEntry = NULL;
+ BOOLEAN LinuxRescue = FALSE;
LatestEntry = CurrentEntry = LoaderList;
if (LoaderList == NULL) {
LatestEntry = NewEntry;
} else {
- while ((CurrentEntry != NULL) && (TimeComp(&(NewEntry->TimeStamp), &(CurrentEntry->TimeStamp)) < 0)) {
+ if (StriSubCmp(L"vmlinuz-0-rescue", NewEntry->FileName))
+ LinuxRescue = TRUE;
+ while ((CurrentEntry != NULL) && (LinuxRescue || (TimeComp(&(NewEntry->TimeStamp), &(CurrentEntry->TimeStamp)) < 0))) {
PrevEntry = CurrentEntry;
CurrentEntry = CurrentEntry->NextEntry;
} // while
MyStriCmp(Extension, L".icns") ||
MyStriCmp(Extension, L".png") ||
(MyStriCmp(DirEntry->FileName, FALLBACK_BASENAME) && (MyStriCmp(Path, L"EFI\\BOOT"))) ||
- StriSubCmp(L"shell", DirEntry->FileName) ||
+ FilenameIn(Volume, Path, DirEntry->FileName, SHELL_NAMES) ||
IsSymbolicLink(Volume, Path, DirEntry) || /* is symbolic link */
HasSignedCounterpart(Volume, Path, DirEntry->FileName) || /* a file with same name plus ".efi.signed" is present */
- FilenameIn(Volume, Path, DirEntry->FileName, GlobalConfig.DontScanFiles))
+ FilenameIn(Volume, Path, DirEntry->FileName, GlobalConfig.DontScanFiles)) {
continue; // skip this
+ }
if (Path)
SPrint(FileName, 255, L"\\%s\\%s", Path, DirEntry->FileName);
NewLoader = LoaderList;
while (NewLoader != NULL) {
- IsLinux = (StriSubCmp(L"bzImage", NewLoader->FileName) || StriSubCmp(L"vmlinuz", NewLoader->FileName));
+ IsLinux = (StriSubCmp(L"bzImage", NewLoader->FileName) ||
+ StriSubCmp(L"vmlinuz", NewLoader->FileName) ||
+ StriSubCmp(L"kernel", NewLoader->FileName));
if ((FirstKernel != NULL) && IsLinux && GlobalConfig.FoldLinuxKernels) {
AddKernelToSubmenu(FirstKernel, NewLoader->FileName, Volume);
} else {
return Entry;
} /* static LOADER_ENTRY * AddToolEntry() */
-//
-// pre-boot driver functions
-//
-
-static UINTN ScanDriverDir(IN CHAR16 *Path)
-{
- EFI_STATUS Status;
- REFIT_DIR_ITER DirIter;
- UINTN NumFound = 0;
- EFI_FILE_INFO *DirEntry;
- CHAR16 FileName[256];
-
- CleanUpPathNameSlashes(Path);
- // look through contents of the directory
- DirIterOpen(SelfRootDir, Path, &DirIter);
- while (DirIterNext(&DirIter, 2, LOADER_MATCH_PATTERNS, &DirEntry)) {
- if (DirEntry->FileName[0] == '.')
- continue; // skip this
-
- SPrint(FileName, 255, L"%s\\%s", Path, DirEntry->FileName);
- NumFound++;
- Status = StartEFIImage(FileDevicePath(SelfLoadedImage->DeviceHandle, FileName),
- L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE);
- }
- Status = DirIterClose(&DirIter);
- if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) {
- SPrint(FileName, 255, L"while scanning the %s directory", Path);
- CheckError(Status, FileName);
- }
- return (NumFound);
-}
-
-#ifdef __MAKEWITH_GNUEFI
-static EFI_STATUS ConnectAllDriversToAllControllers(VOID)
-{
- EFI_STATUS Status;
- UINTN AllHandleCount;
- EFI_HANDLE *AllHandleBuffer;
- UINTN Index;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINT32 *HandleType;
- UINTN HandleIndex;
- BOOLEAN Parent;
- BOOLEAN Device;
-
- Status = LibLocateHandle(AllHandles,
- NULL,
- NULL,
- &AllHandleCount,
- &AllHandleBuffer);
- if (EFI_ERROR(Status))
- return Status;
-
- for (Index = 0; Index < AllHandleCount; Index++) {
- //
- // Scan the handle database
- //
- Status = LibScanHandleDatabase(NULL,
- NULL,
- AllHandleBuffer[Index],
- NULL,
- &HandleCount,
- &HandleBuffer,
- &HandleType);
- if (EFI_ERROR (Status))
- goto Done;
-
- Device = TRUE;
- if (HandleType[Index] & EFI_HANDLE_TYPE_DRIVER_BINDING_HANDLE)
- Device = FALSE;
- if (HandleType[Index] & EFI_HANDLE_TYPE_IMAGE_HANDLE)
- Device = FALSE;
-
- if (Device) {
- Parent = FALSE;
- for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
- if (HandleType[HandleIndex] & EFI_HANDLE_TYPE_PARENT_HANDLE)
- Parent = TRUE;
- } // for
-
- if (!Parent) {
- if (HandleType[Index] & EFI_HANDLE_TYPE_DEVICE_HANDLE) {
- Status = refit_call4_wrapper(BS->ConnectController,
- AllHandleBuffer[Index],
- NULL,
- NULL,
- TRUE);
- }
- }
- }
-
- MyFreePool (HandleBuffer);
- MyFreePool (HandleType);
- }
-
-Done:
- MyFreePool (AllHandleBuffer);
- return Status;
-} /* EFI_STATUS ConnectAllDriversToAllControllers() */
-#else
-static EFI_STATUS ConnectAllDriversToAllControllers(VOID) {
- BdsLibConnectAllDriversToAllControllers();
- return 0;
-}
-#endif
-
-// Load all EFI drivers from rEFInd's "drivers" subdirectory and from the
-// directories specified by the user in the "scan_driver_dirs" configuration
-// file line.
-static VOID LoadDrivers(VOID)
-{
- CHAR16 *Directory, *SelfDirectory;
- UINTN i = 0, Length, NumFound = 0;
-
- // load drivers from the subdirectories of rEFInd's home directory specified
- // in the DRIVER_DIRS constant.
- while ((Directory = FindCommaDelimited(DRIVER_DIRS, i++)) != NULL) {
- SelfDirectory = SelfDirPath ? StrDuplicate(SelfDirPath) : NULL;
- CleanUpPathNameSlashes(SelfDirectory);
- MergeStrings(&SelfDirectory, Directory, L'\\');
- NumFound += ScanDriverDir(SelfDirectory);
- MyFreePool(Directory);
- MyFreePool(SelfDirectory);
- }
-
- // Scan additional user-specified driver directories....
- i = 0;
- while ((Directory = FindCommaDelimited(GlobalConfig.DriverDirs, i++)) != NULL) {
- CleanUpPathNameSlashes(Directory);
- Length = StrLen(Directory);
- if (Length > 0) {
- NumFound += ScanDriverDir(Directory);
- } // if
- MyFreePool(Directory);
- } // while
-
- // connect all devices
- if (NumFound > 0) {
- ConnectAllDriversToAllControllers();
- }
-} /* static VOID LoadDrivers() */
-
// Locates boot loaders. NOTE: This assumes that GlobalConfig.LegacyType is set correctly.
static VOID ScanForBootloaders(VOID) {
UINTN i;
FreeList((VOID ***) &(MainMenu.Entries), &MainMenu.EntryCount);
MainMenu.Entries = NULL;
MainMenu.EntryCount = 0;
- ReadConfig(GlobalConfig.ConfigFilename);
ConnectAllDriversToAllControllers();
ScanVolumes();
+ ReadConfig(GlobalConfig.ConfigFilename);
+ SetVolumeIcons();
ScanForBootloaders();
ScanForTools();
SetupScreen();
if (GlobalConfig.LegacyType == LEGACY_TYPE_MAC)
CopyMem(GlobalConfig.ScanFor, "ihebocm ", NUM_SCAN_OPTIONS);
SetConfigFilename(ImageHandle);
+ MokProtocol = SecureBootSetup();
+ LoadDrivers();
+ ScanVolumes(); // Do before ReadConfig() because it needs SelfVolume->VolName
ReadConfig(GlobalConfig.ConfigFilename);
+ SetVolumeIcons();
if (GlobalConfig.SpoofOSXVersion && GlobalConfig.SpoofOSXVersion[0] != L'\0')
SetAppleOSInfo();
refit_call4_wrapper(BS->SetWatchdogTimer, 0x0000, 0x0000, 0x0000, NULL);
// further bootstrap (now with config available)
- MokProtocol = SecureBootSetup();
- LoadDrivers();
- ScanVolumes();
ScanForBootloaders();
ScanForTools();
SetupScreen();