]> Git Repo - u-boot.git/blobdiff - lib/efi_loader/efi_file.c
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-usb into...
[u-boot.git] / lib / efi_loader / efi_file.c
index 204105e25afd8b34ece680cd9b4042016fde3e65..520c730220a96e7089c37972ce72ddd64ec20b48 100644 (file)
@@ -246,10 +246,10 @@ error:
        return NULL;
 }
 
-static efi_status_t efi_file_open_int(struct efi_file_handle *this,
-                                     struct efi_file_handle **new_handle,
-                                     u16 *file_name, u64 open_mode,
-                                     u64 attributes)
+efi_status_t efi_file_open_int(struct efi_file_handle *this,
+                              struct efi_file_handle **new_handle,
+                              u16 *file_name, u64 open_mode,
+                              u64 attributes)
 {
        struct file_handle *fh = to_fh(this);
        efi_status_t ret;
@@ -369,11 +369,17 @@ static efi_status_t file_close(struct file_handle *fh)
        return EFI_SUCCESS;
 }
 
-static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file)
+efi_status_t efi_file_close_int(struct efi_file_handle *file)
 {
        struct file_handle *fh = to_fh(file);
+
+       return file_close(fh);
+}
+
+static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file)
+{
        EFI_ENTRY("%p", file);
-       return EFI_EXIT(file_close(fh));
+       return EFI_EXIT(efi_file_close_int(file));
 }
 
 static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
@@ -480,6 +486,17 @@ static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size,
        return EFI_SUCCESS;
 }
 
+static void rtc2efi(struct efi_time *time, struct rtc_time *tm)
+{
+       memset(time, 0, sizeof(struct efi_time));
+       time->year = tm->tm_year;
+       time->month = tm->tm_mon;
+       time->day = tm->tm_mday;
+       time->hour = tm->tm_hour;
+       time->minute = tm->tm_min;
+       time->second = tm->tm_sec;
+}
+
 static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
                void *buffer)
 {
@@ -535,6 +552,10 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
        info->size = required_size;
        info->file_size = dent->size;
        info->physical_size = dent->size;
+       info->attribute = dent->attr;
+       rtc2efi(&info->create_time, &dent->create_time);
+       rtc2efi(&info->modification_time, &dent->change_time);
+       rtc2efi(&info->last_access_time, &dent->access_time);
 
        if (dent->type == FS_DT_DIR)
                info->attribute |= EFI_FILE_DIRECTORY;
@@ -547,14 +568,14 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size,
        return EFI_SUCCESS;
 }
 
-static efi_status_t efi_file_read_int(struct efi_file_handle *this,
-                                     efi_uintn_t *buffer_size, void *buffer)
+efi_status_t efi_file_read_int(struct efi_file_handle *this,
+                              efi_uintn_t *buffer_size, void *buffer)
 {
        struct file_handle *fh = to_fh(this);
        efi_status_t ret = EFI_SUCCESS;
        u64 bs;
 
-       if (!this || !buffer_size || !buffer)
+       if (!this || !buffer_size)
                return EFI_INVALID_PARAMETER;
 
        bs = *buffer_size;
@@ -758,24 +779,11 @@ out:
        return EFI_EXIT(ret);
 }
 
