コード例 #1
0
ファイル: main.c プロジェクト: NateBrune/dEFIant
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;
}
コード例 #2
0
ファイル: efifs.c プロジェクト: oza/FreeBSD-7.3-dyntick
/*
 * 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);
	}
}
コード例 #3
0
ファイル: Main.cpp プロジェクト: KunYi/Injector
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;
}
コード例 #4
0
ファイル: boot.c プロジェクト: linnaea/uefi-ntfs-multiboot
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;
}
コード例 #5
0
ファイル: efifs.c プロジェクト: oza/FreeBSD-7.3-dyntick
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);
}