efi_loader: enable file SetInfo()
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Sat, 6 Apr 2019 16:17:39 +0000 (18:17 +0200)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Sun, 7 Apr 2019 12:17:06 +0000 (14:17 +0200)
EFI shell command edit uses the SetInfo() methods to unset the read only
attribute of the file to be edited. So let efi_file_setinfo() return
success in this case.

Return an error if the function is called for to rename or resize a file
as we do not support this yet.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
lib/efi_loader/efi_file.c

index e7ea2466fe425f3842a71e74cda59eb410ef6518..182d735e6bc28cadf6a83823cdb5d344020480e0 100644 (file)
@@ -637,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);
 
-       return EFI_EXIT(EFI_UNSUPPORTED);
+       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;
+
+               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)