OSDN Git Service

Use efi_error() at lots of places.
authorPeter Jones <pjones@redhat.com>
Tue, 9 Aug 2016 14:59:04 +0000 (10:59 -0400)
committerPeter Jones <pjones@redhat.com>
Wed, 10 Aug 2016 19:23:24 +0000 (15:23 -0400)
Signed-off-by: Peter Jones <pjones@redhat.com>
16 files changed:
src/creator.c
src/disk.c
src/dp-acpi.c
src/dp-hw.c
src/dp-media.c
src/dp-message.c
src/dp.c
src/dp.h
src/efivar.c
src/efivarfs.c
src/generics.h
src/guid.c
src/include/efivar/efivar-dp.h
src/lib.c
src/linux.c
src/vars.c

index 24e49b5..14d446a 100644 (file)
@@ -53,6 +53,7 @@ find_file(const char * const filepath, char **devicep, char **relpathp)
        linklen = strlen(filepath);
        if (linklen > PATH_MAX) {
                errno = ENAMETOOLONG;
+               efi_error("filepath length exceeds PATH_MAX");
                return -1;
        }
        strcpy(linkbuf, filepath);
@@ -67,8 +68,10 @@ find_file(const char * const filepath, char **devicep, char **relpathp)
                        ssize_t l;
 
                        l = readlink(linkbuf, tmp, PATH_MAX);
-                       if (l < 0)
+                       if (l < 0) {
+                               efi_error("readlink failed");
                                return -1;
+                       }
                        tmp[l] = '\0';
                        linklen = l;
                        strcpy(linkbuf, tmp);
@@ -78,8 +81,10 @@ find_file(const char * const filepath, char **devicep, char **relpathp)
        } while (1);
 
        mounts = fopen("/proc/self/mounts", "r");
-       if (mounts == NULL)
-               return rc;
+       if (mounts == NULL) {
+               efi_error("couldn not open /proc/self/mounts");
+               return -1;
+       }
 
        struct mntent *me;
        while (1) {
@@ -88,8 +93,10 @@ find_file(const char * const filepath, char **devicep, char **relpathp)
                errno = 0;
                me = getmntent(mounts);
                if (!me) {
-                       if (feof(mounts))
+                       if (feof(mounts)) {
                                errno = ENOENT;
+                               efi_error("could not find mountpoint");
+                       }
                        goto err;
                }
 
@@ -100,6 +107,7 @@ find_file(const char * const filepath, char **devicep, char **relpathp)
                if (rc < 0) {
                        if (errno == ENOENT)
                                continue;
+                       efi_error("could not stat mountpoint");
                        goto err;
                }
 
@@ -113,12 +121,17 @@ find_file(const char * const filepath, char **devicep, char **relpathp)
                        if (strncmp(linkbuf, me->mnt_dir, mntlen))
                                continue;
                        *devicep = strdup(me->mnt_fsname);
-                       if (!*devicep)
+                       if (!*devicep) {
+                               errno = ENOMEM;
+                               efi_error("strdup failed");
                                goto err;
+                       }
                        *relpathp = strdup(linkbuf + mntlen);
                        if (!*relpathp) {
                                free(*devicep);
                                *devicep = NULL;
+                               errno = ENOMEM;
+                               efi_error("strdup failed");
                                goto err;
                        }
                        ret = 0;
@@ -138,10 +151,16 @@ open_disk(struct disk_info *info, int flags)
        int rc;
 
        rc = asprintfa(&diskpath, "/dev/%s", info->disk_name);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("could not allocate buffer");
                return -1;
+       }
+
+       rc = open(diskpath, flags);
+       if (rc < 0)
+               efi_error("could not open disk");
 
-       return open(diskpath, flags);
+       return rc;
 }
 
 static char *
@@ -167,12 +186,16 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
        int saved_errno;
 
        fd = open(devpath, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("could not open device for ESP");
                goto err;
+       }
 
        rc = eb_disk_info_from_fd(fd, &info);
-       if (rc < 0 && errno != ENOSYS)
+       if (rc < 0 && errno != ENOSYS) {
+               efi_error("could not get ESP disk info");
                goto err;
+       }
 
        if (partition > 0)
                info.part = partition;
@@ -190,8 +213,10 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
                        && (!(options & EFIBOOT_ABBREV_FILE)
                            && !(options & EFIBOOT_ABBREV_HD))) {
                sz = efidp_make_edd10(buf, size, info.edd10_devicenum);
-               if (sz < 0)
+               if (sz < 0) {
+                       efi_error("could not make EDD 1.0 device path");
                        return -1;
+               }
                off = sz;
        } else if (!(options & EFIBOOT_ABBREV_FILE)
                   && !(options & EFIBOOT_ABBREV_HD)) {
@@ -201,8 +226,10 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
                 * from there.
                 */
                sz = make_blockdev_path(buf, size, &info);
-               if (sz < 0)
+               if (sz < 0) {
+                       efi_error("could not create device path");
                        return -1;
+               }
                off += sz;
        }
 
@@ -212,33 +239,44 @@ efi_va_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
                int rc;
 
                rc = set_disk_and_part_name(&info);
-               if (rc < 0)
+               if (rc < 0) {
+                       efi_error("could not set disk and partition name");
                        goto err;
+               }
 
                disk_fd = open_disk(&info,
-                   (options& EFIBOOT_OPTIONS_WRITE_SIGNATURE)?O_RDWR:O_RDONLY);
-               if (disk_fd < 0)
+                                   (options & EFIBOOT_OPTIONS_WRITE_SIGNATURE)
+                                    ? O_RDWR : O_RDONLY);
+               if (disk_fd < 0) {
+                       efi_error("could not open disk");
                        goto err;
+               }
 
                sz = make_hd_dn(buf, size, off, disk_fd, info.part, options);
                saved_errno = errno;
                close(disk_fd);
                errno = saved_errno;
-               if (sz < 0)
+               if (sz < 0) {
+                       efi_error("could not make HD() DP node");
                        goto err;
+               }
                off += sz;
        }
 
        char *filepath = strdupa(relpath);
        tilt_slashes(filepath);
        sz = efidp_make_file(buf+off, size?size-off:0, filepath);
-       if (sz < 0)
+       if (sz < 0) {
+               efi_error("could not make File() DP node");
                goto err;
+       }
        off += sz;
 
        sz = efidp_make_end_entire(buf+off, size?size-off:0);
-       if (sz < 0)
+       if (sz < 0) {
+               efi_error("could not make EndEntire DP node");
                goto err;
+       }
        off += sz;
        ret = off;
 err:
@@ -278,6 +316,8 @@ efi_generate_file_device_path_from_esp(uint8_t *buf, ssize_t size,
        saved_errno = errno;
        va_end(ap);
        errno = saved_errno;
+       if (ret < 0)
+               efi_error("could not generate File DP from ESP");
        return ret;
 }
 
@@ -297,16 +337,22 @@ efi_generate_file_device_path(uint8_t *buf, ssize_t size,
        int saved_errno;
 
        rc = find_file(filepath, &child_devpath, &relpath);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("could not canonicalize fs path");
                return -1;
+       }
 
        rc = find_parent_devpath(child_devpath, &parent_devpath);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("could not find parent device for file");
                return -1;
+       }
 
        rc = get_partition_number(child_devpath);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("could not get partition number for device");
                goto err;
+       }
 
        va_start(ap, options);
 
