diff options
author | Tom Rini | 2021-01-23 19:07:00 -0500 |
---|---|---|
committer | Tom Rini | 2021-01-23 19:07:00 -0500 |
commit | 69d29fe1c0aeb33f42633a75555d30b7921c02aa (patch) | |
tree | b3b960b8e0b89202e0f8389efc4c79bdc3299a49 | |
parent | e716c9022970dac9be15856a6651a07132463578 (diff) | |
parent | 8d0949b3ed6985377682d7ec260be07ef26ef6d4 (diff) |
Merge tag 'efi-2021-04-rc1-3' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
Pull request for UEFI sub-system for efi-2021-04-rc1-3
Bug fixes for UEFI sub-system:
* correct value of EFI_BLOCK_IO_PROTOCOL.Media.LastBlock
* correct GUID when closing of EFI_LOAD_FILE_PROTOCOL
* error handling in mkeficapsule tool
Bug fixes for FAT file system:
* consistent error handling for flush dir()
-rw-r--r-- | cmd/efidebug.c | 12 | ||||
-rw-r--r-- | fs/fat/fat.c | 32 | ||||
-rw-r--r-- | fs/fat/fat_write.c | 78 | ||||
-rw-r--r-- | include/fat.h | 7 | ||||
-rw-r--r-- | lib/efi_loader/efi_boottime.c | 14 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_disk.c | 30 | ||||
-rw-r--r-- | tools/mkeficapsule.c | 41 |
8 files changed, 126 insertions, 90 deletions
diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 9a2d4ddd5ef..83bc2196a5a 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -189,14 +189,16 @@ static int do_efi_capsule_res(struct cmd_tbl *cmdtp, int flag, ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, NULL)); if (ret == EFI_BUFFER_TOO_SMALL) { result = malloc(size); + if (!result) + return CMD_RET_FAILURE; ret = EFI_CALL(RT->get_variable(var_name16, &guid, NULL, &size, result)); - if (ret != EFI_SUCCESS) { - free(result); - printf("Failed to get %ls\n", var_name16); + } + if (ret != EFI_SUCCESS) { + free(result); + printf("Failed to get %ls\n", var_name16); - return CMD_RET_FAILURE; - } + return CMD_RET_FAILURE; } printf("Result total size: 0x%x\n", result->variable_total_size); diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 157dad60a48..fb6ce094ac1 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -123,16 +123,16 @@ static void get_name(dir_entry *dirent, char *s_name) { char *ptr; - memcpy(s_name, dirent->name, 8); + memcpy(s_name, dirent->nameext.name, 8); s_name[8] = '\0'; ptr = s_name; while (*ptr && *ptr != ' ') ptr++; if (dirent->lcase & CASE_LOWER_BASE) downcase(s_name, (unsigned)(ptr - s_name)); - if (dirent->ext[0] && dirent->ext[0] != ' ') { + if (dirent->nameext.ext[0] && dirent->nameext.ext[0] != ' ') { *ptr++ = '.'; - memcpy(ptr, dirent->ext, 3); + memcpy(ptr, dirent->nameext.ext, 3); if (dirent->lcase & CASE_LOWER_EXT) downcase(ptr, 3); ptr[3] = '\0'; @@ -472,16 +472,15 @@ static int slot2str(dir_slot *slotptr, char *l_name, int *idx) } /* Calculate short name checksum */ -static __u8 mkcksum(const char name[8], const char ext[3]) +static __u8 mkcksum(struct nameext *nameext) { int i; + u8 *pos = (void *)nameext; __u8 ret = 0; - for (i = 0; i < 8; i++) - ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i]; - for (i = 0; i < 3; i++) - ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i]; + for (i = 0; i < 11; i++) + ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + pos[i]; return ret; } @@ -896,7 +895,7 @@ static dir_entry *next_dent(fat_itr *itr) } /* have we reached the last valid entry? */ - if (itr->dent->name[0] == 0) + if (itr->dent->nameext.name[0] == 0) return NULL; return itr->dent; @@ -905,7 +904,7 @@ static dir_entry *next_dent(fat_itr *itr) static dir_entry *extract_vfat_name(fat_itr *itr) { struct dir_entry *dent = itr->dent; - int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK; + int seqn = itr->dent->nameext.name[0] & ~LAST_LONG_ENTRY_MASK; u8 chksum, alias_checksum = ((dir_slot *)dent)->alias_checksum; int n = 0; @@ -932,18 +931,19 @@ static dir_entry *extract_vfat_name(fat_itr *itr) * We are now at the short file name entry. * If it is marked as deleted, just skip it. */ - if (dent->name[0] == DELETED_FLAG || - dent->name[0] == aRING) + if (dent->nameext.name[0] == DELETED_FLAG || + dent->nameext.name[0] == aRING) return NULL; itr->l_name[n] = '\0'; - chksum = mkcksum(dent->name, dent->ext); + chksum = mkcksum(&dent->nameext); /* checksum mismatch could mean deleted file, etc.. skip it: */ if (chksum != alias_checksum) { debug("** chksum=%x, alias_checksum=%x, l_name=%s, s_name=%8s.%3s\n", - chksum, alias_checksum, itr->l_name, dent->name, dent->ext); + chksum, alias_checksum, itr->l_name, dent->nameext.name, + dent->nameext.ext); return NULL; } @@ -984,12 +984,12 @@ static int fat_itr_next(fat_itr *itr) itr->dent_rem = itr->remaining; itr->dent_start = itr->dent; itr->dent_clust = itr->clust; - if (dent->name[0] == DELETED_FLAG) + if (dent->nameext.name[0] == DELETED_FLAG) continue; if (dent->attr & ATTR_VOLUME) { if ((dent->attr & ATTR_VFAT) == ATTR_VFAT && - (dent->name[0] & LAST_LONG_ENTRY_MASK)) { + (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) { /* long file name */ dent = extract_vfat_name(itr); /* diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 20a54a24189..0132ef9b42f 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -275,7 +275,7 @@ static int fat_find_empty_dentries(fat_itr *itr, int count) log_debug("Not enough directory entries available\n"); return -ENOSPC; } - switch (itr->dent->name[0]) { + switch (itr->dent->nameext.name[0]) { case 0x00: case DELETED_FLAG: if (!n) { @@ -399,7 +399,7 @@ fill_dir_slot(fat_itr *itr, const char *l_name, const char *shortname) int idx = 0, ret; /* Get short file name checksum value */ - checksum = mkcksum(shortname, shortname + 8); + checksum = mkcksum((void *)shortname); do { memset(slotptr, 0x00, sizeof(dir_slot)); @@ -418,8 +418,12 @@ fill_dir_slot(fat_itr *itr, const char *l_name, const char *shortname) slotptr--; counter--; - if (itr->remaining == 0) - flush_dir(itr); + if (!itr->remaining) { + /* Write directory table to device */ + ret = flush_dir(itr); + if (ret) + return ret; + } next_dent(itr); if (!itr->dent) @@ -639,15 +643,23 @@ set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size) buffer, size); } -static int -flush_dir(fat_itr *itr) +/** + * flush_dir() - flush directory + * + * @itr: directory iterator + * Return: 0 for success, -EIO on error + */ +static int flush_dir(fat_itr *itr) { fsdata *mydata = itr->fsdata; u32 startsect, sect_offset, nsects; + int ret; - if (!itr->is_root || mydata->fatsize == 32) - return set_cluster(mydata, itr->clust, itr->block, - mydata->clust_size * mydata->sect_size); + if (!itr->is_root || mydata->fatsize == 32) { + ret = set_cluster(mydata, itr->clust, itr->block, + mydata->clust_size * mydata->sect_size); + goto out; + } sect_offset = itr->clust * mydata->clust_size; startsect = mydata->rootdir_sect + sect_offset; @@ -655,8 +667,14 @@ flush_dir(fat_itr *itr) nsects = min_t(u32, mydata->clust_size, mydata->rootdir_size - sect_offset); - return set_sectors(mydata, startsect, itr->block, - nsects * mydata->sect_size); + ret = set_sectors(mydata, startsect, itr->block, + nsects * mydata->sect_size); +out: + if (ret) { + log_err("Error: writing directory entry\n"); + return -EIO; + } + return 0; } /* @@ -1151,7 +1169,7 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, dentptr->attr = attr; - memcpy(dentptr->name, shortname, SHORT_NAME_SIZE); + memcpy(&dentptr->nameext, shortname, SHORT_NAME_SIZE); } /** @@ -1176,7 +1194,7 @@ static dir_entry *find_directory_entry(fat_itr *itr, char *filename) if (!match) continue; - if (itr->dent->name[0] == '\0') + if (itr->dent->nameext.name[0] == '\0') return NULL; else return itr->dent; @@ -1390,10 +1408,6 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer, /* Write directory table to device */ ret = flush_dir(itr); - if (ret) { - printf("Error: writing directory entry\n"); - ret = -EIO; - } exit: free(filename_copy); @@ -1456,14 +1470,10 @@ static int delete_single_dentry(fat_itr *itr) struct dir_entry *dent = itr->dent; memset(dent, 0, sizeof(*dent)); - dent->name[0] = DELETED_FLAG; + dent->nameext.name[0] = DELETED_FLAG; - if (!itr->remaining) { - if (flush_dir(itr)) { - printf("error: writing directory entry\n"); - return -EIO; - } - } + if (!itr->remaining) + return flush_dir(itr); return 0; } @@ -1476,7 +1486,7 @@ static int delete_single_dentry(fat_itr *itr) static int delete_long_name(fat_itr *itr) { struct dir_entry *dent = itr->dent; - int seqn = itr->dent->name[0] & ~LAST_LONG_ENTRY_MASK; + int seqn = itr->dent->nameext.name[0] & ~LAST_LONG_ENTRY_MASK; while (seqn--) { int ret; @@ -1521,7 +1531,7 @@ static int delete_dentry_long(fat_itr *itr) dent = itr->dent_start; /* Delete long name */ if ((dent->attr & ATTR_VFAT) == ATTR_VFAT && - (dent->name[0] & LAST_LONG_ENTRY_MASK)) { + (dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) { int ret; ret = delete_long_name(itr); @@ -1530,12 +1540,7 @@ static int delete_dentry_long(fat_itr *itr) } /* Delete short name */ delete_single_dentry(itr); - if (flush_dir(itr)) { - printf("error: writing directory entry\n"); - return -EIO; - } - - return 0; + return flush_dir(itr); } int fat_unlink(const char *filename) @@ -1707,12 +1712,10 @@ int fat_mkdir(const char *new_dirname) } memset(dotdent, 0, bytesperclust); - memcpy(dotdent[0].name, ". ", 8); - memcpy(dotdent[0].ext, " ", 3); + memcpy(&dotdent[0].nameext, ". ", 11); dotdent[0].attr = ATTR_DIR | ATTR_ARCH; - memcpy(dotdent[1].name, ".. ", 8); - memcpy(dotdent[1].ext, " ", 3); + memcpy(&dotdent[1].nameext, ".. ", 11); dotdent[1].attr = ATTR_DIR | ATTR_ARCH; if (itr->is_root) @@ -1739,13 +1742,12 @@ int fat_mkdir(const char *new_dirname) ret = flush_dirty_fat_buffer(mydata); if (ret) { printf("Error: flush fat buffer\n"); + ret = -EIO; goto exit; } /* Write directory table to device */ ret = flush_dir(itr); - if (ret) - printf("Error: writing directory entry\n"); exit: free(dirname_copy); diff --git a/include/fat.h b/include/fat.h index b9f273f381f..bd8e450b33a 100644 --- a/include/fat.h +++ b/include/fat.h @@ -132,8 +132,13 @@ typedef struct volume_info #define CASE_LOWER_BASE 8 /* base (name) is lower case */ #define CASE_LOWER_EXT 16 /* extension is lower case */ +struct nameext { + char name[8]; + char ext[3]; +}; + typedef struct dir_entry { - char name[8],ext[3]; /* Name and extension */ + struct nameext nameext; /* Name and extension */ __u8 attr; /* Attribute bits */ __u8 lcase; /* Case for name and ext (CASE_LOWER_x) */ __u8 ctime_ms; /* Creation time, milliseconds */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b2cb0160c08..ce658a8e733 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -687,8 +687,15 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, return EFI_INVALID_PARAMETER; } + /* + * The UEFI specification requires event notification levels to be + * > TPL_APPLICATION and <= TPL_HIGH_LEVEL. + * + * Parameter NotifyTpl should not be checked if it is not used. + */ if ((type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) && - (!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS)) + (!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS || + notify_tpl == TPL_APPLICATION)) return EFI_INVALID_PARAMETER; ret = efi_allocate_pool(pool_type, sizeof(struct efi_event), @@ -1990,10 +1997,7 @@ efi_status_t efi_load_image_from_path(bool boot_policy, if (ret != EFI_SUCCESS) efi_free_pages(addr, pages); out: - if (load_file_protocol) - EFI_CALL(efi_close_protocol(device, - &efi_guid_load_file2_protocol, - efi_root, NULL)); + EFI_CALL(efi_close_protocol(device, guid, efi_root, NULL)); if (ret == EFI_SUCCESS) { *buffer = (void *)(uintptr_t)addr; *size = buffer_size; diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index dad1b0fcf7c..0d5a7b63ec8 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -764,7 +764,7 @@ static efi_status_t efi_capsule_scan_dir(u16 ***files, unsigned int *num) goto err; /* make a list */ - tmp_files = malloc(count * sizeof(*files)); + tmp_files = malloc(count * sizeof(*tmp_files)); if (!tmp_files) { ret = EFI_OUT_OF_RESOURCES; goto err; diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 26b953461bc..c0804effdef 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -343,7 +343,7 @@ static int efi_fs_exists(struct blk_desc *desc, int part) * @if_typename: interface name for block device * @desc: internal block device * @dev_index: device index for block device - * @offset: offset into disk for simple partitions + * @part_info: partition info * @part: partition * @disk: pointer to receive the created handle * Return: disk object @@ -354,7 +354,7 @@ static efi_status_t efi_disk_add_dev( const char *if_typename, struct blk_desc *desc, int dev_index, - lbaint_t offset, + struct disk_partition *part_info, unsigned int part, struct efi_disk_obj **disk) { @@ -374,7 +374,7 @@ static efi_status_t efi_disk_add_dev( efi_add_handle(&diskobj->header); /* Fill in object data */ - if (part) { + if (part_info) { struct efi_device_path *node = efi_dp_part_node(desc, part); struct efi_handler *handler; void *protocol_interface; @@ -396,8 +396,12 @@ static efi_status_t efi_disk_add_dev( diskobj->dp = efi_dp_append_node(dp_parent, node); efi_free_pool(node); + diskobj->offset = part_info->start; + diskobj->media.last_block = part_info->size - 1; } else { diskobj->dp = efi_dp_from_part(desc, part); + diskobj->offset = 0; + diskobj->media.last_block = desc->lba - 1; } diskobj->part = part; @@ -432,7 +436,6 @@ static efi_status_t efi_disk_add_dev( diskobj->ops = block_io_disk_template; diskobj->ifname = if_typename; diskobj->dev_index = dev_index; - diskobj->offset = offset; diskobj->desc = desc; /* Fill in EFI IO Media info (for read/write callbacks) */ @@ -445,13 +448,21 @@ static efi_status_t efi_disk_add_dev( diskobj->media.media_id = 1; diskobj->media.block_size = desc->blksz; diskobj->media.io_align = desc->blksz; - diskobj->media.last_block = desc->lba - offset; if (part) diskobj->media.logical_partition = 1; diskobj->ops.media = &diskobj->media; if (disk) *disk = diskobj; + EFI_PRINT("BlockIO: part %u, present %d, logical %d, removable %d" + ", offset " LBAF ", last_block %llu\n", + diskobj->part, + diskobj->media.media_present, + diskobj->media.logical_partition, + diskobj->media.removable_media, + diskobj->offset, + diskobj->media.last_block); + /* Store first EFI system partition */ if (part && !efi_system_partition.if_type) { int r; @@ -493,7 +504,6 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, { int disks = 0; char devname[32] = { 0 }; /* dp->str is u16[32] long */ - struct disk_partition info; int part; struct efi_device_path *dp = NULL; efi_status_t ret; @@ -506,12 +516,14 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, /* Add devices for each partition */ for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { + struct disk_partition info; + if (part_get_info(desc, part, &info)) continue; snprintf(devname, sizeof(devname), "%s:%d", pdevname, part); ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid, - info.start, part, NULL); + &info, part, NULL); if (ret != EFI_SUCCESS) { log_err("Adding partition %s failed\n", pdevname); continue; @@ -553,7 +565,7 @@ efi_status_t efi_disk_register(void) /* Add block device for the full device */ log_info("Scanning disk %s...\n", dev->name); ret = efi_disk_add_dev(NULL, NULL, if_typename, - desc, desc->devnum, 0, 0, &disk); + desc, desc->devnum, NULL, 0, &disk); if (ret == EFI_NOT_READY) { log_notice("Disk %s not ready\n", dev->name); continue; @@ -599,7 +611,7 @@ efi_status_t efi_disk_register(void) /* Add block device for the full device */ ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, - i, 0, 0, &disk); + i, NULL, 0, &disk); if (ret == EFI_NOT_READY) { log_notice("Disk %s not ready\n", devname); continue; diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c index 270943fc90a..162494907a8 100644 --- a/tools/mkeficapsule.c +++ b/tools/mkeficapsule.c @@ -137,8 +137,8 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, bool overlay) { int ret; - int srcfd = 0; - int destfd = 0; + int srcfd = -1; + int destfd = -1; void *sptr = NULL; void *dptr = NULL; off_t src_size; @@ -150,6 +150,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, if (srcfd == -1) { fprintf(stderr, "%s: Can't open %s: %s\n", __func__, pkey_file, strerror(errno)); + ret = -1; goto err; } @@ -157,6 +158,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, if (ret == -1) { fprintf(stderr, "%s: Can't stat %s: %s\n", __func__, pkey_file, strerror(errno)); + ret = -1; goto err; } @@ -164,9 +166,10 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, /* mmap the public key esl file */ sptr = mmap(0, src_size, PROT_READ, MAP_SHARED, srcfd, 0); - if ((sptr == MAP_FAILED) || (errno != 0)) { + if (sptr == MAP_FAILED) { fprintf(stderr, "%s: Failed to mmap %s:%s\n", __func__, pkey_file, strerror(errno)); + ret = -1; goto err; } @@ -175,6 +178,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, if (destfd == -1) { fprintf(stderr, "%s: Can't open %s: %s\n", __func__, dtb_file, strerror(errno)); + ret = -1; goto err; } @@ -189,21 +193,24 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, if (ftruncate(destfd, dtb.st_size)) { fprintf(stderr, "%s: Can't expand %s: %s\n", __func__, dtb_file, strerror(errno)); - goto err;; + ret = -1; + goto err; } errno = 0; /* mmap the dtb file */ dptr = mmap(0, dtb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, destfd, 0); - if ((dptr == MAP_FAILED) || (errno != 0)) { + if (dptr == MAP_FAILED) { fprintf(stderr, "%s: Failed to mmap %s:%s\n", __func__, dtb_file, strerror(errno)); + ret = -1; goto err; } if (fdt_check_header(dptr)) { fprintf(stderr, "%s: Invalid FDT header\n", __func__); + ret = -1; goto err; } @@ -211,6 +218,7 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, if (ret) { fprintf(stderr, "%s: Cannot expand FDT: %s\n", __func__, fdt_strerror(ret)); + ret = -1; goto err; } @@ -219,10 +227,11 @@ static int add_public_key(const char *pkey_file, const char *dtb_file, if (ret < 0) { fprintf(stderr, "%s: Unable to add public key to the FDT\n", __func__); + ret = -1; goto err; } - return 0; + ret = 0; err: if (sptr) @@ -231,13 +240,13 @@ err: if (dptr) munmap(dptr, dtb.st_size); - if (srcfd >= 0) + if (srcfd != -1) close(srcfd); - if (destfd >= 0) + if (destfd != -1) close(destfd); - return -1; + return ret; } static int create_fwbin(char *path, char *bin, efi_guid_t *guid, @@ -310,6 +319,9 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid, image.version = 0x00000003; memcpy(&image.update_image_type_id, guid, sizeof(*guid)); image.update_image_index = index; + image.reserved[0] = 0; + image.reserved[1] = 0; + image.reserved[2] = 0; image.update_image_size = bin_stat.st_size; image.update_vendor_code_size = 0; /* none */ image.update_hardware_instance = instance; @@ -421,26 +433,25 @@ int main(int argc, char **argv) /* need a fit image file or raw image file */ if (!file && !pkey_file && !dtb_file) { - printf("%s: %d\n", __func__, __LINE__); print_usage(); - return -1; + exit(EXIT_FAILURE); } if (pkey_file && dtb_file) { ret = add_public_key(pkey_file, dtb_file, overlay); if (ret == -1) { printf("Adding public key to the dtb failed\n"); - return -1; + exit(EXIT_FAILURE); } else { - return 0; + exit(EXIT_SUCCESS); } } if (create_fwbin(argv[optind], file, guid, index, instance) < 0) { printf("Creating firmware capsule failed\n"); - return -1; + exit(EXIT_FAILURE); } - return 0; + exit(EXIT_SUCCESS); } |