-/**
- * efi_file_setpos() - set current position in file
- *
- * This function implements the SetPosition service of the EFI file protocol.
- * See the UEFI spec for details.
- *
- * @file:      file handle
- * @pos:       new file position
- * Return:     status code
- */
-static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
-                                          u64 pos)
+efi_status_t efi_file_setpos_int(struct efi_file_handle *file, u64 pos)
 {
        struct file_handle *fh = to_fh(file);
        efi_status_t ret = EFI_SUCCESS;
 
-       EFI_ENTRY("%p, %llu", file, pos);
-
        if (fh->isdir) {
                if (pos != 0) {
                        ret = EFI_UNSUPPORTED;
@@ -797,6 +805,28 @@ static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
        fh->offset = pos;
 
 error:
+       return ret;
+}
+
+/**
+ * efi_file_setpos() - set current position in file
+ *
+ * This function implements the SetPosition service of the EFI file protocol.
+ * See the UEFI spec for details.
+ *
+ * @file:      file handle
+ * @pos:       new file position
+ * Return:     status code
+ */
+static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file,
+                                          u64 pos)
+{
+       efi_status_t ret = EFI_SUCCESS;
+
+       EFI_ENTRY("%p, %llu", file, pos);
+
+       ret = efi_file_setpos_int(file, pos);
+
        return EFI_EXIT(ret);
 }
 
@@ -809,7 +839,7 @@ static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file,
        efi_status_t ret = EFI_SUCCESS;
        u16 *dst;
 
-       EFI_ENTRY("%p, %pUl, %p, %p", file, info_type, buffer_size, buffer);
+       EFI_ENTRY("%p, %pUs, %p, %p", file, info_type, buffer_size, buffer);
 
        if (!file || !info_type || !buffer_size ||
            (*buffer_size && !buffer)) {
@@ -909,7 +939,7 @@ static efi_status_t EFIAPI efi_file_setinfo(struct efi_file_handle *file,
        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);
+       EFI_ENTRY("%p, %pUs, %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;
@@ -1068,8 +1098,17 @@ static const struct efi_file_handle efi_file_handle_protocol = {
 /**
  * efi_file_from_path() - open file via device path
  *
+ * The device path @fp consists of the device path of the handle with the
+ * simple file system protocol and one or more file path device path nodes.
+ * The concatenation of all file path names provides the total file path.
+ *
+ * The code starts at the first file path node and tries to open that file or
+ * directory. If there is a succeding file path node, the code opens it relative
+ * to this directory and continues iterating until reaching the last file path
+ * node.
+ *
  * @fp:                device path
- * @return:    EFI_FILE_PROTOCOL for the file or NULL
+ * Return:     EFI_FILE_PROTOCOL for the file or NULL
  */
 struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
 {
@@ -1098,16 +1137,27 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
                        container_of(fp, struct efi_device_path_file_path, dp);
                struct efi_file_handle *f2;
                u16 *filename;
+               size_t filename_sz;
 
                if (!EFI_DP_TYPE(fp, MEDIA_DEVICE, FILE_PATH)) {
                        printf("bad file path!\n");
-                       f->close(f);
+                       EFI_CALL(f->close(f));
                        return NULL;
                }
 
-               filename = u16_strdup(fdp->str);
+               /*
+                * UEFI specification requires pointers that are passed to
+                * protocol member functions to be aligned.  So memcpy it
+                * unconditionally
+                */
+               if (fdp->dp.length <= offsetof(struct efi_device_path_file_path, str))
+                       return NULL;
+               filename_sz = fdp->dp.length -
+                       offsetof(struct efi_device_path_file_path, str);
+               filename = malloc(filename_sz);
                if (!filename)
                        return NULL;
+               memcpy(filename, fdp->str, filename_sz);
                EFI_CALL(ret = f->open(f, &f2, filename,
                                       EFI_FILE_MODE_READ, 0));
                free(filename);
@@ -1123,17 +1173,23 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp)
        return f;
 }
 
+efi_status_t efi_open_volume_int(struct efi_simple_file_system_protocol *this,
+                                struct efi_file_handle **root)
+{
+       struct file_system *fs = to_fs(this);
+
+       *root = file_open(fs, NULL, NULL, 0, 0);
+
+       return EFI_SUCCESS;
+}
+
 static efi_status_t EFIAPI
 efi_open_volume(struct efi_simple_file_system_protocol *this,
                struct efi_file_handle **root)
 {
-       struct file_system *fs = to_fs(this);
-
        EFI_ENTRY("%p, %p", this, root);
 
-       *root = file_open(fs, NULL, NULL, 0, 0);
-
-       return EFI_EXIT(EFI_SUCCESS);
+       return EFI_EXIT(efi_open_volume_int(this, root));
 }
 
 struct efi_simple_file_system_protocol *
This page took 0.035401 seconds and 4 git commands to generate.