@@ -316,6 +362,8 @@ efi_generate_file_device_path(uint8_t *buf, ssize_t size,
        saved_errno = errno;
        va_end(ap);
        errno = saved_errno;
+       if (ret < 0)
+               efi_error("could not generate File DP from ESP");
 err:
        saved_errno = errno;
        if (child_devpath)
@@ -340,6 +388,8 @@ make_ipv4_path(uint8_t *buf, ssize_t size,
               uint16_t protocol __attribute__((unused)),
               uint8_t addr_origin __attribute__((unused)))
 {
+       ssize_t ret;
+
 #if 0
        if (local_addr == NULL || remote_addr == NULL ||
            gateway_addr == NULL || netmask == NULL) {
@@ -347,7 +397,10 @@ make_ipv4_path(uint8_t *buf, ssize_t size,
                return -1;
        }
 #endif
-       return efidp_make_ipv4(buf, size, 0, 0, 0, 0, 0, 0, 0, 0);
+       ret = efidp_make_ipv4(buf, size, 0, 0, 0, 0, 0, 0, 0, 0);
+       if (ret < 0)
+               efi_error("could not make ipv4 DP node");
+       return ret;
 }
 
 ssize_t
@@ -368,20 +421,26 @@ efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size,
        ssize_t sz;
 
        sz = make_mac_path(buf, size, ifname);
-       if (sz < 0)
+       if (sz < 0) {
+               efi_error("could not make MAC DP node");
                return -1;
+       }
        off += sz;
 
        sz = make_ipv4_path(buf+off, size?size-off:0, local_addr, remote_addr,
                            gateway_addr, netmask, local_port, remote_port,
                            protocol, addr_origin);
-       if (sz < 0)
+       if (sz < 0) {
+               efi_error("could not make IPV4 DP node");
                return -1;
+       }
        off += sz;
 
        sz = efidp_make_end_entire(buf+off, size?size-off:0);
-       if (sz < 0)
+       if (sz < 0) {
+               efi_error("could not make EndEntire DP node");
                return -1;
+       }
        off += sz;
 
        return off;
index 261c6d3..91d636d 100644 (file)
@@ -53,9 +53,15 @@ static int report_errors;
 static inline int
 is_mbr_valid(legacy_mbr *mbr)
 {
+       int ret;
        if (!mbr)
                return 0;
-       return (mbr->signature == MSDOS_MBR_SIGNATURE);
+       ret = (mbr->signature == MSDOS_MBR_SIGNATURE);
+       if (!ret) {
+               errno = ENOTTY;
+               efi_error("mbr signature is not MSDOS_MBR_SIGNATURE");
+       }
+       return ret;
 }
 
 /************************************************************
@@ -78,6 +84,8 @@ msdos_disk_get_extended_partition_info (int fd __attribute__((unused)),
 {
         /* Until I can handle these... */
         //fprintf(stderr, "Extended partition info not supported.\n");
+       errno = ENOSYS;
+       efi_error("extended partition info is not supported");
         return -1;
 }
 
@@ -104,10 +112,16 @@ msdos_disk_get_partition_info (int fd, int write_signature,
        struct stat stat;
        struct timeval tv;
 
-       if (!mbr)
+       if (!mbr) {
+               errno = EINVAL;
+               efi_error("mbr argument must not be NULL");
                return -1;
-       if (!is_mbr_valid(mbr))
+       }
+       if (!is_mbr_valid(mbr)) {
+               errno = ENOENT;
+               efi_error("mbr is not valid");
                return -1;
+       }
 
        *mbr_type = 0x01;
        *signature_type = 0x01;
@@ -127,7 +141,8 @@ msdos_disk_get_partition_info (int fd, int write_signature,
                rc = fstat(fd, &stat);
                if (rc < 0) {
                        if (report_errors)
-                               perror("stat disk");
+                               perror("fstat disk");
+                       efi_error("could not fstat disk");
                        return rc;
                }
 
@@ -135,6 +150,7 @@ msdos_disk_get_partition_info (int fd, int write_signature,
                if (rc < 0) {
                        if (report_errors)
                                perror("gettimeofday");
+                       efi_error("gettimeofday failed");
                        return rc;
                }
 
@@ -146,13 +162,21 @@ msdos_disk_get_partition_info (int fd, int write_signature,
                /* Write it to the disk */
                lseek(fd, 0, SEEK_SET);
                rc = write(fd, mbr, sizeof(*mbr));
+               if (rc < 0) {
+                       efi_error("could not write MBR signature");
+                       return rc;
+               }
        }
        *(uint32_t *)signature = mbr->unique_mbr_signature;
 
         if (num > 4) {
                /* Extended partition */
-                return msdos_disk_get_extended_partition_info(fd, mbr, num,
-                                                              start, size);
+                rc = msdos_disk_get_extended_partition_info(fd, mbr, num,
+                                                           start, size);
+               if (rc < 0) {
+                       efi_error("could not get extended partition info");
+                       return rc;
+               }
         } else if (num == 0) {
                /* Whole disk */
                 *start = 0;
@@ -182,13 +206,16 @@ get_partition_info(int fd, uint32_t options,
        int sector_size = get_sector_size(fd);
 
        mbr_size = lcm(sizeof(*mbr), sector_size);
-       if ((rc = posix_memalign(&mbr_sector, sector_size, mbr_size)) != 0)
+       if ((rc = posix_memalign(&mbr_sector, sector_size, mbr_size)) != 0) {
+               efi_error("posix_memalign failed");
                goto error;
+       }
        memset(mbr_sector, '\0', mbr_size);
 
        offset = lseek(fd, 0, SEEK_SET);
        this_bytes_read = read(fd, mbr_sector, mbr_size);
        if (this_bytes_read < (ssize_t)sizeof(*mbr)) {
+               efi_error("short read trying to read mbr data");
                rc=1;
                goto error_free_mbr;
        }
@@ -208,9 +235,11 @@ get_partition_info(int fd, uint32_t options,
                                                            mbr_type,
                                                            signature_type);
                if (mbr_invalid) {
+                       efi_error("neither MBR nor GPT is valid");
                        rc=1;
                        goto error_free_mbr;
                }
+               efi_error_clear();
        }
  error_free_mbr:
        free(mbr_sector);
@@ -233,12 +262,17 @@ _make_hd_dn(uint8_t *buf, ssize_t size, int fd, uint32_t partition,
        errno = 0;
 
        rc = get_partition_info(fd, options,
-                               partition>0?partition:1, &part_start,
+                               partition > 0 ? partition : 1, &part_start,
                                &part_size, signature, &format,
                                &signature_type);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("could not get partition info");
                return rc;
+       }
 
-       return efidp_make_hd(buf, size, partition>0?partition:1, part_start,
-                            part_size, signature, format, signature_type);
+       rc = efidp_make_hd(buf, size, partition>0?partition:1, part_start,
+                          part_size, signature, format, signature_type);
+       if (rc < 0)
+               efi_error("could not make HD DP node");
+       return rc;
 }
index 37c0b71..f23fbeb 100644 (file)
@@ -180,6 +180,9 @@ efidp_make_acpi_hid(uint8_t *buf, ssize_t size, uint32_t hid, uint32_t uid)
                acpi_hid->hid = hid;
        }
 
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -210,5 +213,8 @@ efidp_make_acpi_hid_ex(uint8_t *buf, ssize_t size,
                strcpy(next, cidstr);
        }
 
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
index 1778467..43a7f54 100644 (file)
@@ -94,6 +94,10 @@ efidp_make_pci(uint8_t *buf, ssize_t size, uint8_t device, uint8_t function)
                pci->device = device;
                pci->function = function;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -111,5 +115,9 @@ efidp_make_edd10(uint8_t *buf, ssize_t size, uint32_t hardware_device)
                memcpy(&edd_dp->vendor_guid, &edd10_guid, sizeof (edd10_guid));
                edd_dp->hardware_device = hardware_device;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
index 287db1b..cde2ad8 100644 (file)
@@ -163,6 +163,10 @@ efidp_make_file(uint8_t *buf, ssize_t size, char *filepath)
                memset(buf+4, 0, req-4);
                utf8_to_ucs2(file->name, req-4, 1, lf);
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -187,5 +191,9 @@ efidp_make_hd(uint8_t *buf, ssize_t size, uint32_t num, uint64_t part_start,
                hd->format = format;
                hd->signature_type = signature_type;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
index d2433a0..63ee291 100644 (file)
@@ -480,8 +480,10 @@ _format_message_dn(char *buf, size_t size, const_efidp dp)
        case EFIDP_MSG_ISCSI: {
                ssize_t sz = efidp_node_size(dp)
                        - offsetof(efidp_iscsi, target_name);
-               if (sz < 0)
+               if (sz < 0) {
+                       efi_error("bad DP node size");
                        return -1;
+               }
 
                if (sz > EFIDP_ISCSI_MAX_TARGET_NAME_LEN)
                        sz = EFIDP_ISCSI_MAX_TARGET_NAME_LEN;
@@ -521,8 +523,10 @@ _format_message_dn(char *buf, size_t size, const_efidp dp)
                break;
        case EFIDP_MSG_URI: {
                ssize_t sz = efidp_node_size(dp) - offsetof(efidp_uri, uri);
-               if (sz < 0)
+               if (sz < 0) {
+                       efi_error("bad DP node size");
                        return -1;
+               }
 
                char uri[sz + 1];
                memcpy(uri, dp->uri.uri, sz);
@@ -562,6 +566,10 @@ efidp_make_mac_addr(uint8_t *buf, ssize_t size, uint8_t if_type,
                memcpy(mac->mac_addr, mac_addr,
                       mac_addr_size > 32 ? 32 : mac_addr_size);
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -588,6 +596,10 @@ efidp_make_ipv4(uint8_t *buf, ssize_t size, uint32_t local, uint32_t remote,
                *((char *)ipv4->gateway) = htonl(gateway);
                *((char *)ipv4->netmask) = htonl(netmask);
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -603,6 +615,10 @@ efidp_make_scsi(uint8_t *buf, ssize_t size, uint16_t target, uint16_t lun)
                scsi->target = target;
                scsi->lun = lun;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -626,6 +642,10 @@ efidp_make_nvme(uint8_t *buf, ssize_t size, uint32_t namespace_id,
                        memset(nvme->ieee_eui_64, '\0',
                               sizeof (nvme->ieee_eui_64));
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -645,6 +665,10 @@ efidp_make_sata(uint8_t *buf, ssize_t size, uint16_t hba_port,
                sata->port_multiplier_port = port_multiplier_port;
                sata->lun = lun;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -664,6 +688,10 @@ efidp_make_atapi(uint8_t *buf, ssize_t size, uint16_t primary,
                atapi->slave = slave;
                atapi->lun = lun;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
 
@@ -687,5 +715,9 @@ efidp_make_sas(uint8_t *buf, ssize_t size, uint64_t sas_address)
                sas->drive_bay_id = 0;
                sas->rtp = 0;
        }
+
+       if (sz < 0)
+               efi_error("efidp_make_generic failed");
+
        return sz;
 }
index d280fe2..e9a257e 100644 (file)
--- a/src/dp.c
+++ b/src/dp.c
@@ -37,6 +37,7 @@ efidp_data_address(const_efidp dp)
 {
        if (dp->length <= 4) {
                errno = ENOSPC;
+               efi_error("DP was smaller than DP header");
                return NULL;
        }
        return (void *)((uint8_t *)dp + sizeof (dp));
@@ -48,11 +49,14 @@ efidp_set_node_data(const_efidp dn, void *buf, size_t bufsize)
 {
        if (dn->length < 4 || bufsize > (size_t)dn->length - 4) {
                errno = ENOSPC;
+               efi_error("DP was smaller than DP header");
                return -1;
        }
        void *data = efidp_data_address(dn);
-       if (!data)
+       if (!data) {
+               efi_error("efidp_data_address failed");
                return -1;
+       }
        memcpy(data, buf, bufsize);
        return 0;
 }
@@ -66,17 +70,22 @@ efidp_duplicate_extra(const_efidp dp, efidp *out, size_t extra)
        efidp new;
 
        sz = efidp_size(dp);
-       if (sz < 0)
+       if (sz < 0) {
+               efi_error("efidp_size(dp) returned error");
                return sz;
+       }
 
        if (add(sz, extra, &plus)) {
                errno = EOVERFLOW;
+               efi_error("arithmetic overflow computing allocation size");
                return -1;
        }
 
        new = calloc(1, plus);
-       if (!new)
+       if (!new) {
+               efi_error("allocation failed");
                return -1;
+       }
 
        memcpy(new, dp, sz);
        *out = new;
@@ -87,7 +96,11 @@ int
 __attribute__((__visibility__ ("default")))
 efidp_duplicate_path(const_efidp  dp, efidp *out)
 {
-       return efidp_duplicate_extra(dp, out, 0);
+       int rc;
+       rc = efidp_duplicate_extra(dp, out, 0);
+       if (rc < 0)
+               efi_error("efi_duplicate_extra(dp, out, 0) returned error");
+       return rc;
 }
 
 int
@@ -98,47 +111,66 @@ efidp_append_path(const_efidp dp0, const_efidp dp1, efidp *out)
        const_efidp le;
        int rc;
 
-       if (!dp0 && !dp1)
-               return efidp_duplicate_path((const_efidp)&end_entire, out);
+       if (!dp0 && !dp1) {
+               rc = efidp_duplicate_path((const_efidp)&end_entire, out);
+               if (rc < 0)
+                       efi_error("efidp_duplicate_path failed");
+               return rc;
+       }
 
-       if (dp0 && !dp1)
-               return efidp_duplicate_path(dp0, out);
+       if (dp0 && !dp1) {
+               rc = efidp_duplicate_path(dp0, out);
+               if (rc < 0)
+                       efi_error("efidp_duplicate_path failed");
+               return rc;
+       }
 
-       if (!dp0 && dp1)
-               return efidp_duplicate_path(dp1, out);
+       if (!dp0 && dp1) {
+               rc = efidp_duplicate_path(dp1, out);
+               if (rc < 0)
+                       efi_error("efidp_duplicate_path failed");
+               return rc;
+       }
 
        lsz = efidp_size(dp0);
-       if (lsz < 0)
+       if (lsz < 0) {
+               efi_error("efidp_size(dp0) returned error");
                return -1;
+       }
 
        rsz = efidp_size(dp1);
-       if (rsz < 0)
+       if (lsz < 0) {
+               efi_error("efidp_size(dp1) returned error");
                return -1;
+       }
 
        le = dp0;
        while (1) {
                if (efidp_type(le) == EFIDP_END_TYPE &&
                                efidp_subtype(le) == EFIDP_END_ENTIRE) {
                        ssize_t lesz = efidp_size(le);
-                       if (lesz < 0)
-                               return -1;
                        lsz -= lesz;
                        break;
                }
 
                rc = efidp_get_next_end(le, &le);
-               if (rc < 0)
+               if (rc < 0) {
+                       efi_error("efidp_get_next_end() returned error");
                        return -1;
+               }
        }
 
        efidp new;
        if (add(lsz, rsz, &newsz)) {
                errno = EOVERFLOW;
+               efi_error("arithmetic overflow computing allocation size");
                return -1;
        }
        new = malloc(newsz);
-       if (!new)
+       if (!new) {
+               efi_error("allocation failed");
                return -1;
+       }
        *out = new;
 
        memcpy(new, dp0, lsz);
@@ -154,16 +186,32 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
        ssize_t lsz, rsz, newsz;
        int rc;
 
-       if (!dp && !dn)
-               return efidp_duplicate_path((const_efidp)(const efidp_header * const)&end_entire, out);
+       if (!dp && !dn) {
+               rc = efidp_duplicate_path(
+                       (const_efidp)(const efidp_header * const)&end_entire,
+                       out);
+               if (rc < 0)
+                       efi_error("efidp_duplicate_path() failed");
+               return rc;
+       }
 
        lsz = efidp_size(dp);
-       if (lsz < 0)
+       if (lsz < 0) {
+               efi_error("efidp_size(dp) returned error");
                return -1;
+       }
 
+       if (dp && !dn) {
+               rc = efidp_duplicate_path(dp, out);
+               if (rc < 0)
+                       efi_error("efidp_duplicate_path() failed");
+               return rc;
+       }
+
+       lsz = efidp_size(dp);
+       if (lsz < 0)
+               return -1;
 
-       if (dp && !dn)
-               return efidp_duplicate_path(dp, out);
 
        rsz = efidp_node_size(dn);
        if (rsz < 0)
@@ -172,11 +220,15 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
        if (!dp && dn) {
                if (add(rsz, sizeof(end_entire), &newsz)) {
                        errno = EOVERFLOW;
+                       efi_error(
+                         "arithmetic overflow computing allocation size");
                        return -1;
                }
                efidp new = malloc(rsz + sizeof (end_entire));
-               if (!new)
+               if (!new) {
+                       efi_error("allocation failed");
                        return -1;
+               }
 
                memcpy(new, dn, dn->length);
                memcpy((uint8_t *)new + dn->length, &end_entire,
@@ -185,14 +237,6 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
                return 0;
        }
 
-       lsz = efidp_size(dp);
-       if (lsz < 0)
-               return -1;
-
-       rsz = efidp_node_size(dn);
-       if (rsz < 0)
-               return -1;
-
        const_efidp le;
        le = dp;
        while (1) {
@@ -204,18 +248,23 @@ efidp_append_node(const_efidp dp, const_efidp dn, efidp *out)
                }
 
                rc = efidp_get_next_end(le, &le);
-               if (rc < 0)
+               if (rc < 0) {
+                       efi_error("efidp_get_next_end() returned error");
                        return -1;
+               }
        }
 
        if (add(lsz, rsz, &newsz) || add(newsz, sizeof(end_entire), &newsz)) {
                errno = EOVERFLOW;
+               efi_error("arithmetic overflow computing allocation size");
                return -1;
        }
 
        efidp new = malloc(newsz);
-       if (!new)
+       if (!new) {
+               efi_error("allocation failed");
                return -1;
+       }
 
        *out = new;
        memcpy(new, dp, lsz);
@@ -370,8 +419,10 @@ efidp_format_device_path(char *buf, size_t size, const_efidp dp, ssize_t limit)
                        limit -= efidp_node_size(dp);
 
                int rc = efidp_next_node(dp, &dp);
-               if (rc < 0)
+               if (rc < 0) {
+                       efi_error("could not format DP");
                        return rc;
+               }
        }
        return off+1;
 }
@@ -382,6 +433,7 @@ efidp_parse_device_node(char *path __attribute__((unused)),
                        efidp out __attribute__((unused)),
                        size_t size __attribute__((unused)))
 {
+       efi_error("not implented");
        errno = -ENOSYS;
        return -1;
 }
@@ -392,6 +444,7 @@ efidp_parse_device_path(char *path __attribute__((unused)),
                        efidp out __attribute__((unused)),
                        size_t size __attribute__((unused)))
 {
+       efi_error("not implented");
        errno = -ENOSYS;
        return -1;
 }
@@ -423,6 +476,7 @@ efidp_make_generic(uint8_t *buf, ssize_t size, uint8_t type, uint8_t subtype,
        if (!size)
                return total_size;
        if (size < total_size) {
+               efi_error("total size is bigger than size limit");
                errno = ENOSPC;
                return -1;
        }
index 6c5558c..d6775a6 100644 (file)
--- a/src/dp.h
+++ b/src/dp.h
 
 #include "ucs2.h"
 
-#define format(buf, size, off, fmt, args...) ({                        \
+#define format(buf, size, off, dp_type, fmt, args...) ({               \
                ssize_t _x = 0;                                         \
                if ((off) >= 0) {                                       \
                        _x = snprintf(((buf)+(off)),                    \
                               ((size)?((size)-(off)):0),               \
                               fmt, ## args);                           \
-                       if (_x < 0)                                     \
+                       if (_x < 0) {                                   \
+                               efi_error(                              \
+                                       "could not build %s DP string", \
+                                       (dp_type));                     \
                                return _x;                              \
+                       }                                               \
                        (off) += _x;                                    \
                }                                                       \
                off;                                                    \
        })
 
-#define format_helper(fn, buf, size, off, args...) ({          \
+#define format_helper(fn, buf, size, off, dp_type, args...) ({         \
                ssize_t _x;                                             \
                _x = (fn)(((buf)+(off)),                                \
-                         ((size)?((size)-(off)):0), ## args);          \
+                         ((size)?((size)-(off)):0), dp_type, ## args); \
                if (_x < 0)                                             \
+                       efi_error("could not build %s DP string",       \
+                                 dp_type);                             \
                (off) += _x;                                            \
        })
 
                (void *)__newbuf;                                       \
        })
 
-#define format_guid(buf, size, off, guid) ({                           \
+#define format_guid(buf, size, off, dp_type, guid) ({                  \
                int _rc;                                                \
                char *_guidstr = NULL;                                  \
                                                                        \
                _rc = efi_guid_to_str(guid, &_guidstr);                 \
-               format(buf, size, off, "%s", _guidstr);                 \
+               if (_rc < 0) {                                          \
+                       efi_error("could not build %s GUID DP string",  \
+                                 dp_type);                             \
+               } else {                                                \
+                       _guidstr = onstack(_guidstr,                    \
+                                          strlen(_guidstr)+1);         \
+                       _rc = format(buf, size, off, dp_type, "%s",     \
+                                    _guidstr); \
+               }                                                       \
+               _rc;                                                    \
        })
 
 static inline ssize_t
 __attribute__((__unused__))
-format_hex_helper(char *buf, size_t size, const void * const addr,
-                 const size_t len)
+format_hex_helper(char *buf, size_t size, const char *dp_type,
+                 const void * const addr, const size_t len)
 {
        ssize_t off = 0;
        for (size_t i = 0; i < len; i++) {
-               format(buf, size, off, "%02x",
+               format(buf, size, off, dp_type, "%02x",
                       *((const unsigned char * const )addr+i));
        }
        return off;
 }
 
-#define format_hex(buf, size, off, addr, len)                          \
-       format_helper(format_hex_helper, buf, size, off, addr, len)
+#define format_hex(buf, size, off, dp_type, addr, len)                 \
+       format_helper(format_hex_helper, buf, size, off, dp_type, addr, len)
 
 static inline ssize_t
 __attribute__((__unused__))
@@ -99,10 +114,10 @@ format_vendor_helper(char *buf, size_t size, char *label, const_efidp dp)
        return off;
 }
 
-#define format_vendor(buf, size, off, label, dp)                       \
+#define format_vendor(buf, size, off, label, dp)               \
        format_helper(format_vendor_helper, buf, size, off, label, dp)
 
-#define format_ucs2(buf, size, off, str, len) ({                       \
+#define format_ucs2(buf, size, off, dp_type, str, len) ({              \
                uint16_t _ucs2buf[(len)];                               \
                memset(_ucs2buf, '\0', sizeof (_ucs2buf));              \
                memcpy(_ucs2buf, str, sizeof (_ucs2buf)                 \
@@ -112,17 +127,17 @@ format_vendor_helper(char *buf, size_t size, char *label, const_efidp dp)
                if (_asciibuf == NULL)                                  \
                        return -1;                                      \
                _asciibuf = onstack(_asciibuf, (len));                  \
-               format(buf, size, off, "%s", _asciibuf);                \
+               format(buf, size, off, dp_type, "%s", _asciibuf);       \
        })
 
-#define format_array(buf, size, off, fmt, type, addr, len) ({          \
+#define format_array(buf, size, off, dp_type, fmt, type, addr, len) ({ \
                for (size_t _i = 0; _i < len; _i++) {                   \
                        if (_i != 0)                                    \
-                               format(buf, size, off, ",");            \
-                       format(buf, size, off, fmt,                     \
+                               format(buf, size, off, dp_type, ",");   \
+                       format(buf, size, off, dp_type, fmt,            \
                               ((type *)addr)[_i]);                     \
                }                                                       \
-               (off);                                                  \
+               off;                                                    \
        })
 
 extern ssize_t _format_hw_dn(char *buf, size_t size, const_efidp dp);
index c1c7424..cbefe8b 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <ctype.h>
+#include <err.h>
 #include <fcntl.h>
 #include <popt.h>
 #include <stdio.h>
@@ -55,6 +56,35 @@ static const char *attribute_names[] = {
        ""
 };
 
+static int verbose_errors = 0;
+
+static void
+show_errors(void)
+{
+       int rc = 0;
+
+       if (!verbose_errors)
+               return;
+
+       printf("Error trace:\n");
+       for (int i = 0; rc > 0; i++) {
+               char *filename = NULL;
+               char *function = NULL;
+               int line = 0;
+               char *message = NULL;
+               int error = 0;
+
+               rc = efi_error_get(i, &filename, &function, &line, &message,
+                                  &error);
+               if (rc < 0)
+                       err(1, "error fetching trace value");
+               if (rc == 0)
+                       break;
+               printf(" %s:%d %s(): %s: %s", filename, line, function,
+                      strerror(error), message);
+       }
+}
+
 static void
 list_all_variables(void)
 {
@@ -69,6 +99,7 @@ list_all_variables(void)
 
        if (rc < 0) {
                fprintf(stderr, "efivar: error listing variables: %m\n");
+               show_errors();
                exit(1);
        }
 }
@@ -89,7 +120,9 @@ parse_name(const char *guid_name, char **name, efi_guid_t *guid)
                if (right[1] != '-' || right[2] == '\0') {
 bad_name:
                        errno = -EINVAL;
-                       fprintf(stderr, "efivar: invalid name \"%s\"\n", guid_name);
+                       fprintf(stderr, "efivar: invalid name \"%s\"\n",
+                               guid_name);
+                       show_errors();
                        exit(1);
                }
                name_pos = right + 1 - guid_name;
@@ -148,6 +181,7 @@ show_variable(char *guid_name, int display_type)
        rc = efi_get_variable(guid, name, &data, &data_size, &attributes);
        if (rc < 0) {
                fprintf(stderr, "efivar: show variable: %m\n");
+               show_errors();
                exit(1);
        }
 
@@ -229,6 +263,7 @@ edit_variable(const char *guid_name, void *data, size_t data_size, int attrib,
                                &old_attributes);
        if (rc < 0) {
                fprintf(stderr, "efivar: %m\n");
+               show_errors();
                exit(1);
        }
 
@@ -248,6 +283,7 @@ edit_variable(const char *guid_name, void *data, size_t data_size, int attrib,
 
        if (rc < 0) {
                fprintf(stderr, "efivar: %m\n");
+               show_errors();
                exit(1);
        }
 }
@@ -257,6 +293,7 @@ validate_name(const char *name)
 {
        if (name == NULL) {
                fprintf(stderr, "Invalid variable name\n");
+               show_errors();
                exit(1);
        }
 }
index ac12faf..426090f 100644 (file)
@@ -72,11 +72,19 @@ efivarfs_probe(void)
                        typeof(buf.f_type) magic = EFIVARFS_MAGIC;
                        if (!memcmp(&buf.f_type, &magic, sizeof (magic)))
                                return 1;
+                       else
+                               efi_error("bad fs type for %s", path);
 
                        tmp = getenv("EFIVARFS_PATH");
-                       if (tmp && !strcmp(tmp, path))
+                       if (tmp && !strcmp(tmp, path)) {
+                               efi_error_clear();
                                return 1;
+                       }
+               } else {
+                       efi_error("statfs(%s) failed", path);
                }
