-0.2.4 (?/??/2012):
+0.2.5 (?/??/2012):
------------------
+- Fixed bug that caused icons to drop back to generic icons when rEFInd
+ was launched in certain ways (such as from an EFI shell in rEFInd's
+ directory) on certain systems.
+
+- Fixed bug that caused "unknown disable flag" to be shown (very briefly)
+ instead of "unknown hideui flag" when an improper hideui flag was set.
+
+0.2.4 (4/5/2012):
+-----------------
+
- Created new refind.conf entry: "showtools". This entry takes options of
"shell", "gptsync", "about", "exit", "reboot", and "shutdown". This
option is in some respects an affirmative version of portions of the old
-J -r -v -x ./lost+found -o ../../refind-cd-$Version.iso \
-eltorito-alt-boot -efi-boot refind-bin-$Version.img \
-no-emul-boot ./
-
+
# Below is like above, but also creates an El Torito entry for BIOS
# booting. That's useless, but in case something flakes out without
# it, I'll preserve this version for a while....
# -eltorito-alt-boot -efi-boot refind-bin-$Version.img \
# -no-emul-boot ./
-cd ../../
-rm -r temp/
+# Create a bootable USB flash drive image, using the FAT filesystem
+# created above and a stored partition table image (plus some empty
+# sectors)....
+rm ../../refind-flashdrive-$Version.*
+cat $StartDir/flashparts.img refind-bin-$Version.img > refind-flashdrive-$Version.img
+cp $StartDir/README-flashdrive.txt ./
+cd ..
+mv refind-bin-$Version refind-flashdrive-$Version
+zip -9r ../refind-flashdrive-$Version.zip \
+ refind-flashdrive-$Version/refind-flashdrive-$Version.img \
+ refind-flashdrive-$Version/docs refind-flashdrive-$Version/LICENSE.txt \
+ refind-flashdrive-$Version/COPYING.txt \
+ refind-flashdrive-$Version/CREDITS.txt \
+ refind-flashdrive-$Version/README.txt \
+ refind-flashdrive-$Version/SHELLS.txt \
+ refind-flashdrive-$Version/README-flashdrive.txt
+mv refind-flashdrive-$Version/refind-flashdrive-$Version.img ../
+
+cd ../
+
+# Zip up the optical disc image....
+rm refind-cd-$Version.zip
+zip -9 refind-cd-$Version.zip refind-cd-$Version.iso
+
+#rm -r temp/
Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0);
if (CheckError(Status, L"while loading the configuration file"))
return Status;
-
+
FileInfo = LibFileInfo(FileHandle);
if (FileInfo == NULL) {
// TODO: print and register the error
if (ReadSize > MAXCONFIGFILESIZE)
ReadSize = MAXCONFIGFILESIZE;
FreePool(FileInfo);
-
+
File->BufferSize = (UINTN)ReadSize; // was limited to a few K before, so this is safe
File->Buffer = AllocatePool(File->BufferSize);
Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &File->BufferSize, File->Buffer);
return Status;
}
Status = refit_call1_wrapper(FileHandle->Close, FileHandle);
-
+
// setup for reading
File->Current8Ptr = (CHAR8 *)File->Buffer;
File->End8Ptr = File->Current8Ptr + File->BufferSize;
} else if (StriCmp(FlagName, L"all") == 0) {
GlobalConfig.HideUIFlags = HIDEUI_ALL;
} else {
- Print(L" unknown disable flag: '%s'\n", FlagName);
+ Print(L" unknown hideui flag: '%s'\n", FlagName);
}
}
{
if (Id >= BUILTIN_ICON_COUNT)
return NULL;
-
+
if (BuiltinIconTable[Id].Image == NULL)
BuiltinIconTable[Id].Image = LoadIcnsFallback(SelfDir, BuiltinIconTable[Id].Path, BuiltinIconTable[Id].PixelSize);
-
+
return BuiltinIconTable[Id].Image;
}
Image = egLoadIcon(SelfDir, FileName, 128);
if (Image != NULL)
return Image;
-
+
// try the fallback name with os_ instead of boot_
if (BootLogo)
return LoadOSIcon(NULL, FallbackIconName, FALSE);
-
+
return DummyImage(128);
} /* EG_IMAGE * LoadOSIcon() */
// self recognition stuff
//
+// Converts forward slashes to backslashes and removes duplicate slashes.
+// Necessary because some (buggy?) EFI implementations produce "\/" strings
+// in pathnames.
+static VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) {
+ CHAR16 *NewName;
+ UINTN i, j = 0;
+ BOOLEAN LastWasSlash = FALSE;
+
+ NewName = AllocateZeroPool(sizeof(CHAR16) * (StrLen(PathName) + 1));
+ if (NewName != NULL) {
+ for (i = 0; i < StrLen(PathName); i++) {
+ if ((PathName[i] == L'/') || (PathName[i] == L'\\')) {
+ if (!LastWasSlash)
+ NewName[j++] = L'\\';
+ LastWasSlash = TRUE;
+ } else {
+ NewName[j++] = PathName[i];
+ LastWasSlash = FALSE;
+ } // if/else
+ } // for
+ NewName[j] = 0;
+ // Copy the transformed name back....
+ StrCpy(PathName, NewName);
+ FreePool(NewName);
+ } // if allocation OK
+} // CleanUpPathNameSlashes()
+
EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle)
{
EFI_STATUS Status;
CHAR16 *DevicePathAsString;
- CHAR16 BaseDirectory[256];
UINTN i;
-
+
SelfImageHandle = ImageHandle;
Status = refit_call3_wrapper(BS->HandleProtocol, SelfImageHandle, &LoadedImageProtocol, (VOID **) &SelfLoadedImage);
if (CheckFatalError(Status, L"while getting a LoadedImageProtocol handle"))
// find the current directory
DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath);
+ CleanUpPathNameSlashes(DevicePathAsString);
if (DevicePathAsString != NULL) {
- StrCpy(BaseDirectory, DevicePathAsString);
- FreePool(DevicePathAsString);
- for (i = StrLen(BaseDirectory); i > 0 && BaseDirectory[i] != '\\'; i--) ;
- BaseDirectory[i] = 0;
+ for (i = StrLen(DevicePathAsString); (i > 0) && (DevicePathAsString[i] != '\\'); i--) ;
+ DevicePathAsString[i] = 0;
} else
- BaseDirectory[0] = 0;
- SelfDirPath = StrDuplicate(BaseDirectory);
-
+ DevicePathAsString[0] = 0;
+ SelfDirPath = StrDuplicate(DevicePathAsString);
+ FreePool(DevicePathAsString);
+
return FinishInitRefitLib();
}
}
static EFI_STATUS FinishInitRefitLib(VOID)
-{
+{
EFI_STATUS Status;
if (SelfRootDir == NULL) {
{
CHAR16 *FileName;
UINTN i;
-
+
FileName = Path;
-
+
if (Path != NULL) {
for (i = StrLen(Path); i > 0; i--) {
if (Path[i-1] == '\\' || Path[i-1] == '/') {
}
}
}
-
+
return FileName;
}
VOID ReplaceExtension(IN OUT CHAR16 *Path, IN CHAR16 *Extension)
{
UINTN i;
-
+
for (i = StrLen(Path); i >= 0; i--) {
if (Path[i] == '.') {
Path[i] = 0;
{
UINT8 *BufferPtr;
UINTN Offset;
-
+
BufferPtr = Buffer;
BufferLength -= SearchStringLength;
for (Offset = 0; Offset < BufferLength; Offset++, BufferPtr++) {
if (CompareMem(BufferPtr, SearchString, SearchStringLength) == 0)
return (INTN)Offset;
}
-
+
return -1;
}
FreePool(SmallCopy);
FreePool(BigCopy);
} // if
-
+
return (Found);
} // BOOLEAN StriSubCmp()
VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) {
UINTN Length1 = 0, Length2 = 0;
CHAR16* NewString;
-
+
if (*First != NULL)
Length1 = StrLen(*First);
if (Second != NULL)
CHAR16 *FindLastDirName(IN CHAR16 *Path) {
UINTN i, StartOfElement = 0, EndOfElement = 0, PathLength, CopyLength;
CHAR16 *Found = NULL;
-
+
PathLength = StrLen(Path);
// Find start & end of target element
for (i = 0; i < PathLength; i++) {
CHAR16 *FindNumbers(IN CHAR16 *InString) {
UINTN i, StartOfElement, EndOfElement = 0, InLength, CopyLength;
CHAR16 *Found = NULL;
-
+
InLength = StartOfElement = StrLen(InString);
// Find start & end of target element
for (i = 0; i < InLength; i++) {
{
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.4");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.4.2");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
CHAR16 ShortcutLetter = 0;
FileName = Basename(LoaderPath);
-
+
// locate a custom icon for the loader
StrCpy(IconFileName, LoaderPath);
ReplaceExtension(IconFileName, L".icns");
if (FileExists(Volume->RootDir, IconFileName)) {
Entry->me.Image = LoadIcns(Volume->RootDir, IconFileName, 128);
} // if
-
+
Temp = FindLastDirName(LoaderPath);
MergeStrings(&OSIconName, Temp, L',');
FreePool(Temp);
if (Entry->me.Image == NULL)
Entry->me.Image = LoadOSIcon(OSIconName, L"unknown", FALSE);
} // VOID SetLoaderDefaults()
-
+
// Add a specified EFI boot loader to the list, using automatic settings
// for icons, options, etc.
LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume) {
{
UINTN x, y, src_x, src_y;
EG_PIXEL *DestPtr, *SrcPtr;
-
+
if (!AllowGraphicsMode)
return;
if (SelectionImages[0] != NULL)
return;
-
+
// load small selection image
if (GlobalConfig.SelectionSmallFileName != NULL) {
SelectionImages[2] = egLoadImage(SelfDir, GlobalConfig.SelectionSmallFileName, FALSE);
ROW1_TILESIZE, ROW1_TILESIZE, &MenuBackgroundPixel);
if (SelectionImages[2] == NULL)
return;
-
+
// load big selection image
if (GlobalConfig.SelectionBigFileName != NULL) {
SelectionImages[0] = egLoadImage(SelfDir, GlobalConfig.SelectionBigFileName, FALSE);
}
if (SelectionImages[0] == NULL) {
// calculate big selection image from small one
-
+
SelectionImages[0] = egCreateImage(ROW0_TILESIZE, ROW0_TILESIZE, FALSE);
if (SelectionImages[0] == NULL) {
egFreeImage(SelectionImages[2]);
SelectionImages[2] = NULL;
return;
}
-
+
DestPtr = SelectionImages[0]->PixelData;
SrcPtr = SelectionImages[2]->PixelData;
for (y = 0; y < ROW0_TILESIZE; y++) {
src_y = (ROW1_TILESIZE >> 1);
else
src_y = y - (ROW0_TILESIZE - ROW1_TILESIZE);
-
+
for (x = 0; x < ROW0_TILESIZE; x++) {
if (x < (ROW1_TILESIZE >> 1))
src_x = x;
src_x = (ROW1_TILESIZE >> 1);
else
src_x = x - (ROW0_TILESIZE - ROW1_TILESIZE);
-
+
*DestPtr++ = SrcPtr[src_y * ROW1_TILESIZE + src_x];
}
}
}
-
+
// non-selected background images
SelectionImages[1] = egCreateFilledImage(ROW0_TILESIZE, ROW0_TILESIZE, FALSE, &MenuBackgroundPixel);
SelectionImages[3] = egCreateFilledImage(ROW1_TILESIZE, ROW1_TILESIZE, FALSE, &MenuBackgroundPixel);
break;
}
}
-
+
StyleFunc(Screen, &State, MENU_FUNCTION_CLEANUP, NULL);
-
+
if (ChosenEntry)
*ChosenEntry = Screen->Entries[State.CurrentSelection];
return MenuExit;
static UINTN MenuPosY;
static CHAR16 **DisplayStrings;
CHAR16 *TimeoutMessage;
-
+
switch (Function) {
-
+
case MENU_FUNCTION_INIT:
// vertical layout
MenuPosY = 4;
if (Screen->TimeoutSeconds > 0)
MenuHeight -= 2;
InitScroll(State, Screen->EntryCount, MenuHeight);
-
+
// determine width of the menu
MenuWidth = 20; // minimum
for (i = 0; i <= State->MaxIndex; i++) {
}
if (MenuWidth > ConWidth - 6)
MenuWidth = ConWidth - 6;
-
+
// prepare strings for display
DisplayStrings = AllocatePool(sizeof(CHAR16 *) * Screen->EntryCount);
for (i = 0; i <= State->MaxIndex; i++)
// TODO: shorten strings that are too long (PoolPrint doesn't do that...)
// TODO: use more elaborate techniques for shortening too long strings (ellipses in the middle)
// TODO: account for double-width characters
-
+
// initial painting
BeginTextScreen(Screen->Title);
if (Screen->InfoLineCount > 0) {
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, Screen->InfoLines[i]);
}
}
-
+
break;
-
+
case MENU_FUNCTION_CLEANUP:
// release temporary memory
for (i = 0; i <= State->MaxIndex; i++)
FreePool(DisplayStrings[i]);
FreePool(DisplayStrings);
break;
-
+
case MENU_FUNCTION_PAINT_ALL:
// paint the whole screen (initially and after scrolling)
for (i = 0; i <= State->MaxIndex; i++) {
else
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, L" ");
break;
-
+
case MENU_FUNCTION_PAINT_SELECTION:
// redraw selection cursor
refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 2, MenuPosY + (State->LastSelection - State->FirstVisible));
refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_CHOICE_CURRENT);
refit_call2_wrapper(ST->ConOut->OutputString, ST->ConOut, DisplayStrings[State->CurrentSelection]);
break;
-
+
case MENU_FUNCTION_PAINT_TIMEOUT:
if (ParamText[0] == 0) {
// clear message
InitSelection();
SwitchToGraphicsAndClear();
break;
-
+
case MENU_FUNCTION_CLEANUP:
FreePool(itemPosX);
break;
-
+
case MENU_FUNCTION_PAINT_ALL:
BltClearScreen(TRUE);
PaintAll(Screen, State, itemPosX, row0PosY, row1PosY, textPosY);
case MENU_FUNCTION_PAINT_SELECTION:
PaintSelection(Screen, State, itemPosX, row0PosY, row1PosY, textPosY);
break;
-
+
case MENU_FUNCTION_PAINT_TIMEOUT:
if (!(GlobalConfig.HideUIFlags & HIDEUI_FLAG_LABEL))
DrawMainMenuText(ParamText, (UGAWidth - LAYOUT_TEXT_WIDTH) >> 1, textPosY + TEXT_LINE_HEIGHT);
break;
-
+
}
}