static efi_status_t EFIAPI efi_file_getinfo(struct efi_file_handle *file, const efi_guid_t *info_type, efi_uintn_t *buffer_size, void *buffer) { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS; EFI_ENTRY("%p, %p, %p, %p", file, info_type, buffer_size, buffer); if (!guidcmp(info_type, &efi_file_info_guid)) { struct efi_file_info *info = buffer; char *filename = basename(fh); unsigned int required_size; loff_t file_size; /* check buffer size: */ required_size = sizeof(*info) + 2 * (strlen(filename) + 1); if (*buffer_size < required_size) { *buffer_size = required_size; ret = EFI_BUFFER_TOO_SMALL; goto error; } if (set_blk_dev(fh)) { ret = EFI_DEVICE_ERROR; goto error; } if (fs_size(fh->path, &file_size)) { ret = EFI_DEVICE_ERROR; goto error; } memset(info, 0, required_size); info->size = required_size; info->file_size = file_size; info->physical_size = file_size; if (fh->isdir) info->attribute |= EFI_FILE_DIRECTORY; ascii2unicode((u16 *)info->file_name, filename); } else if (!guidcmp(info_type, &efi_file_system_info_guid)) { struct efi_file_system_info *info = buffer; disk_partition_t part; efi_uintn_t required_size; int r; if (fh->fs->part >= 1) r = part_get_info(fh->fs->desc, fh->fs->part, &part); else r = part_get_info_whole_disk(fh->fs->desc, &part); if (r < 0) { ret = EFI_DEVICE_ERROR; goto error; } required_size = sizeof(info) + 2 * (strlen((const char *)part.name) + 1); if (*buffer_size < required_size) { *buffer_size = required_size; ret = EFI_BUFFER_TOO_SMALL; goto error; } memset(info, 0, required_size); info->size = required_size; info->read_only = true; info->volume_size = part.size * part.blksz; info->free_space = 0; info->block_size = part.blksz; /* * TODO: The volume label is not available in U-Boot. * Use the partition name as substitute. */ ascii2unicode((u16 *)info->volume_label, (const char *)part.name); } else { ret = EFI_UNSUPPORTED; } error: return EFI_EXIT(ret); }
int blk_get_device_part_str(const char *ifname, const char *dev_part_str, struct blk_desc **dev_desc, disk_partition_t *info, int allow_whole_dev) { int ret = -1; const char *part_str; char *dup_str = NULL; const char *dev_str; int dev; char *ep; int p; int part; disk_partition_t tmpinfo; #ifdef CONFIG_SANDBOX /* * Special-case a pseudo block device "hostfs", to allow access to the * host's own filesystem. */ if (0 == strcmp(ifname, "hostfs")) { *dev_desc = NULL; info->start = 0; info->size = 0; info->blksz = 0; info->bootable = 0; strcpy((char *)info->type, BOOT_PART_TYPE); strcpy((char *)info->name, "Sandbox host"); #if CONFIG_IS_ENABLED(PARTITION_UUIDS) info->uuid[0] = 0; #endif #ifdef CONFIG_PARTITION_TYPE_GUID info->type_guid[0] = 0; #endif return 0; } #endif #ifdef CONFIG_CMD_UBIFS /* * Special-case ubi, ubi goes through a mtd, rathen then through * a regular block device. */ if (0 == strcmp(ifname, "ubi")) { if (!ubifs_is_mounted()) { printf("UBIFS not mounted, use ubifsmount to mount volume first!\n"); return -1; } *dev_desc = NULL; memset(info, 0, sizeof(*info)); strcpy((char *)info->type, BOOT_PART_TYPE); strcpy((char *)info->name, "UBI"); #if CONFIG_IS_ENABLED(PARTITION_UUIDS) info->uuid[0] = 0; #endif return 0; } #endif /* If no dev_part_str, use bootdevice environment variable */ if (!dev_part_str || !strlen(dev_part_str) || !strcmp(dev_part_str, "-")) dev_part_str = env_get("bootdevice"); /* If still no dev_part_str, it's an error */ if (!dev_part_str) { printf("** No device specified **\n"); goto cleanup; } /* Separate device and partition ID specification */ part_str = strchr(dev_part_str, ':'); if (part_str) { dup_str = strdup(dev_part_str); dup_str[part_str - dev_part_str] = 0; dev_str = dup_str; part_str++; } else { dev_str = dev_part_str; } /* Look up the device */ dev = blk_get_device_by_str(ifname, dev_str, dev_desc); if (dev < 0) goto cleanup; /* Convert partition ID string to number */ if (!part_str || !*part_str) { part = PART_UNSPECIFIED; } else if (!strcmp(part_str, "auto")) { part = PART_AUTO; } else { /* Something specified -> use exactly that */ part = (int)simple_strtoul(part_str, &ep, 16); /* * Less than whole string converted, * or request for whole device, but caller requires partition. */ if (*ep || (part == 0 && !allow_whole_dev)) { printf("** Bad partition specification %s %s **\n", ifname, dev_part_str); goto cleanup; } } /* * No partition table on device, * or user requested partition 0 (entire device). */ if (((*dev_desc)->part_type == PART_TYPE_UNKNOWN) || (part == 0)) { if (!(*dev_desc)->lba) { printf("** Bad device size - %s %s **\n", ifname, dev_str); goto cleanup; } /* * If user specified a partition ID other than 0, * or the calling command only accepts partitions, * it's an error. */ if ((part > 0) || (!allow_whole_dev)) { printf("** No partition table - %s %s **\n", ifname, dev_str); goto cleanup; } (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); part_get_info_whole_disk(*dev_desc, info); ret = 0; goto cleanup; } /* * Now there's known to be a partition table, * not specifying a partition means to pick partition 1. */ if (part == PART_UNSPECIFIED) part = 1; /* * If user didn't specify a partition number, or did specify something * other than "auto", use that partition number directly. */ if (part != PART_AUTO) { ret = part_get_info(*dev_desc, part, info); if (ret) { printf("** Invalid partition %d **\n", part); goto cleanup; } } else { /* * Find the first bootable partition. * If none are bootable, fall back to the first valid partition. */ part = 0; for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { ret = part_get_info(*dev_desc, p, info); if (ret) continue; /* * First valid partition, or new better partition? * If so, save partition ID. */ if (!part || info->bootable) part = p; /* Best possible partition? Stop searching. */ if (info->bootable) break; /* * We now need to search further for best possible. * If we what we just queried was the best so far, * save the info since we over-write it next loop. */ if (part == p) tmpinfo = *info; } /* If we found any acceptable partition */ if (part) { /* * If we searched all possible partition IDs, * return the first valid partition we found. */ if (p == MAX_SEARCH_PARTITIONS + 1) *info = tmpinfo; } else { printf("** No valid partitions found **\n"); ret = -1; goto cleanup; } } if (strncmp((char *)info->type, BOOT_PART_TYPE, sizeof(info->type)) != 0) { printf("** Invalid partition type \"%.32s\"" " (expect \"" BOOT_PART_TYPE "\")\n", info->type); ret = -1; goto cleanup; } (*dev_desc)->log2blksz = LOG2((*dev_desc)->blksz); ret = part; goto cleanup; cleanup: free(dup_str); return ret; }