+       } else {
+               efi_error("access(%s, F_OK) failed", path);
        }
 
        return 0;
@@ -100,6 +108,8 @@ efivarfs_set_fd_immutable(int fd, int immutable)
        if (rc < 0) {
                if (errno == ENOTTY)
                        rc = 0;
+               else
+                       efi_error("ioctl(%d, FS_IOC_GETFLAGS) failed", fd);
        } else if ((immutable && !(flags & FS_IMMUTABLE_FL)) ||
                   (!immutable && (flags & FS_IMMUTABLE_FL))) {
                if (immutable)
@@ -108,6 +118,8 @@ efivarfs_set_fd_immutable(int fd, int immutable)
                        flags &= ~FS_IMMUTABLE_FL;
 
                rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
+               if (rc < 0)
+                       efi_error("ioctl(%d, FS_IOC_SETFLAGS) failed", fd);
        }
 
        return rc;
@@ -122,16 +134,21 @@ efivarfs_set_immutable(char *path, int immutable)
 
        fd = open(path, O_RDONLY);
        if (fd < 0) {
-               if (errno == ENOTTY)
+               if (errno == ENOTTY) {
+                       efi_error("open(%s, O_RDONLY) failed", path);
                        return 0;
-               else
+               } else {
                        return fd;
+               }
        }
 
        rc = efivarfs_set_fd_immutable(fd, immutable);
        error = errno;
        close(fd);
        errno = error;
