diff options
author | Matt Fleming <matt.fleming@linux.intel.com> | 2011-06-27 12:18:33 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@linux.intel.com> | 2011-07-28 12:21:29 +0100 |
commit | 93ecef34e72cf6008cadbee0c499bdcfbec60e8d (patch) | |
tree | b91c214e0e7330a913d4289a422e87ed4a9d8e69 | |
parent | e86f71fe1a230b4e43c6ee43f9697fb8daa46eef (diff) | |
download | efilinux-93ecef34e72cf6008cadbee0c499bdcfbec60e8d.tar.gz |
efilinux: File support
Files are managed via 'struct file', which allows us to hide the
details necessary for accessing the file via the firmware, e.g. all
the handles.
Signed-off-by: Matt Fleming <matt.fleming@linux.intel.com>
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | entry.c | 6 | ||||
-rw-r--r-- | fs/fs.c | 208 | ||||
-rw-r--r-- | fs/fs.h | 109 | ||||
-rw-r--r-- | protocol.h | 71 |
5 files changed, 398 insertions, 3 deletions
@@ -53,18 +53,19 @@ LDSCRIPT=$(LIBDIR)/gnuefi/elf_$(ARCH)_efi.lds CFLAGS=-I. -I/usr/include/efi -I/usr/include/efi/$(ARCH) \ -DEFI_FUNCTION_WRAPPER -fPIC -fshort-wchar -ffreestanding \ - -Wall + -Wall -Ifs/ LDFLAGS=-T $(LDSCRIPT) -Bsymbolic -shared -nostdlib -L$(LIBDIR) $(CRT0) IMAGE=efilinux.efi OBJS = entry.o malloc.o +FS = fs/fs.o all: $(IMAGE) efilinux.efi: efilinux.so -efilinux.so: $(OBJS) +efilinux.so: $(OBJS) $(FS) $(LD) $(LDFLAGS) -o $@ $^ -lgnuefi -lefi $(shell $(CC) -print-libgcc-file-name) clean: - rm -f $(IMAGE) efilinux.so $(OBJS) + rm -f $(IMAGE) efilinux.so $(OBJS) $(FS) @@ -32,7 +32,9 @@ */ #include <efi.h> +#include <efilib.h> #include "efilinux.h" +#include "fs.h" #define ERROR_STRING_LENGTH 32 @@ -171,6 +173,10 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *_table) if (err != EFI_SUCCESS) goto failed; + err = fs_init(); + if (err != EFI_SUCCESS) + goto failed; + return EFI_SUCCESS; failed: @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2011, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <efi.h> +#include <efilib.h> +#include "efilinux.h" +#include "fs.h" +#include "stdlib.h" +#include "protocol.h" + +struct fs_device { + EFI_HANDLE handle; + EFI_FILE_HANDLE fh; + struct fs_ops *ops; +}; + +static struct fs_device *fs_devices; +static UINTN nr_fs_devices; + +/** + * file_open - Open a file on a volume + * @name: pathname of the file to open + * @file: used to return a pointer to the allocated file on success + */ +EFI_STATUS +file_open(CHAR16 *name, struct file **file) +{ + EFI_FILE_HANDLE fh; + struct file *f; + CHAR16 *filename; + EFI_STATUS err; + int dev_len; + int i; + + f = malloc(sizeof(*f)); + if (!f) + return EFI_OUT_OF_RESOURCES; + + for (i = 0; i < nr_fs_devices; i++) { + EFI_DEVICE_PATH *path; + CHAR16 *dev; + + path = DevicePathFromHandle(fs_devices[i].handle); + dev = DevicePathToStr(path); + + if (!StrnCmp(dev, name, StrLen(dev))) { + f->handle = fs_devices[i].fh; + dev_len = StrLen(dev); + free_pool(dev); + break; + } + + free_pool(dev); + } + + if (i == nr_fs_devices) { + err = EFI_NOT_FOUND; + goto fail; + } + + /* Strip the device name */ + filename = name + dev_len; + + /* skip any path separators */ + while (*filename == ':' || *filename == '\\') + filename++; + + err = uefi_call_wrapper(f->handle->Open, 5, f->handle, &fh, + filename, EFI_FILE_MODE_READ, (UINT64)0); + if (err != EFI_SUCCESS) + goto fail; + + f->fh = fh; + *file = f; + + return err; +fail: + Print(L"Unable to open file \"%s\"", name); + free(f); + return err; +} + +/** + * file_close - Close a file handle + * @f: the file to close + */ +EFI_STATUS +file_close(struct file *f) +{ + UINTN err; + + err = uefi_call_wrapper(f->handle->Close, 1, f->fh); + + if (err == EFI_SUCCESS) + free(f); + + return err; +} + +/** + * list_boot_devices - Print a list of all disks with filesystems + */ +void list_boot_devices(void) +{ + int i; + + Print(L"Devices:\n\n"); + + for (i = 0; i < nr_fs_devices; i++) { + EFI_DEVICE_PATH *path; + EFI_HANDLE dev_handle; + CHAR16 *dev; + + dev_handle = fs_devices[i].handle; + + path = DevicePathFromHandle(dev_handle); + dev = DevicePathToStr(path); + + Print(L"\t%d. \"%s\"\n", i, dev); + free_pool(dev); + } + + Print(L"\n"); +} + +/* + * Initialise filesystem protocol. + */ +EFI_STATUS +fs_init(void) +{ + EFI_STATUS err; + UINTN size = 0; + int i; + + size = 0; + err = locate_handle(ByProtocol, &FileSystemProtocol, + NULL, &size, NULL); + + if (err != EFI_SUCCESS && size == 0) { + Print(L"No devices support filesystems\n"); + goto out; + } + + nr_fs_devices = size / sizeof(EFI_HANDLE); + fs_devices = malloc(sizeof(*fs_devices) * nr_fs_devices); + if (!fs_devices) + goto out; + + err = locate_handle(ByProtocol, &FileSystemProtocol, + NULL, &size, (void **)fs_devices); + + for (i = 0; i < nr_fs_devices; i++) { + EFI_FILE_IO_INTERFACE *io; + EFI_FILE_HANDLE fh; + EFI_HANDLE dev_handle; + + dev_handle = fs_devices[i].handle; + err = handle_protocol(dev_handle, &FileSystemProtocol, + (void **)&io); + if (err != EFI_SUCCESS) + goto out; + + err = volume_open(io, &fh); + if (err != EFI_SUCCESS) + goto out; + + fs_devices[i].fh = fh; + } + +out: + return err; +} + +void fs_exit(void) +{ + free(fs_devices); +} @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2011, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __FS_H__ +#define __FS_H__ + +#define MAX_FILENAME 256 + +struct file { + EFI_FILE_HANDLE handle; + EFI_FILE_HANDLE fh; +}; + +/** + * volume_open - Open the root directory on a volume + * @vol: the volume to open + * @fh: place to return the open file handle for the root directory + */ +static inline EFI_STATUS +volume_open(EFI_FILE_IO_INTERFACE *vol, EFI_FILE_HANDLE *fh) +{ + return uefi_call_wrapper(vol->OpenVolume, 2, vol, fh); +} + +/** + * file_read - Read from an open file + * @f: the file to read + * @size: size in bytes to read from @f + * @buf: place to store the data read + */ +static inline EFI_STATUS +file_read(struct file *f, UINTN *size, void *buf) +{ + return uefi_call_wrapper(f->handle->Read, 3, f->fh, size, buf); +} + +/** + * file_set_position - Set the current offset of a file + * @f: the file on which we're changing current file position + * @pos: the file offset to set the current position to + */ +static inline EFI_STATUS +file_set_position(struct file *f, UINT64 pos) +{ + return uefi_call_wrapper(f->fh->SetPosition, 2, f->fh, pos); +} + +/** + * file_size - Get the size (in bytes) of @file + * @f: the file to query + * @size: where to store the size of the file + */ +static inline EFI_STATUS +file_size(struct file *f, UINT64 *size) +{ + EFI_FILE_INFO *info; + + info = LibFileInfo(f->fh); + + if (!info) + return EFI_UNSUPPORTED; + + *size = info->FileSize; + + free_pool(info); + + return EFI_SUCCESS; +} + +extern EFI_STATUS file_open(CHAR16 *name, struct file **file); +extern EFI_STATUS file_close(struct file *f); + +extern void list_boot_devices(void); + +extern EFI_STATUS fs_init(void); +extern void fs_exit(void); + +#endif /* __FS_H__ */ diff --git a/protocol.h b/protocol.h new file mode 100644 index 0000000..6881d70 --- /dev/null +++ b/protocol.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PROTOCOL_H__ +#define __PROTOCOL_H__ + +/** + * handle_protocol - Query @handle to see if it supports @protocol + * @handle: the handle being queried + * @protocol: the GUID of the protocol + * @interface: used to return the protocol interface + * + * Query @handle to see if @protocol is supported. If it is supported, + * @interface contains the protocol interface. + */ +static inline EFI_STATUS +handle_protocol(EFI_HANDLE handle, EFI_GUID *protocol, void **interface) +{ + return uefi_call_wrapper(boot->HandleProtocol, 3, + handle, protocol, interface); +} + +/** + * locate_handle - Search for handles that support @protocol + * @type: the search type, which handles are returned + * @protocol: the protocol to search by (only valid if @type is ByProtocol) + * @key: the search key + * @size: on input the size in bytes of @buffer, on output the size of + * the returned array or the required size to store the array + * in @buffer if it was not large enough + * @buffer: buffere where the array of handles is returned + */ +static inline EFI_STATUS +locate_handle(EFI_LOCATE_SEARCH_TYPE type, EFI_GUID *protocol, void *key, + UINTN *size, EFI_HANDLE *buffer) +{ + return uefi_call_wrapper(boot->LocateHandle, 5, type, protocol, + key, size, buffer); +} + +#endif /* __PROTOCOL_H__ */ |