// Sets the screen resolution to the specified value, if possible. // If the specified value is not valid, displays a warning with the valid // modes on UEFI systems, or silently fails on EFI 1.x systems. Note that // this function attempts to set ANY screen resolution, even 0x0 or // ridiculously large values. // Returns TRUE if successful, FALSE if not. BOOLEAN egSetScreenSize(IN UINTN ScreenWidth, IN UINTN ScreenHeight) { EFI_STATUS Status = EFI_SUCCESS; EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; UINT32 ModeNum = 0; UINTN Size; BOOLEAN ModeSet = FALSE; UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate; if (GraphicsOutput != NULL) { // GOP mode (UEFI) // Do a loop through the modes to see if the specified one is available; // and if so, switch to it.... while ((Status == EFI_SUCCESS) && (!ModeSet)) { Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info)) && (Info->HorizontalResolution == ScreenWidth) && (Info->VerticalResolution == ScreenHeight)) { Status = refit_call2_wrapper(GraphicsOutput->SetMode, GraphicsOutput, ModeNum); ModeSet = (Status == EFI_SUCCESS); } // if ModeNum++; } // while() if (ModeSet) { egScreenWidth = ScreenWidth; egScreenHeight = ScreenHeight; } else {// If unsuccessful, display an error message for the user.... Print(L"Error setting mode %d x %d; using default mode!\nAvailable modes are:\n", ScreenWidth, ScreenHeight); ModeNum = 0; Status = EFI_SUCCESS; while (Status == EFI_SUCCESS) { Status = refit_call4_wrapper(GraphicsOutput->QueryMode, GraphicsOutput, ModeNum, &Size, &Info); if ((Status == EFI_SUCCESS) && (Size >= sizeof(*Info))) { Print(L"Mode %d: %d x %d\n", ModeNum, Info->HorizontalResolution, Info->VerticalResolution); } // else ModeNum++; } // while() PauseForKey(); } // if() } else if (UgaDraw != NULL) { // UGA mode (EFI 1.x) // Try to use current color depth & refresh rate for new mode. Maybe not the best choice // in all cases, but I don't know how to probe for alternatives.... Status = refit_call5_wrapper(UgaDraw->GetMode, UgaDraw, &UGAWidth, &UGAHeight, &UGADepth, &UGARefreshRate); Status = refit_call5_wrapper(UgaDraw->SetMode, UgaDraw, ScreenWidth, ScreenHeight, UGADepth, UGARefreshRate); if (Status == EFI_SUCCESS) { egScreenWidth = ScreenWidth; egScreenHeight = ScreenHeight; ModeSet = TRUE; } else { // TODO: Find a list of supported modes and display it. // NOTE: Below doesn't actually appear unless we explicitly switch to text mode. // This is just a placeholder until something better can be done.... Print(L"Error setting mode %d x %d; unsupported mode!\n"); } // if/else } // if/else if return (ModeSet); } // BOOLEAN egSetScreenSize()
VOID egInitScreen(VOID) { EFI_STATUS Status = EFI_SUCCESS; UINT32 UGAWidth, UGAHeight, UGADepth, UGARefreshRate; // get protocols Status = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **) &ConsoleControl); if (EFI_ERROR(Status)) ConsoleControl = NULL; Status = LibLocateProtocol(&UgaDrawProtocolGuid, (VOID **) &UgaDraw); if (EFI_ERROR(Status)) UgaDraw = NULL; Status = LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **) &GraphicsOutput); if (EFI_ERROR(Status)) GraphicsOutput = NULL; // get screen size egHasGraphics = FALSE; if (GraphicsOutput != NULL) { egScreenWidth = GraphicsOutput->Mode->Info->HorizontalResolution; egScreenHeight = GraphicsOutput->Mode->Info->VerticalResolution; egHasGraphics = TRUE; } else if (UgaDraw != NULL) { Status = refit_call5_wrapper(UgaDraw->GetMode, UgaDraw, &UGAWidth, &UGAHeight, &UGADepth, &UGARefreshRate); if (EFI_ERROR(Status)) { UgaDraw = NULL; // graphics not available } else { egScreenWidth = UGAWidth; egScreenHeight = UGAHeight; egHasGraphics = TRUE; } } }
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; }
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; }
/** 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(); }
fsw_status_t fsw_efi_read_block(struct fsw_volume *vol, fsw_u64 phys_bno, void *buffer) { int i, ReadCache = -1; FSW_VOLUME_DATA *Volume = (FSW_VOLUME_DATA *)vol->host_data; EFI_STATUS Status = EFI_SUCCESS; BOOLEAN ReadOneBlock = FALSE; fsw_u64 StartRead = phys_bno * vol->phys_blocksize; if (buffer == NULL) return (fsw_status_t) EFI_BAD_BUFFER_SIZE; // Initialize static data structures, if necessary.... if (LastRead < 0) { fsw_efi_clear_cache(); } // if // Look for a cache hit on the current query.... i = 0; do { if ((Caches[i].Volume == Volume) && (Caches[i].CacheValid == TRUE) && (StartRead >= Caches[i].CacheStart) && ((StartRead + vol->phys_blocksize) <= (Caches[i].CacheStart + CACHE_SIZE))) { ReadCache = i; } i++; } while ((i < NUM_CACHES) && (ReadCache < 0)); // No cache hit found; load new cache and pass it on.... if (ReadCache < 0) { if (LastRead == -1) LastRead = 1; ReadCache = 1 - LastRead; // NOTE: If NUM_CACHES > 2, this must become more complex Caches[ReadCache].CacheValid = FALSE; if (Caches[ReadCache].Cache == NULL) Caches[ReadCache].Cache = AllocatePool(CACHE_SIZE); if (Caches[ReadCache].Cache != NULL) { Status = refit_call5_wrapper(Volume->DiskIo->ReadDisk, Volume->DiskIo, Volume->MediaId, StartRead, CACHE_SIZE, Caches[ReadCache].Cache); if (!EFI_ERROR(Status)) { Caches[ReadCache].CacheStart = StartRead; Caches[ReadCache].CacheValid = TRUE; Caches[ReadCache].Volume = Volume; LastRead = ReadCache; } else { ReadOneBlock = TRUE; } } else { ReadOneBlock = TRUE; } // if cache memory allocated } // if (ReadCache < 0) if (Caches[ReadCache].Cache != NULL && Caches[ReadCache].CacheValid == TRUE && vol->phys_blocksize > 0) { CopyMem(buffer, &Caches[ReadCache].Cache[StartRead - Caches[ReadCache].CacheStart], vol->phys_blocksize); } else { ReadOneBlock = TRUE; } if (ReadOneBlock) { // Something's failed, so try a simple disk read of one block.... Status = refit_call5_wrapper(Volume->DiskIo->ReadDisk, Volume->DiskIo, Volume->MediaId, phys_bno * vol->phys_blocksize, vol->phys_blocksize, buffer); } Volume->LastIOStatus = Status; return Status; } // fsw_status_t *fsw_efi_read_block()