+       if (rc < 0)
+               efi_error("efivarfs_set_fd_immutable(%d, %d) on %s failed",
+                         fd, immutable, path);
        return rc;
 }
 
@@ -144,13 +161,17 @@ efivarfs_get_variable_size(efi_guid_t guid, const char *name, size_t *size)
        typeof(errno) errno_value;
 
        rc = make_efivarfs_path(&path, guid, name);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("make_efivarfs_path failed");
                goto err;
+       }
 
        struct stat statbuf = { 0, };
        rc = stat(path, &statbuf);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("stat(%s) failed", path);
                goto err;
+       }
 
        ret = 0;
        /* Compensate for the size of the Attributes field. */
@@ -176,8 +197,10 @@ efivarfs_get_variable_attributes(efi_guid_t guid, const char *name,
        uint32_t attribs;
 
        ret = efi_get_variable(guid, name, &data, &data_size, &attribs);
-       if (ret < 0)
+       if (ret < 0) {
+               efi_error("efi_get_variable failed");
                return ret;
+       }
 
        *attributes = attribs;
        if (data)
@@ -197,20 +220,28 @@ efivarfs_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
 
        char *path;
        int rc = make_efivarfs_path(&path, guid, name);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("make_efivarfs_path failed");
                return -1;
+       }
 
        int fd = open(path, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("open(%s)", path);
                goto err;
+       }
 
        rc = read(fd, &ret_attributes, sizeof (ret_attributes));
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("read failed");
                goto err;
