efivars.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // SPDX-License-Identifier: LGPL-2.1-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2015 Intel Corporation. All rights reserved.
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <stdint.h>
  21. #include <sys/stat.h>
  22. #include <sys/types.h>
  23. #include <sys/param.h>
  24. #include <sys/uio.h>
  25. #include "peripheral/efivars.h"
  26. #define SYSFS_EFIVARS "/sys/firmware/efi/efivars"
  27. typedef struct {
  28. uint32_t data1;
  29. uint16_t data2;
  30. uint16_t data3;
  31. uint8_t data4[8];
  32. } efi_guid_t;
  33. #define VENDOR_GUID \
  34. (efi_guid_t) { 0xd5f9d775, 0x1a09, 0x4e89, \
  35. { 0x96, 0xcf, 0x1d, 0x19, 0x55, 0x4d, 0xa6, 0x67 } }
  36. static void efivars_pathname(const char *name, char *pathname, size_t size)
  37. {
  38. static efi_guid_t guid = VENDOR_GUID;
  39. snprintf(pathname, size - 1,
  40. "%s/%s-%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  41. SYSFS_EFIVARS, name, guid.data1, guid.data2, guid.data3,
  42. guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3],
  43. guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7]);
  44. }
  45. int efivars_read(const char *name, uint32_t *attributes,
  46. void *data, size_t size)
  47. {
  48. char pathname[PATH_MAX];
  49. struct iovec iov[2];
  50. uint32_t attr;
  51. ssize_t len;
  52. int fd;
  53. efivars_pathname(name, pathname, PATH_MAX);
  54. fd = open(pathname, O_RDONLY | O_CLOEXEC);
  55. if (fd < 0)
  56. return -EIO;
  57. iov[0].iov_base = &attr;
  58. iov[0].iov_len = sizeof(attr);
  59. iov[1].iov_base = data;
  60. iov[1].iov_len = size;
  61. len = readv(fd, iov, 2);
  62. close(fd);
  63. if (len < 0)
  64. return -EIO;
  65. if (attributes)
  66. *attributes = attr;
  67. return 0;
  68. }
  69. int efivars_write(const char *name, uint32_t attributes,
  70. const void *data, size_t size)
  71. {
  72. char pathname[PATH_MAX];
  73. void *buf;
  74. ssize_t written;
  75. int fd;
  76. efivars_pathname(name, pathname, PATH_MAX);
  77. buf = malloc(size + sizeof(attributes));
  78. if (!buf)
  79. return -ENOMEM;
  80. fd = open(pathname, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0644);
  81. if (fd < 0) {
  82. free(buf);
  83. return -EIO;
  84. }
  85. memcpy(buf, &attributes, sizeof(attributes));
  86. memcpy(buf + sizeof(attributes), data, size);
  87. written = write(fd, buf, size + sizeof(attributes));
  88. close(fd);
  89. free(buf);
  90. if (written < 0)
  91. return -EIO;
  92. return 0;
  93. }