EFI_STATUS EFIAPI efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) { InitializeLib(image_handle, systab); EFI_STATUS Status; systab->ConOut->ClearScreen(systab->ConOut); // CLEAR! EFI_GUID simplefs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; // a simple file system protocol in efi // (different from UEFI specification. In specification, this is called EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID ) EFI_FILE_IO_INTERFACE *simplefs; // the simple file system's interface // (different from UEFI specification. In specification, this is called EFI_SIMPLE_FILE_SYSTEM_PROTOCOL) EFI_FILE *root; // root directory EFI_FILE *dir; CHAR16 *dirname=L"\\stories"; // name of the directory where bmp pictures are put status=systab->BootServices->LocateProtocol(&simplefs_guid, NULL, (VOID **)&simplefs); if(EFI_ERROR(status)) Print(L"locate protocol failed \n"); status=simplefs->OpenVolume(simplefs, &root); if(EFI_ERROR(status)) Print(L"open volume failed\n"); status=root->Open(root, &dir, dirname, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY); if(EFI_ERROR(status)) Print(L"open directory failed\n"); VOID *buf; INT32 index=1; status = readFile(dir, index, systab, buf); // Put the contents of 1.story into buf Print(L"%s", buf); WaitForSingleEvent(ST->ConIn->WaitForKey, 0); uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key); return Status; }
/* * Print information about disks */ static void efifs_dev_print(int verbose) { union { EFI_FILE_SYSTEM_INFO info; char buffer[1024]; } fi; char line[80]; EFI_FILE_IO_INTERFACE *fsif; EFI_FILE *volume; EFI_HANDLE h; EFI_STATUS status; UINTN sz; int i, unit; for (unit = 0, h = efi_find_handle(&efifs_dev, 0); h != NULL; h = efi_find_handle(&efifs_dev, ++unit)) { sprintf(line, " %s%d: ", efifs_dev.dv_name, unit); pager_output(line); status = BS->HandleProtocol(h, &sfs_guid, (VOID **)&fsif); if (EFI_ERROR(status)) goto err; status = fsif->OpenVolume(fsif, &volume); if (EFI_ERROR(status)) goto err; sz = sizeof(fi); status = volume->GetInfo(volume, &fs_guid, &sz, &fi); volume->Close(volume); if (EFI_ERROR(status)) goto err; if (fi.info.ReadOnly) pager_output("[RO] "); else pager_output(" "); for (i = 0; fi.info.VolumeLabel[i] != 0; i++) fi.buffer[i] = fi.info.VolumeLabel[i]; fi.buffer[i] = 0; if (fi.buffer[0] != 0) pager_output(fi.buffer); else pager_output("EFI filesystem"); pager_output("\n"); continue; err: sprintf(line, "[--] error %d: unable to obtain information\n", efi_status_to_errno(status)); pager_output(line); } }
EFI_STATUS EntryPoint ( EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable ) { EFI_STATUS Status = 0; UINTN i = 0; EFI_FILE_IO_INTERFACE *Vol = 0; EFI_FILE_HANDLE RootFs = 0; EFI_FILE_HANDLE FileHandle = 0; EFI_HANDLE* Search = 0; EFI_HANDLE DeviceHandle = 0; UINTN Size = 0; VOID* BootmgrBuffer = 0; EFI_FILE_INFO* FileInfoBuffer = 0; EFI_HANDLE BootmgrHandle = NULL; EFI_LOADED_IMAGE *BootmgrLoadedImage = 0; EFI_LOADED_IMAGE *LoadedImage = 0; CHAR16 *BOOTMGFW = L"\\EFI\\Microsoft\\BOOT\\BOOTMGFW.EFI"; CHAR16 *BOOTMGFW_BAK = L"\\EFI\\Microsoft\\BOOT\\BOOTMGFW.BAK"; EFI_DEVICE_PATH_PROTOCOL* DevPath = 0; ST = SystemTable; BS = ST->BootServices; RS = ST->RuntimeServices; Status = Main(); //=========================================================================// // get device handle for the loaded (this) image // //=========================================================================// Status = BS->HandleProtocol(ImageHandle, &gLoadedImageProtocol, (VOID **) &LoadedImage); if (EFI_ERROR (Status)) { return Status; } DeviceHandle = LoadedImage->DeviceHandle; //=========================================================================// // get file io interface for device image was loaded from // //=========================================================================// Status = BS->HandleProtocol(DeviceHandle, &gFileSystemProtocol, (VOID **) &Vol); if (EFI_ERROR (Status)) { return Status; } //=========================================================================// // open file system root for the device image was loaded from // //=========================================================================// Status = Vol->OpenVolume(Vol, &RootFs); if (EFI_ERROR (Status)) { return Status; } //=========================================================================// // try to open bootmgfw on file system that image was loaded from // //=========================================================================// //=========================================================================// // look for BOOTMGFW.BAK first to support BOOTMGFW.EFI replacement // // install method. // //=========================================================================// Status = RootFs->Open(RootFs, &FileHandle, BOOTMGFW_BAK, EFI_FILE_MODE_READ, 0); if (Status == EFI_SUCCESS) { BOOTMGFW = BOOTMGFW_BAK; } else if (Status == EFI_NOT_FOUND) { /* if BOOTMGFW.BAK not found search for BOOTMGFW.EFI */ Status = RootFs->Open(RootFs, &FileHandle, BOOTMGFW, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { RootFs->Close(RootFs); switch(Status) { case EFI_NOT_FOUND: //=========================================================================// // failed to find bootmgfw on same device, look for it on other devices. // // get array of device handle's that bootmgfw might be installed on // // first get size of array // //=========================================================================// Size = 0; Status = BS->LocateHandle(ByProtocol, &gFileSystemProtocol, NULL, &Size, 0); if(Status == EFI_BUFFER_TOO_SMALL) { /* allocate memory for array */ Search = (EFI_HANDLE *) AllocatePool(Size); } if(Search) { /* get the array */ Status = BS->LocateHandle(ByProtocol, &gFileSystemProtocol, NULL, &Size, Search); /* loop through handle's open each file system & try to open bootmgfw */ if(Status == EFI_SUCCESS) { for(i = 0; i < Size / sizeof(EFI_HANDLE); i++) { /* we already know bootmgfw is not in the same device as the loaded image, skip */ if(Search[i] == DeviceHandle) { continue; } /* get file io interface */ Status = BS->HandleProtocol(Search[i], &gFileSystemProtocol, (VOID **) &Vol); if(EFI_ERROR (Status)) { continue; } /* open file system root on the device */ Status = Vol->OpenVolume(Vol, &RootFs); if(EFI_ERROR (Status)) { continue; } /* try to open bootmgfw on the file system */ Status = RootFs->Open(RootFs, &FileHandle, BOOTMGFW, EFI_FILE_MODE_READ, 0); if(Status == EFI_SUCCESS) { /* found it, set DeviceHandle & break the loop */ DeviceHandle = Search[i]; break; } /* clean up for next pass */ RootFs->Close(RootFs); } /* free array of device handles, if EFI_SUCCESS break */ /* the switch/case else fall through to the error */ BS->FreePool(Search); if(Status == EFI_SUCCESS) { break; } } } default: return Status; } } } else { return Status; } //============================================================================// // RootFs is open, FileHandle is open, DeviceHandle is set // // get size of bootmgfw.efi by retriving an EFI_FILE_INFO // // first get the size of the STRUCT and allocate memory // //============================================================================// Size = 0; Status = FileHandle->GetInfo(FileHandle, &gFileInfo, &Size, NULL); if(Status == EFI_BUFFER_TOO_SMALL) { /* allocate memory for EFI_FILE_INFO */ FileInfoBuffer = (EFI_FILE_INFO *) AllocatePool(Size); } else { FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // get EFI_FILE_INFO for bootmgfw.efi // //=========================================================================// Status = FileHandle->GetInfo(FileHandle, &gFileInfo, &Size, FileInfoBuffer); if(EFI_ERROR(Status)) { FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // get size of bootmgfw.efi // //=========================================================================// Size = FileInfoBuffer->FileSize; //=========================================================================// // free EFI_FILE_INFO buffer // //=========================================================================// BS->FreePool(FileInfoBuffer); //=========================================================================// // allocate memory for bootmgfw.efi // //=========================================================================// BootmgrBuffer = AllocatePool(Size); if (!BootmgrBuffer) { BS->FreePool(BootmgrBuffer); FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // read bootmgfw.efi into buffer // //=========================================================================// Status = FileHandle->Read(FileHandle, &Size, BootmgrBuffer); if (EFI_ERROR (Status)) { BS->FreePool(BootmgrBuffer); FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // close handle for bootmgfw.efi // //=========================================================================// Status = FileHandle->Close(FileHandle); if (EFI_ERROR (Status)) { } //=========================================================================// // close handle for file system root // //=========================================================================// Status = RootFs->Close(RootFs); if (EFI_ERROR (Status)) { } //=========================================================================// // load bootmgfw.efi from buffer to execution space // //=========================================================================// Status = BS->LoadImage(FALSE, ImageHandle, 0, BootmgrBuffer, Size, &BootmgrHandle); if (EFI_ERROR (Status)) { BS->FreePool(BootmgrBuffer); return Status; } BS->FreePool(BootmgrBuffer); //=========================================================================// // set bootmgfw.efi start variables // //=========================================================================// Status = BS->HandleProtocol(BootmgrHandle, &gLoadedImageProtocol, (VOID **) &BootmgrLoadedImage); if (EFI_ERROR (Status)) { return Status; } BootmgrLoadedImage->DeviceHandle = DeviceHandle; BootmgrLoadedImage->ParentHandle = NULL; BootmgrLoadedImage->FilePath = FileDevicePath(DeviceHandle, BOOTMGFW); //=========================================================================// // start bootmgfw.efi execution // //=========================================================================// Status = BS->StartImage(BootmgrHandle, 0, 0); //============================================================================// // should never get here show error // //============================================================================// if (BootmgrHandle != NULL) { Status = BS->UnloadImage(BootmgrHandle); } return Status; }
EFI_STATUS EfiMain(EFI_HANDLE hImage, EFI_SYSTEM_TABLE *pST) { EFI_LOADED_IMAGE *pImage; EFI_STATUS nStatus; EFI_HANDLE hDriver, *hBlkDevs; UINTN nBlkDevs; EFI_DEVICE_PATH *pBootPart, *pBootDisk = NULL; g_hImage = hImage; InitializeLib(hImage, pST); Print(L"%H\n*** UEFI:NTFS multiboot ***"); if (EFI_ERROR((nStatus = BS->OpenProtocol(hImage, &LoadedImageProtocol, &pImage, hImage, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)))) { Print(L"%E\nUnable to convert handle to interface: %r\n", nStatus); goto end; } pBootPart = DevicePathFromHandle(pImage->DeviceHandle); pBootDisk = GetParentDevice(pBootPart); CHAR16 *pszDev = DevicePathToStr(pBootDisk); Print(L"%N\nDisk: %s\n", pszDev); FreePool(pszDev); Print(L"%H\n[ INFO ] Disconnecting problematic File System drivers\n"); DisconnectBlockingDrivers(); Print(L"%H\n[ WAIT ] Loading NTFS driver"); EFI_DEVICE_PATH *pDrvPath = FileDevicePath(pImage->DeviceHandle, DriverPath); if (pDrvPath == NULL) { Print(L"%E\r[ FAIL ] Unable to construct path to NTFS driver\n"); goto end; } nStatus = BS->LoadImage(FALSE, hImage, pDrvPath, NULL, 0, &hDriver); FreePool(pDrvPath); if (EFI_ERROR(nStatus)) { Print(L"%E\r[ FAIL ] Unable to load NTFS driver: %r\n", nStatus); goto end; } if (EFI_ERROR((nStatus = BS->StartImage(hDriver, NULL, NULL)))) { Print(L"%E\r[ FAIL ] Unable to start NTFS driver: %r\n", nStatus); goto end; } Print(L"%H\r[ OK ] NTFS driver loaded and started\n"); LINKED_LOADER_PATH_LIST_NODE *list = NULL; EFI_DEVICE_PATH *ldr; if (EFI_ERROR((nStatus = BS->LocateHandleBuffer(ByProtocol, &BlockIoProtocol, NULL, &nBlkDevs, &hBlkDevs)))) { Print(L"%E\r[ FAIL ] Unable to enumerate block devices: %r\n", nStatus); goto end; } for (UINTN i = 0; i < nBlkDevs; i++) { EFI_DEVICE_PATH *pDevice = DevicePathFromHandle(hBlkDevs[i]); pszDev = DevicePathToStr(pDevice); Print(L"%N\r[ INFO ] Probing %d devices... [%d] %s", nBlkDevs, i + 1, pszDev); FreePool(pszDev); if (CompareDevicePaths(pDevice, pBootPart) == 0) continue; if (CompareDevicePaths(pDevice, pBootDisk) == 0) continue; EFI_DEVICE_PATH *pDisk = GetParentDevice(pDevice); _Bool probe = CompareDevicePaths(pDisk, pBootDisk) == 0; FreePool(pDisk); #if !defined(_DEBUG) if (!probe) continue; #endif EFI_BLOCK_IO *blkIo; if (EFI_ERROR((nStatus = BS->OpenProtocol(hBlkDevs[i], &BlockIoProtocol, &blkIo, hImage, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)))) { Print(L"%E\n[ WARN ] Unable to open block device, skipping: %r\n", nStatus); continue; } //No media or not a partition. if ((blkIo->Media == NULL) || (!blkIo->Media->LogicalPartition)) continue; CHAR8 *buffer = AllocatePool(blkIo->Media->BlockSize); if (buffer == NULL) { Print(L"%E\n[ WARN ] Unable to allocate buffer of size %d\n", blkIo->Media->BlockSize); continue; } nStatus = blkIo->ReadBlocks(blkIo, blkIo->Media->MediaId, 0, blkIo->Media->BlockSize, buffer); _Bool isNTFS = CompareMem(&buffer[3], NTFSMagic, sizeof(NTFSMagic)) == 0; FreePool(buffer); if (EFI_ERROR(nStatus)) { Print(L"%E\n[ WARN ] Unable to read block device, skipping: %r\n", nStatus); continue; } if (!isNTFS) continue; Print(L"%H\n[ WAIT ] Attaching NTFS driver to device"); EFI_FILE_IO_INTERFACE *fs; nStatus = BS->OpenProtocol(hBlkDevs[i], &FileSystemProtocol, NULL, hImage, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); if (nStatus == EFI_UNSUPPORTED) { nStatus = BS->ConnectController(hBlkDevs[i], NULL, NULL, TRUE); } for (UINTN j = 0; j < NUM_RETRIES; j++) { if ((!EFI_ERROR((nStatus = BS->OpenProtocol(hBlkDevs[i], &FileSystemProtocol, &fs, hImage, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL))))) { break; } Print(L"."); BS->Stall(DELAY * 1000000); } if(EFI_ERROR(nStatus)) { Print(L"%E\r[ WARN ] Unable to attach NTFS driver, skipping: %r\n", nStatus); continue; } Print(L"%H\r[ OK ] NTFS driver attached to current device\n"); Print(L"%H\r[ WAIT ] Locating EFI boot loader"); EFI_FILE *fsRoot; if (EFI_ERROR((nStatus = fs->OpenVolume(fs, &fsRoot)))) { Print(L"%E\r[ WARN ] Unable to open root directory, skipping: %r\n", nStatus); continue; } CHAR16 *loader = StrDuplicate(LoaderPath); if (EFI_ERROR((nStatus = SetPathCase(fsRoot, loader)))) { FreePool(loader); Print(L"%E\r[ WARN ] Unable to locate EFI boot loader on this device: %r\n", nStatus); continue; } Print(L"%H\r[ OK ] EFI boot loader located at %s\n", loader); ldr = FileDevicePath(hBlkDevs[i], loader); ListAppend(&list, ldr); FreePool(loader); } UINTN nListEntries = 0, nBootEntry = 0, nPage = 0, nTotalPage = 0; EFI_INPUT_KEY key; _Bool interactive = FALSE; ListTraverse(&list, CountEntries, 0, 0, &nListEntries); switch (nListEntries) { case 0: Print(L"%E\n[ FAIL ] No bootable partition\n", nStatus); nStatus = EFI_NOT_FOUND; goto end; case 1: goto boot; default: nTotalPage = (nListEntries - 1) / PAGE_SIZE + 1; while (1) { ST->ConOut->ClearScreen(ST->ConOut); Print(L"%H*** UEFI:NTFS Multiboot ***\n"); pszDev = DevicePathToStr(pBootDisk); Print(L"%NDisk: %s\n\n%H", pszDev); FreePool(pszDev); ListTraverse(&list, DisplayEntries, nPage * PAGE_SIZE, PAGE_SIZE, NULL); Print(L"%N\nPage %hd / %hd, %hd entries\n", nPage + 1, nTotalPage, nListEntries); Print(L"%H\n[F1 - F8] [1 - 8] %N Boot corresponding entry"); Print(L"%H\n[PgUp] [<] [-] %N Previous page"); Print(L"%H\n[PgDn] [>] [+] %N Next page"); if (!interactive) { INTN nCountDown = AUTOBOOT_TIME; Print(L"%N\n\n"); while (nCountDown >= 0) { Print(L"\rWill automatically boot the first entry in %d seconds...", nCountDown); if (WaitForSingleEvent(ST->ConIn->WaitForKey, 1000 * 1000 * 10) != EFI_TIMEOUT) { interactive = TRUE; break; } nCountDown--; } if (!interactive) { goto boot; } } else { WaitForSingleEvent(ST->ConIn->WaitForKey, 0); } ST->ConIn->ReadKeyStroke(ST->ConIn, &key); switch (key.UnicodeChar) { case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8': nBootEntry = nPage * PAGE_SIZE + (key.UnicodeChar - L'1'); goto boot; case L'+':case L'=':case L'>':case L'.': if ((nPage + 1) != nTotalPage) { nPage++; } break; case L'-':case L'_': case L'<': case L',': if (nPage != 0) { nPage--; } break; default: switch (key.ScanCode) { case 0x09: if (nPage != 0) { nPage--; } break; case 0x0a: if ((nPage + 1) != nTotalPage) { nPage++; } break; case 0x0b:case 0x0c:case 0x0d:case 0x0e:case 0x0f:case 0x10:case 0x11:case 0x12: nBootEntry = nPage * PAGE_SIZE + (key.ScanCode - 0x0b); goto boot; } } } } boot: ldr = NULL; Print(L"%H"); ST->ConOut->ClearScreen(ST->ConOut); ListTraverse(&list, ReadEntry, nBootEntry, 1, &ldr); ListTraverse(&list, DisplayEntries, nBootEntry, 1, NULL); if (ldr == NULL) { Print(L"%E\n[ FAIL ] No such boot entry\n", nStatus); nStatus = EFI_NOT_FOUND; goto end; } ldr = DuplicateDevicePath(ldr); ListTraverse(&list, DestroyEntries, 0, 0, NULL); ListDestroy(&list); EFI_HANDLE hChain; nStatus = BS->LoadImage(FALSE, hImage, ldr, NULL, 0, &hChain); FreePool(ldr); if (EFI_ERROR(nStatus)) { Print(L"%E\n[ FAIL ] Unable to load boot loader: %r\n", nStatus); goto end; } Print(L"%N"); if (EFI_ERROR((nStatus = BS->StartImage(hChain, NULL, NULL)))) { Print(L"%E\n[ FAIL ] Unable to start boot loader: %r\n", nStatus); goto end; } end: if (pBootDisk) FreePool(pBootDisk); if (EFI_ERROR(nStatus)) { Print(L"Press any key to exit\n"); WaitForSingleEvent(ST->ConIn->WaitForKey, 0); ST->ConIn->ReadKeyStroke(ST->ConIn, &key); } return nStatus; }
static int efifs_open(const char *upath, struct open_file *f) { struct devdesc *dev = f->f_devdata; EFI_FILE_IO_INTERFACE *fsif; EFI_FILE *file, *root; EFI_HANDLE h; EFI_STATUS status; CHAR16 *cp, *path; if (f->f_dev != &efifs_dev || dev->d_unit < 0) return (EINVAL); h = efi_find_handle(f->f_dev, dev->d_unit); if (h == NULL) return (EINVAL); status = BS->HandleProtocol(h, &sfs_guid, (VOID **)&fsif); if (EFI_ERROR(status)) return (efi_status_to_errno(status)); /* Get the root directory. */ status = fsif->OpenVolume(fsif, &root); if (EFI_ERROR(status)) return (efi_status_to_errno(status)); while (*upath == '/') upath++; /* Special case: opening the root directory. */ if (*upath == '\0') { f->f_fsdata = root; return (0); } path = malloc((strlen(upath) + 1) * sizeof(CHAR16)); if (path == NULL) { root->Close(root); return (ENOMEM); } cp = path; while (*upath != '\0') { if (*upath == '/') { *cp = '\\'; while (upath[1] == '/') upath++; } else *cp = *upath; upath++; cp++; } *cp = 0; /* Open the file. */ status = root->Open(root, &file, path, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); if (status == EFI_ACCESS_DENIED || status == EFI_WRITE_PROTECTED) status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0); free(path); root->Close(root); if (EFI_ERROR(status)) return (efi_status_to_errno(status)); f->f_fsdata = file; return (0); }