+       }
 
        rc = read_file(fd, &ret_data, &size);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("read_file failed");
                goto err;
+       }
 
        *attributes = ret_attributes;
        *data = ret_data;
@@ -235,11 +266,15 @@ efivarfs_del_variable(efi_guid_t guid, const char *name)
 {
        char *path;
        int rc = make_efivarfs_path(&path, guid, name);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("make_efivarfs_path failed");
                return -1;
+       }
 
        efivarfs_set_immutable(path, 0);
        rc = unlink(path);
+       if (rc < 0)
+               efi_error("unlink failed");
 
        typeof(errno) errno_value = errno;
        free(path);
@@ -257,35 +292,48 @@ efivarfs_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
        int ret = -1;
 
        if (strlen(name) > 1024) {
+               efi_error("name too long (%zd of 1024)", strlen(name));
                errno = EINVAL;
                return -1;
        }
 
        char *path;
        int rc = make_efivarfs_path(&path, guid, name);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("make_efivarfs_path failed");
                return -1;
+       }
 
        int fd = -1;
 
        if (!access(path, F_OK) && !(attributes & EFI_VARIABLE_APPEND_WRITE)) {
                rc = efi_del_variable(guid, name);
-               if (rc < 0)
+               if (rc < 0) {
+                       efi_error("efi_del_variable failed");
                        goto err;
+               }
        }
 
        fd = open(path, O_WRONLY|O_CREAT, mode);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("open(%s, O_WRONLY|O_CREAT, mode) failed", path);
                goto err;
+       }
        efivarfs_set_fd_immutable(fd, 0);
 
        memcpy(buf, &attributes, sizeof (attributes));
        memcpy(buf + sizeof (attributes), data, data_size);
-       rc = write(fd, buf, sizeof (attributes) + data_size);
+#if 0
+               errno = ENOSPC;
+               rc = -1;
+#else
+               rc = write(fd, buf, sizeof (attributes) + data_size);
+#endif
        if (rc >= 0) {
                ret = 0;
                efivarfs_set_fd_immutable(fd, 1);
        } else {
+               efi_error("write failed");
                efivarfs_set_fd_immutable(fd, 0);
                unlink(path);
        }
@@ -306,14 +354,22 @@ static int
 efivarfs_append_variable(efi_guid_t guid, const char *name, uint8_t *data,
        size_t data_size, uint32_t attributes)
 {
+       int rc;
        attributes |= EFI_VARIABLE_APPEND_WRITE;
-       return efivarfs_set_variable(guid, name, data, data_size, attributes, 0);
+       rc = efivarfs_set_variable(guid, name, data, data_size, attributes, 0);
+       if (rc < 0)
+               efi_error("efivarfs_set_variable failed");
+       return rc;
 }
 
 static int
 efivarfs_get_next_variable_name(efi_guid_t **guid, char **name)
 {
-       return generic_get_next_variable_name(get_efivarfs_path(), guid, name);
+       int rc;
+       rc = generic_get_next_variable_name(get_efivarfs_path(), guid, name);
+       if (rc < 0)
+               efi_error("generic_get_next_variable_name failed");
+       return rc;
 }
 
 static int
@@ -321,11 +377,15 @@ efivarfs_chmod_variable(efi_guid_t guid, const char *name, mode_t mode)
 {
        char *path;
        int rc = make_efivarfs_path(&path, guid, name);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("make_efivarfs_path failed");
                return -1;
+       }
 
        rc = chmod(path, mode);
        int saved_errno = errno;
