/** Function opens and returns a file handle to the root directory of a volume. @param DeviceHandle A handle for a device @return A valid file handle or NULL is returned **/ EFI_FILE_HANDLE EfiLibOpenRoot ( IN EFI_HANDLE DeviceHandle ) { EFI_STATUS Status; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_HANDLE File; File = NULL; // // File the file system interface to the device // Status = refit_call3_wrapper(gBS->HandleProtocol, DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **) &Volume ); // // Open the root directory of the volume // if (!EFI_ERROR (Status)) { Status = Volume->OpenVolume ( Volume, &File ); } // // Done // return EFI_ERROR (Status) ? NULL : File; }
VOID EndlessIdleLoop(VOID) { UINTN index; for (;;) { ReadAllKeyStrokes(); refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &index); } }
VOID egScreenShot(VOID) { EFI_STATUS Status; EG_IMAGE *Image; UINT8 *FileData; UINTN FileDataLength; UINTN Index; if (!egHasGraphics) return; // allocate a buffer for the whole screen Image = egCreateImage(egScreenWidth, egScreenHeight, FALSE); if (Image == NULL) { Print(L"Error egCreateImage returned NULL\n"); goto bailout_wait; } // get full screen image if (GraphicsOutput != NULL) { refit_call10_wrapper(GraphicsOutput->Blt, GraphicsOutput, (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)Image->PixelData, EfiBltVideoToBltBuffer, 0, 0, 0, 0, Image->Width, Image->Height, 0); } else if (UgaDraw != NULL) { refit_call10_wrapper(UgaDraw->Blt, UgaDraw, (EFI_UGA_PIXEL *)Image->PixelData, EfiUgaVideoToBltBuffer, 0, 0, 0, 0, Image->Width, Image->Height, 0); } // encode as BMP egEncodeBMP(Image, &FileData, &FileDataLength); egFreeImage(Image); if (FileData == NULL) { Print(L"Error egEncodeBMP returned NULL\n"); goto bailout_wait; } // save to file on the ESP Status = egSaveFile(NULL, L"screenshot.bmp", FileData, FileDataLength); FreePool(FileData); if (EFI_ERROR(Status)) { Print(L"Error egSaveFile: %x\n", Status); goto bailout_wait; } return; // DEBUG: switch to text mode bailout_wait: egSetGraphicsModeEnabled(FALSE); refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &Index); }
// The following is based on the grub_linuxefi_secure_validate() function in Fedora's // version of GRUB 2. // Returns TRUE if the specified data is validated by Shim's MOK, FALSE otherwise BOOLEAN ShimValidate (VOID *data, UINT32 size) { SHIM_LOCK *shim_lock; EFI_GUID ShimLockGuid = SHIM_LOCK_GUID; if ((data != NULL) && (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS)) { if (!shim_lock) return FALSE; if (shim_lock->shim_verify(data, size) == EFI_SUCCESS) return TRUE; } return FALSE; } // BOOLEAN ShimValidate()
static VOID DrawScreenHeader(IN CHAR16 *Title) { UINTN y; // clear to black background egClearScreen(&DarkBackgroundPixel); // first clear in graphics mode refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); refit_call1_wrapper(ST->ConOut->ClearScreen, ST->ConOut); // then clear in text mode // paint header background refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BANNER); for (y = 0; y < 3; y++) { refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, y); Print(BlankLine); } // print header text refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 3, 1); Print(L"rEFInd - %s", Title); // reposition cursor refit_call2_wrapper(ST->ConOut->SetAttribute, ST->ConOut, ATTR_BASIC); refit_call3_wrapper(ST->ConOut->SetCursorPosition, ST->ConOut, 0, 4); }
/** Find the first instance of this Protocol in the system and return it's interface. @param ProtocolGuid Provides the protocol to search for @param Interface On return, a pointer to the first interface that matches ProtocolGuid @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid **/ EFI_STATUS EfiLibLocateProtocol ( IN EFI_GUID *ProtocolGuid, OUT VOID **Interface ) { EFI_STATUS Status; Status = refit_call3_wrapper(gBS->LocateProtocol, ProtocolGuid, NULL, (VOID **) Interface ); return Status; }
static int scan_disks(int (*hook)(struct fsw_volume *, struct fsw_volume *), struct fsw_volume *master) { EFI_STATUS Status; EFI_HANDLE *Handles; UINTN HandleCount = 0; UINTN i; UINTN scanned = 0; // Driver hangs if compiled with GNU-EFI unless there's a Print() statement somewhere. // I'm still trying to track that down; in the meantime, work around it.... #if defined(__MAKEWITH_GNUEFI) Print(L" "); #endif DPRINT(L"Scanning disks\n"); Status = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &HandleCount, &Handles); if (Status == EFI_NOT_FOUND) return -1; // no filesystems. strange, but true... for (i = 0; i < HandleCount; i++) { EFI_DISK_IO *diskio; EFI_BLOCK_IO *blockio; Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &gEfiDiskIoProtocolGuid, (VOID **) &diskio); if (Status != 0) continue; Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &gEfiBlockIoProtocolGuid, (VOID **) &blockio); if (Status != 0) continue; struct fsw_volume *vol = create_dummy_volume(diskio, blockio->Media->MediaId); if(vol) { DPRINT(L"Checking disk %d\n", i); if(hook(master, vol) == FSW_SUCCESS) scanned++; free_dummy_volume(vol); } } return scanned; }
VOID PauseForKey(VOID) { UINTN index; Print(L"\n* Hit any key to continue *"); if (ReadAllKeyStrokes()) { // remove buffered key strokes refit_call1_wrapper(BS->Stall, 5000000); // 5 seconds delay ReadAllKeyStrokes(); // empty the buffer again } refit_call3_wrapper(BS->WaitForEvent, 1, &ST->ConIn->WaitForKey, &index); ReadAllKeyStrokes(); // empty the buffer to protect the menu Print(L"\n"); }
/** Boot the legacy system with the boot option @param Option The legacy boot option which have BBS device path @retval EFI_UNSUPPORTED There is no legacybios protocol, do not support legacy boot. @retval EFI_STATUS Return the status of LegacyBios->LegacyBoot (). **/ EFI_STATUS BdsLibDoLegacyBoot ( IN BDS_COMMON_OPTION *Option ) { EFI_STATUS Status; EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; Status = refit_call3_wrapper(gBS->LocateProtocol, &gEfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } UpdateBbsTable(Option); return refit_call4_wrapper(LegacyBios->LegacyBoot, LegacyBios, (BBS_BBS_DEVICE_PATH *) Option->DevicePath, Option->LoadOptionsSize, Option->LoadOptions); }
EFI_STATUS egLoadFile(IN EFI_FILE* BaseDir, IN CHAR16 *FileName, OUT UINT8 **FileData, OUT UINTN *FileDataLength) { EFI_STATUS Status; EFI_FILE_HANDLE FileHandle; EFI_FILE_INFO *FileInfo; UINT64 ReadSize; UINTN BufferSize; UINT8 *Buffer; Status = refit_call5_wrapper(BaseDir->Open, BaseDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { return Status; } FileInfo = LibFileInfo(FileHandle); if (FileInfo == NULL) { refit_call1_wrapper(FileHandle->Close, FileHandle); return EFI_NOT_FOUND; } ReadSize = FileInfo->FileSize; if (ReadSize > MAX_FILE_SIZE) ReadSize = MAX_FILE_SIZE; FreePool(FileInfo); BufferSize = (UINTN)ReadSize; // was limited to 1 GB above, so this is safe Buffer = (UINT8 *) AllocatePool(BufferSize); if (Buffer == NULL) { refit_call1_wrapper(FileHandle->Close, FileHandle); return EFI_OUT_OF_RESOURCES; } Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &BufferSize, Buffer); refit_call1_wrapper(FileHandle->Close, FileHandle); if (EFI_ERROR(Status)) { FreePool(Buffer); return Status; } *FileData = Buffer; *FileDataLength = BufferSize; return EFI_SUCCESS; }
// Function to tell the firmware that OS X is being launched. This is // required to work around problems on some Macs that don't fully // initialize some hardware (especially video displays) when third-party // OSes are launched in EFI mode. EFI_STATUS SetAppleOSInfo() { CHAR16 *AppleOSVersion = NULL; CHAR8 *AppleOSVersion8 = NULL; EFI_STATUS Status; EFI_GUID apple_set_os_guid = EFI_APPLE_SET_OS_PROTOCOL_GUID; EfiAppleSetOsInterface *SetOs = NULL; Status = refit_call3_wrapper(BS->LocateProtocol, &apple_set_os_guid, NULL, (VOID**) &SetOs); // If not a Mac, ignore the call.... if ((Status != EFI_SUCCESS) || (!SetOs)) return EFI_SUCCESS; if ((SetOs->Version != 0) && GlobalConfig.SpoofOSXVersion) { AppleOSVersion = StrDuplicate(L"Mac OS X"); MergeStrings(&AppleOSVersion, GlobalConfig.SpoofOSXVersion, ' '); if (AppleOSVersion) { AppleOSVersion8 = AllocateZeroPool((StrLen(AppleOSVersion) + 1) * sizeof(CHAR8)); UnicodeStrToAsciiStr(AppleOSVersion, AppleOSVersion8); if (AppleOSVersion8) { Status = refit_call1_wrapper (SetOs->SetOsVersion, AppleOSVersion8); if (!EFI_ERROR(Status)) Status = EFI_SUCCESS; MyFreePool(AppleOSVersion8); } else { Status = EFI_OUT_OF_RESOURCES; Print(L"Out of resources in SetAppleOSInfo!\n"); } if ((Status == EFI_SUCCESS) && (SetOs->Version == 2)) Status = refit_call1_wrapper (SetOs->SetOsVendor, (CHAR8 *) "Apple Inc."); MyFreePool(AppleOSVersion); } // if (AppleOSVersion) } // if if (Status != EFI_SUCCESS) Print(L"Unable to set firmware boot type!\n"); return (Status); } // EFI_STATUS SetAppleOSInfo()
// Returns TRUE if the shim program is available to verify binaries, // FALSE if not BOOLEAN ShimLoaded(void) { SHIM_LOCK *shim_lock; EFI_GUID ShimLockGuid = SHIM_LOCK_GUID; return (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS); } // ShimLoaded()
/** Internal helper function. Update the BBS Table so that devices of DeviceType have their boot priority updated to a high/bootable value. See "DeviceType values" in http://www.intel.com/content/dam/doc/reference-guide/efi-compatibility-support-module-specification-v097.pdf NOTE: This function should probably be refactored! Currently, all devices of type are enabled. This should be updated so that only a specific device is enabled. The wrong device could boot if there are multiple targets of the same type. @param DeviceType The device type that we wish to enable **/ VOID UpdateBbsTable (BDS_COMMON_OPTION *Option) { UINT16 Idx; EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; EFI_STATUS Status; UINT16 HddCount = 0; HDD_INFO *HddInfo = NULL; UINT16 BbsCount = 0; BBS_TABLE *LocalBbsTable = NULL; BBS_BBS_DEVICE_PATH *OptionBBS; CHAR16 Desc[100]; Status = refit_call3_wrapper(gBS->LocateProtocol, &gEfiLegacyBootProtocolGuid, NULL, (VOID **) &LegacyBios); if (EFI_ERROR (Status) || (Option == NULL)) { return; } OptionBBS = (BBS_BBS_DEVICE_PATH *) Option->DevicePath; Status = refit_call5_wrapper(LegacyBios->GetBbsInfo, LegacyBios, &HddCount, &HddInfo, &BbsCount, &LocalBbsTable); // Print (L"\n"); // Print (L" NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n"); // Print (L"=============================================\n"); for (Idx = 0; Idx < BbsCount; Idx++) { if(LocalBbsTable[Idx].DeviceType == 0) { continue; } BdsBuildLegacyDevNameString (&LocalBbsTable[Idx], Idx, sizeof (Desc), Desc); // Set devices of a particular type to BootPriority of 0 or 1. 0 is the highest priority. if (LocalBbsTable[Idx].DeviceType == OptionBBS->DeviceType) { if (StriCmp(Desc, Option->Description) == 0) { // This entry exactly matches what we're looking for; make it highest priority LocalBbsTable[Idx].BootPriority = 0; } else { // This entry doesn't exactly match, but is the right disk type; make it a bit lower // in priority. Done mainly as a fallback in case of string-matching weirdness. LocalBbsTable[Idx].BootPriority = 1; } // if/else } else if (LocalBbsTable[Idx].BootPriority <= 1) { // Something's got a high enough boot priority to interfere with booting // our chosen entry, so bump it down a bit.... LocalBbsTable[Idx].BootPriority = 2; } // if/else if // Print ( // L" %02x: %04x %02x/%02x/%02x %02x/%02x %04x %04x %04x:%04x\n", // (UINTN) Idx, // (UINTN) LocalBbsTable[Idx].BootPriority, // (UINTN) LocalBbsTable[Idx].Bus, // (UINTN) LocalBbsTable[Idx].Device, // (UINTN) LocalBbsTable[Idx].Function, // (UINTN) LocalBbsTable[Idx].Class, // (UINTN) LocalBbsTable[Idx].SubClass, // (UINTN) LocalBbsTable[Idx].DeviceType, // (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags, // (UINTN) LocalBbsTable[Idx].BootHandlerSegment, // (UINTN) LocalBbsTable[Idx].BootHandlerOffset, // (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset), // (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset) // ); // Print(L"%s\n", Desc); } // for // PauseForKey(); }