diff options
author | Tom Rini <trini@konsulko.com> | 2019-04-08 22:32:45 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2019-04-08 22:32:45 -0400 |
commit | 1d63ec3fa40e4899ad1d74d5ed3c926acfda54f2 (patch) | |
tree | ceef3a1214f5422b0071454aecd511e1b5f6bf95 /lib/efi_loader/efi_file.c | |
parent | ffb269ab30dbce8ab87d09942e2a6951694516f1 (diff) | |
parent | bfc2dd53812f7946b61c18e915118fb7aad12e6d (diff) |
Merge tag 'efi-2019-07-rc1' of git://git.denx.de/u-boot-efi
Pull request for UEFI sub-system for v2019.07-rc1
The patch series adds support for the BootNext and BootCurrent variables.
The rest is mostly bug fixes. With the bug fixes in place it becomes
possible to use the EFI Shell `edit` command.
A new unit test is supplied to check the image base and size fields of the
loaded image protocol.
An inline check when freeing memory from the pool safeguards against double
frees.
Diffstat (limited to 'lib/efi_loader/efi_file.c')
-rw-r--r-- | lib/efi_loader/efi_file.c | 108 |
1 files changed, 96 insertions, 12 deletions
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 0483403be0..182d735e6b 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -135,6 +135,25 @@ static int sanitize_path(char *path) } /** + * efi_create_file() - create file or directory + * + * @fh: file handle + * @attributes: attributes for newly created file + * Returns: 0 for success + */ +static int efi_create_file(struct file_handle *fh, u64 attributes) +{ + loff_t actwrite; + void *buffer = &actwrite; + + if (attributes & EFI_FILE_DIRECTORY) + return fs_mkdir(fh->path); + else + return fs_write(fh->path, map_to_sysmem(buffer), 0, 0, + &actwrite); +} + +/** * file_open() - open a file handle * * @fs: file system @@ -176,6 +195,7 @@ static struct efi_file_handle *file_open(struct file_system *fs, if (parent) { char *p = fh->path; + int exists; if (plen > 0) { strcpy(p, parent->path); @@ -192,18 +212,17 @@ static struct efi_file_handle *file_open(struct file_system *fs, if (set_blk_dev(fh)) goto error; - if ((mode & EFI_FILE_MODE_CREATE) && - (attributes & EFI_FILE_DIRECTORY)) { - if (fs_mkdir(fh->path)) - goto error; - } else if (!((mode & EFI_FILE_MODE_CREATE) || - fs_exists(fh->path))) - goto error; - + exists = fs_exists(fh->path); /* fs_exists() calls fs_close(), so open file system again */ if (set_blk_dev(fh)) goto error; + if (!exists) { + if (!(mode & EFI_FILE_MODE_CREATE) || + efi_create_file(fh, attributes)) + goto error; + } + /* figure out if file is a directory: */ fh->isdir = is_dir(fh); } else { @@ -257,10 +276,12 @@ static efi_status_t EFIAPI efi_file_open(struct efi_file_handle *file, /* Open file */ *new_handle = file_open(fh->fs, fh, file_name, open_mode, attributes); - if (*new_handle) + if (*new_handle) { + EFI_PRINT("file handle %p\n", *new_handle); ret = EFI_SUCCESS; - else + } else { ret = EFI_NOT_FOUND; + } out: return EFI_EXIT(ret); } @@ -616,9 +637,72 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file, efi_uintn_t buffer_size, void *buffer) { - EFI_ENTRY("%p, %p, %zu, %p", file, info_type, buffer_size, buffer); + struct file_handle *fh = to_fh(file); + efi_status_t ret = EFI_UNSUPPORTED; + + EFI_ENTRY("%p, %pUl, %zu, %p", file, info_type, buffer_size, buffer); + + if (!guidcmp(info_type, &efi_file_info_guid)) { + struct efi_file_info *info = (struct efi_file_info *)buffer; + char *filename = basename(fh); + char *new_file_name, *pos; + loff_t file_size; - return EFI_EXIT(EFI_UNSUPPORTED); + if (buffer_size < sizeof(struct efi_file_info)) { + ret = EFI_BAD_BUFFER_SIZE; + goto out; + } + /* We cannot change the directory attribute */ + if (!fh->isdir != !(info->attribute & EFI_FILE_DIRECTORY)) { + ret = EFI_ACCESS_DENIED; + goto out; + } + /* Check for renaming */ + new_file_name = malloc(utf16_utf8_strlen(info->file_name)); + if (!new_file_name) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + pos = new_file_name; + utf16_utf8_strcpy(&pos, info->file_name); + if (strcmp(new_file_name, filename)) { + /* TODO: we do not support renaming */ + EFI_PRINT("Renaming not supported\n"); + free(new_file_name); + ret = EFI_ACCESS_DENIED; + goto out; + } + free(new_file_name); + /* Check for truncation */ + if (set_blk_dev(fh)) { + ret = EFI_DEVICE_ERROR; + goto out; + } + if (fs_size(fh->path, &file_size)) { + ret = EFI_DEVICE_ERROR; + goto out; + } + if (file_size != info->file_size) { + /* TODO: we do not support truncation */ + EFI_PRINT("Truncation not supported\n"); + ret = EFI_ACCESS_DENIED; + goto out; + } + /* + * We do not care for the other attributes + * TODO: Support read only + */ + ret = EFI_SUCCESS; + } else if (!guidcmp(info_type, &efi_file_system_info_guid)) { + if (buffer_size < sizeof(struct efi_file_system_info)) { + ret = EFI_BAD_BUFFER_SIZE; + goto out; + } + } else { + ret = EFI_UNSUPPORTED; + } +out: + return EFI_EXIT(ret); } static efi_status_t EFIAPI efi_file_flush(struct efi_file_handle *file) |