+       if (rc < 0)
+               efi_error("chmod(%s,0%o) failed", path, mode);
        free(path);
        errno = saved_errno;
        return -1;
index 1b31b15..10f242f 100644 (file)
@@ -42,6 +42,7 @@ generic_get_next_variable_name(const char *path, efi_guid_t **guid, char **name)
 
        if (!guid || !name) {
                errno = EINVAL;
+               efi_error("invalid arguments");
                return -1;
        }
 
@@ -50,30 +51,33 @@ generic_get_next_variable_name(const char *path, efi_guid_t **guid, char **name)
        if ((*guid == NULL && *name != NULL) ||
                        (*guid != NULL && *name == NULL)) {
                errno = EINVAL;
+               efi_error("invalid arguments");
                return -1;
        }
 
        /* if dir is NULL, we're also starting over */
        if (!dir) {
                dir = opendir(path);
-               if (!dir)
+               if (!dir) {
+                       efi_error("opendir(%s) failed", path);
                        return -1;
+               }
 
                int fd = dirfd(dir);
                if (fd < 0) {
                        typeof(errno) errno_value = errno;
+                       efi_error("dirfd failed");
                        closedir(dir);
                        errno = errno_value;
                        return -1;
                }
                int flags = fcntl(fd, F_GETFD);
                if (flags < 0) {
-                       warn("fcntl(fd, F_GETFD) failed");
+                       efi_error("fcntl(fd, F_GETFD) failed");
                } else {
                        flags |= FD_CLOEXEC;
                        if (fcntl(fd, F_SETFD, flags) < 0)
-                               warn("fcntl(fd, F_SETFD, "
-                                       "flags | FD_CLOEXEC) failed");
+                               efi_error("fcntl(fd, F_SETFD, flags | FD_CLOEXEC) failed");
                }
 
                *guid = NULL;
@@ -102,6 +106,7 @@ generic_get_next_variable_name(const char *path, efi_guid_t **guid, char **name)
                        closedir(dir);
                        dir = NULL;
                        errno = EINVAL;
+                       efi_error("text_to_guid failed");
                        return -1;
                }
 
@@ -155,6 +160,7 @@ generic_append_variable(efi_guid_t guid, const char *name,
                attributes &= ~EFI_VARIABLE_APPEND_WRITE;
                rc = efi_del_variable(guid, name);
                if (rc < 0) {
+                       efi_error("efi_del_variable failed");
                        free(data);
                        free(d);
                        return rc;
@@ -164,17 +170,19 @@ generic_append_variable(efi_guid_t guid, const char *name,
                 * let our caller attempt to clean up :/
                 */
                rc = efi_set_variable(guid, name, d, ds, attributes, 0600);
+               if (rc < 0)
+                       efi_error("efi_set_variable failed");
                free(d);
                free(data);
-               return rc;
        } else if (errno == ENOENT) {
                data = new_data;
                data_size = new_data_size;
                attributes = new_attributes & ~EFI_VARIABLE_APPEND_WRITE;
                rc = efi_set_variable(guid, name, data, data_size,
                                      attributes, 0600);
-               return rc;
        }
+       if (rc < 0)
+               efi_error("efi_set_variable failed");
        return rc;
 }
 
index 2f88d17..7e0f2be 100644 (file)
@@ -54,7 +54,11 @@ __attribute__((__nonnull__ (1, 2)))
 __attribute__((__visibility__ ("default")))
 efi_str_to_guid(const char *s, efi_guid_t *guid)
 {
-       return text_to_guid(s, guid);
+       int rc;
+       rc = text_to_guid(s, guid);
+       if (rc < 0)
+               efi_error("text_to_guid(\"%s\",...)", s);
+       return rc;
 }
 
 int
@@ -66,7 +70,7 @@ efi_guid_to_str(const efi_guid_t *guid, char **sp)
        int rc = -1;
 
        if (!sp) {
-               return snprintf(NULL, 0, GUID_FORMAT,
+               rc = snprintf(NULL, 0, GUID_FORMAT,
                                le32_to_cpu(guid->a),
                                le16_to_cpu(guid->b),
                                le16_to_cpu(guid->c),
@@ -74,7 +78,7 @@ efi_guid_to_str(const efi_guid_t *guid, char **sp)
                                guid->e[0], guid->e[1], guid->e[2], guid->e[3],
                                guid->e[4], guid->e[5]);
        } else if (sp && *sp) {
-               return snprintf(*sp, GUID_LENGTH_WITH_NUL, GUID_FORMAT,
+               rc = snprintf(*sp, GUID_LENGTH_WITH_NUL, GUID_FORMAT,
                                le32_to_cpu(guid->a),
                                le16_to_cpu(guid->b),
                                le16_to_cpu(guid->c),
@@ -92,6 +96,8 @@ efi_guid_to_str(const efi_guid_t *guid, char **sp)
                if (rc >= 0)
                        *sp = ret;
        }
+       if (rc < 0)
+               efi_error("Could not format guid");
        return rc;
 }
 
@@ -142,6 +148,7 @@ _get_common_guidname(const efi_guid_t *guid, struct guidname **result)
        if (!tmp) {
                *result = NULL;
                errno = ENOENT;
+               efi_error("GUID is not in common GUID list");
                return -1;
        }
 
@@ -160,7 +167,10 @@ efi_guid_to_name(efi_guid_t *guid, char **name)
                *name = strndup(result->name, sizeof (result->name) -1);
                return *name ? (int)strlen(*name) : -1;
        }
-       return efi_guid_to_str(guid, name);
+       rc = efi_guid_to_str(guid, name);
+       if (rc >= 0)
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -174,6 +184,7 @@ efi_guid_to_symbol(efi_guid_t *guid, char **symbol)
                *symbol = strndup(result->symbol, sizeof (result->symbol) -1);
                return *symbol ? (int)strlen(*symbol) : -1;
        }
+       efi_error_clear();
        errno = EINVAL;
        return -1;
 }
index a039513..45186ea 100644 (file)
@@ -939,35 +939,55 @@ efidp_is_valid(const_efidp dp, ssize_t limit)
                switch (hdr->type) {
                case EFIDP_HARDWARE_TYPE:
                        if (hdr->subtype != EFIDP_HW_VENDOR &&
-                           hdr->length > 1024)
+                           hdr->length > 1024) {
+                               errno = EINVAL;
+                               efi_error("invalid hardware node");
                                return 0;
+                       }
                        break;
                case EFIDP_ACPI_TYPE:
-                       if (hdr->length > 1024)
+                       if (hdr->length > 1024) {
+                               errno = EINVAL;
+                               efi_error("invalid ACPI node");
                                return 0;
+                       }
                        break;
                case EFIDP_MESSAGE_TYPE:
                        if (hdr->subtype != EFIDP_MSG_VENDOR &&
-                           hdr->length > 1024)
+                           hdr->length > 1024) {
+                               errno = EINVAL;
+                               efi_error("invalid message node");
                                return 0;
+                       }
                        break;
                case EFIDP_MEDIA_TYPE:
                        if (hdr->subtype != EFIDP_MEDIA_VENDOR &&
-                           hdr->length > 1024)
+                           hdr->length > 1024) {
+                               errno = EINVAL;
+                               efi_error("invalid media node");
                                return 0;
+                       }
                        break;
                case EFIDP_BIOS_BOOT_TYPE:
                        break;
                case EFIDP_END_TYPE:
-                       if (hdr->length > 4)
+                       if (hdr->length > 4) {
+                               errno = EINVAL;
+                               efi_error("invalid end node");
                                return 0;
+                       }
                        break;
                default:
+                       errno = EINVAL;
+                       efi_error("invalid device path node type");
                        return 0;
                }
 
-               if (limit < hdr->length)
+               if (limit < hdr->length) {
+                       errno = EINVAL;
+                       efi_error("device path node length overruns buffer");
                        return 0;
+               }
                limit -= hdr->length;
 
                if (hdr->type != EFIDP_END_TYPE &&
@@ -978,6 +998,7 @@ efidp_is_valid(const_efidp dp, ssize_t limit)
        }
        if (limit < 0) {
                errno = EINVAL;
+               efi_error("device path node length overruns buffer");
                return 0;
        }
        return 1;
index 6a9b392..60709e3 100644 (file)
--- a/src/lib.c
+++ b/src/lib.c
@@ -47,7 +47,11 @@ __attribute__((__visibility__ ("default")))
 _efi_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
                  size_t data_size, uint32_t attributes)
 {
-       return ops->set_variable(guid, name, data, data_size, attributes, 0600);
+       int rc;
+       rc = ops->set_variable(guid, name, data, data_size, attributes, 0600);
+       if (rc < 0)
+               efi_error("ops->set_variable() failed");
+       return rc;
 }
 __asm__(".symver _efi_set_variable,_efi_set_variable@");
 
@@ -57,7 +61,11 @@ __attribute__((__visibility__ ("default")))
 _efi_set_variable_variadic(efi_guid_t guid, const char *name, uint8_t *data,
                           size_t data_size, uint32_t attributes, ...)
 {
-       return ops->set_variable(guid, name, data, data_size, attributes, 0600);
+       int rc;
+       rc = ops->set_variable(guid, name, data, data_size, attributes, 0600);
+       if (rc < 0)
+               efi_error("ops->set_variable() failed");
+       return rc;
 }
 __asm__(".symver _efi_set_variable_variadic,efi_set_variable@");
 
@@ -67,7 +75,13 @@ __attribute__((__visibility__ ("default")))
 efi_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
                 size_t data_size, uint32_t attributes, mode_t mode)
 {
-       return ops->set_variable(guid, name, data, data_size, attributes, mode);
+       int rc;
+       rc = ops->set_variable(guid, name, data, data_size, attributes, mode);
+       if (rc < 0)
+               efi_error("ops->set_variable() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 __asm__(".symver efi_set_variable,efi_set_variable@@LIBEFIVAR_0.24");
 
@@ -77,10 +91,22 @@ __attribute__((__visibility__ ("default")))
 efi_append_variable(efi_guid_t guid, const char *name, uint8_t *data,
                        size_t data_size, uint32_t attributes)
 {
-       if (!ops->append_variable)
-               return generic_append_variable(guid, name, data, data_size,
-                                               attributes);
-       return ops->append_variable(guid, name, data, data_size, attributes);
+       int rc;
+       if (!ops->append_variable) {
+               rc = generic_append_variable(guid, name, data, data_size,
+                                            attributes);
+               if (rc < 0)
+                       efi_error("generic_append_variable() failed");
+               else
+                       efi_error_clear();
+               return rc;
+       }
+       rc = ops->append_variable(guid, name, data, data_size, attributes);
+       if (rc < 0)
+               efi_error("ops->append_variable() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -88,11 +114,18 @@ __attribute__((__nonnull__ (2)))
 __attribute__((__visibility__ ("default")))
 efi_del_variable(efi_guid_t guid, const char *name)
 {
+       int rc;
        if (!ops->del_variable) {
+               efi_error("del_variable() is not implemented");
                errno = ENOSYS;
                return -1;
        }
-       return ops->del_variable(guid, name);
+       rc = ops->del_variable(guid, name);
+       if (rc < 0)
+               efi_error("ops->del_variable() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -101,11 +134,18 @@ __attribute__((__visibility__ ("default")))
 efi_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
                  size_t *data_size, uint32_t *attributes)
 {
+       int rc;
        if (!ops->get_variable) {
+               efi_error("get_variable() is not implemented");
                errno = ENOSYS;
                return -1;
        }
-       return ops->get_variable(guid, name, data, data_size, attributes);
+       rc = ops->get_variable(guid, name, data, data_size, attributes);
+       if (rc < 0)
+               efi_error("ops->get_variable failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -114,11 +154,18 @@ __attribute__((__visibility__ ("default")))
 efi_get_variable_attributes(efi_guid_t guid, const char *name,
                            uint32_t *attributes)
 {
+       int rc;
        if (!ops->get_variable_attributes) {
+               efi_error("get_variable_attributes() is not implemented");
                errno = ENOSYS;
                return -1;
        }
-       return ops->get_variable_attributes(guid, name, attributes);
+       rc = ops->get_variable_attributes(guid, name, attributes);
+       if (rc < 0)
+               efi_error("ops->get_variable_attributes() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -126,11 +173,18 @@ __attribute__((__nonnull__ (2, 3)))
 __attribute__((__visibility__ ("default")))
 efi_get_variable_size(efi_guid_t guid, const char *name, size_t *size)
 {
+       int rc;
        if (!ops->get_variable_size) {
+               efi_error("get_variable_size() is not implemented");
                errno = ENOSYS;
                return -1;
        }
-       return ops->get_variable_size(guid, name, size);
+       rc = ops->get_variable_size(guid, name, size);
+       if (rc < 0)
+               efi_error("ops->get_variable_size() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -138,11 +192,18 @@ __attribute__((__nonnull__ (1, 2)))
 __attribute__((__visibility__ ("default")))
 efi_get_next_variable_name(efi_guid_t **guid, char **name)
 {
+       int rc;
        if (!ops->get_next_variable_name) {
+               efi_error("get_next_variable_name() is not implemented");
                errno = ENOSYS;
                return -1;
        }
-       return ops->get_next_variable_name(guid, name);
+       rc = ops->get_next_variable_name(guid, name);
+       if (rc < 0)
+               efi_error("ops->get_next_variable_name() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -150,11 +211,18 @@ __attribute__((__nonnull__ (2)))
 __attribute__((__visibility__ ("default")))
 efi_chmod_variable(efi_guid_t guid, const char *name, mode_t mode)
 {
+       int rc;
        if (!ops->chmod_variable) {
+               efi_error("chmod_variable() is not implemented");
                errno = ENOSYS;
                return -1;
        }
-       return ops->chmod_variable(guid, name, mode);
+       rc = ops->chmod_variable(guid, name, mode);
+       if (rc < 0)
+               efi_error("ops->chmod_variable() failed");
+       else
+               efi_error_clear();
+       return rc;
 }
 
 int
@@ -186,7 +254,13 @@ libefivar_init(void)
                                ops = ops_list[i];
                                break;
                        }
-               } else if (ops_list[i]->probe()) {
+               } else {
+                       int rc = ops_list[i]->probe();
+                       if (rc <= 0)
+                               efi_error("ops_list[%d]->probe() failed", i);
+                       else
+                               efi_error_clear();
+
                        ops = ops_list[i];
                        break;
                }
index 994caf1..87f2284 100644 (file)
@@ -254,8 +254,10 @@ sysfs_sata_get_port_info(uint32_t print_id, struct disk_info *info)
        int rc;
 
        d = opendir("/sys/class/ata_device/");
-       if (!d)
+       if (!d) {
+               efi_error("opendir failed on /sys/class/ata_device/");
                return -1;
+       }
 
        while ((de = readdir(d)) != NULL) {
                uint32_t found_print_id;
index 9e32d38..4b4e20f 100644 (file)
@@ -76,8 +76,10 @@ get_file_data_size(int dfd, char *name)
        strcat(raw_var, "/raw_var");
 
        int fd = openat(dfd, raw_var, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("openat failed");
                return -1;
+       }
 
        char buf[4096];
        ssize_t sz, total = 0;
@@ -182,12 +184,16 @@ get_size_from_file(const char *filename, size_t *retsize)
        int errno_value;
        int ret = -1;
        int fd = open(filename, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("open(%s, O_RDONLY) failed", filename);
                goto err;
+       }
 
        int rc = read_file(fd, &buf, &bufsize);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("read_file(%s) failed", filename);
                goto err;
+       }
 
        long long size = strtoll((char *)buf, NULL, 0);
        if ((size == LLONG_MIN || size == LLONG_MAX) && errno == ERANGE) {
@@ -218,12 +224,17 @@ vars_probe(void)
        char *newvar;
 
        /* If we can't tell if it's 64bit or not, this interface is no good. */
-       if (is_64bit() < 0)
+       if (is_64bit() < 0) {
+               efi_error("is_64bit() failed");
                return 0;
-       if (asprintfa(&newvar, "%s%s", get_vars_path(), "new_var") < 0)
+       }
+       if (asprintfa(&newvar, "%s%s", get_vars_path(), "new_var") < 0) {
+               efi_error("asprintfa failed");
                return 0;
+       }
        if (!access(newvar, F_OK))
                return 1;
+       efi_error("access(%s, F_OK) failed", newvar);
        return 0;
 }
 
@@ -238,14 +249,18 @@ vars_get_variable_size(efi_guid_t guid, const char *name, size_t *size)
                          name, guid.a, guid.b, guid.c, bswap_16(guid.d),
                          guid.e[0], guid.e[1], guid.e[2], guid.e[3],
                          guid.e[4], guid.e[5]);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("asprintf failed");
                goto err;
+       }
 
        size_t retsize = 0;
        rc = get_size_from_file(path, &retsize);
        if (rc >= 0) {
                ret = 0;
                *size = retsize;
+       } else if (rc < 0) {
+               efi_error("get_size_from_file(%s) failed", path);
        }
 err:
        errno_value = errno;
@@ -268,8 +283,10 @@ vars_get_variable_attributes(efi_guid_t guid, const char *name,
        uint32_t attribs;
 
        ret = efi_get_variable(guid, name, &data, &data_size, &attribs);
-       if (ret < 0)
+       if (ret < 0) {
+               efi_error("efi_get_variable() failed");
                return ret;
+       }
 
        *attributes = attribs;
        if (data)
@@ -291,16 +308,22 @@ vars_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
                          name, guid.a, guid.b, guid.c, bswap_16(guid.d),
                          guid.e[0], guid.e[1], guid.e[2],
                          guid.e[3], guid.e[4], guid.e[5]);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("asprintf failed");
                return -1;
+       }
 
        int fd = open(path, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("open(%s, O_RDONLY) failed", path);
                goto err;
+       }
 
        rc = read_file(fd, &buf, &bufsize);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("read_file(%s) failed", path);
                goto err;
+       }
 
        bufsize -= 1; /* read_file pads out 1 extra byte to NUL it */
 
@@ -309,13 +332,17 @@ vars_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
 
                if (bufsize != sizeof(efi_kernel_variable_64_t)) {
                        errno = EFBIG;
+                       efi_error("file size is wrong for 64-bit variable (%zd of %zd)",
+                                 bufsize, sizeof(efi_kernel_variable_64_t));
                        goto err;
                }
 
                var64 = (void *)buf;
                *data = malloc(var64->DataSize);
-               if (!*data)
+               if (!*data) {
+                       efi_error("malloc failed");
                        goto err;
+               }
                memcpy(*data, var64->Data, var64->DataSize);
                *data_size = var64->DataSize;
                *attributes = var64->Attributes;
@@ -323,14 +350,18 @@ vars_get_variable(efi_guid_t guid, const char *name, uint8_t **data,
                efi_kernel_variable_32_t *var32;
 
                if (bufsize != sizeof(efi_kernel_variable_32_t)) {
+                       efi_error("file size is wrong for 32-bit variable (%zd of %zd)",
+                                 bufsize, sizeof(efi_kernel_variable_32_t));
                        errno = EFBIG;
                        goto err;
                }
 
                var32 = (void *)buf;
                *data = malloc(var32->DataSize);
-               if (!*data)
+               if (!*data) {
+                       efi_error("malloc failed");
                        goto err;
+               }
                memcpy(*data, var32->Data, var32->DataSize);
                *data_size = var32->DataSize;
                *attributes = var32->Attributes;
@@ -364,39 +395,55 @@ vars_del_variable(efi_guid_t guid, const char *name)
                          name, guid.a, guid.b, guid.c, bswap_16(guid.d),
                          guid.e[0], guid.e[1], guid.e[2],
                          guid.e[3], guid.e[4], guid.e[5]);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("asprintf failed");
                return -1;
+       }
 
        uint8_t *buf = NULL;
        size_t buf_size = 0;
        char *delvar;
 
        int fd = open(path, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("open(%s, O_RDONLY) failed", path);
                goto err;
+       }
 
        rc = read_file(fd, &buf, &buf_size);
        buf_size -= 1; /* read_file pads out 1 extra byte to NUL it */
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("read_file(%s) failed", path);
                goto err;
+       }
 
        if (buf_size != sizeof(efi_kernel_variable_64_t) &&
                       buf_size != sizeof(efi_kernel_variable_32_t)) {
+               efi_error("variable size %zd is not 32-bit (%zd) or 64-bit (%zd)",
+                         buf_size, sizeof(efi_kernel_variable_32_t),
+                         sizeof(efi_kernel_variable_64_t));
+
                errno = EFBIG;
                goto err;
        }
 
-       if (asprintfa(&delvar, "%s%s", get_vars_path(), "del_var") < 0)
+       if (asprintfa(&delvar, "%s%s", get_vars_path(), "del_var") < 0) {
+               efi_error("asprintfa() failed");
                goto err;
+       }
 
        close(fd);
        fd = open(delvar, O_WRONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               efi_error("open(%s, O_WRONLY) failed", delvar);
                goto err;
+       }
 
        rc = write(fd, buf, buf_size);
        if (rc >= 0)
                ret = 0;
+       else
+               efi_error("write() failed");
 err:
        errno_value = errno;
 
@@ -462,11 +509,14 @@ vars_chmod_variable(efi_guid_t guid, const char *name, mode_t mode)
                          name, guid.a, guid.b, guid.c, bswap_16(guid.d),
                          guid.e[0], guid.e[1], guid.e[2], guid.e[3],
                          guid.e[4], guid.e[5]);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("asprintf failed");
                return -1;
+       }
 
        rc = _vars_chmod_variable(path, mode);
        int saved_errno = errno;
+       efi_error("_vars_chmod_variable() failed");
        free(path);
        errno = saved_errno;
        return rc;
@@ -481,10 +531,14 @@ vars_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
        int ret = -1;
 
        if (strlen(name) > 1024) {
+               efi_error("variable name size is too large (%zd of 1024)",
+                         strlen(name));
                errno = EINVAL;
                return -1;
        }
        if (data_size > 1024) {
+               efi_error("variable data size is too large (%zd of 1024)",
+                         data_size);
                errno = ENOSPC;
                return -1;
        }
@@ -494,21 +548,26 @@ vars_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
                          name, guid.a, guid.b, guid.c, bswap_16(guid.d),
                          guid.e[0], guid.e[1], guid.e[2], guid.e[3],
                          guid.e[4], guid.e[5]);
-       if (rc < 0)
+       if (rc < 0) {
+               efi_error("asprintf failed");
                return -1;
+       }
 
        len = rc;
        int fd = -1;
 
        if (!access(path, F_OK)) {
                rc = efi_del_variable(guid, name);
-               if (rc < 0)
+               if (rc < 0) {
+                       efi_error("efi_del_variable failed");
                        goto err;
+               }
        }
        char *newvar;
-       if (asprintfa(&newvar, "%s%s", get_vars_path(), "new_var") < 0)
+       if (asprintfa(&newvar, "%s%s", get_vars_path(), "new_var") < 0) {
+               efi_error("asprintfa failed");
                goto err;
-
+       }
 
        if (is_64bit()) {
                efi_kernel_variable_64_t var64 = {
@@ -523,8 +582,10 @@ vars_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
                memcpy(var64.Data, data, data_size);
 
                fd = open(newvar, O_WRONLY);
-               if (fd < 0)
+               if (fd < 0) {
+                       efi_error("open(%s, O_WRONLY) failed", newvar);
                        goto err;
+               }
 
                rc = write(fd, &var64, sizeof(var64));
        } else {
@@ -539,14 +600,18 @@ vars_set_variable(efi_guid_t guid, const char *name, uint8_t *data,
                memcpy(var32.Data, data, data_size);
 
                fd = open(newvar, O_WRONLY);
-               if (fd < 0)
+               if (fd < 0) {
+                       efi_error("open(%s, O_WRONLY) failed", newvar);
                        goto err;
+               }
 
                rc = write(fd, &var32, sizeof(var32));
        }
 
        if (rc >= 0)
                ret = 0;
+       else
+               efi_error("write() failed");
 
        /* this is inherently racy, but there's no way to do it correctly with
         * this kernel API.  Fortunately, all directory contents get created
@@ -569,7 +634,12 @@ err:
 static int
 vars_get_next_variable_name(efi_guid_t **guid, char **name)
 {
-       return generic_get_next_variable_name(get_vars_path(), guid, name);
+       int rc;
+       const char *vp = get_vars_path();
+       rc = generic_get_next_variable_name(vp, guid, name);
+       if (rc < 0)
+               efi_error("generic_get_next_variable_name(%s,...) failed", vp);
+       return rc;
 }
 
 struct efi_var_operations vars_ops = {