efi_variable.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI utils
  4. *
  5. * Copyright (c) 2017 Rob Clark
  6. */
  7. #include <common.h>
  8. #include <efi_loader.h>
  9. #include <env_internal.h>
  10. #include <hexdump.h>
  11. #include <malloc.h>
  12. #include <search.h>
  13. #include <u-boot/crc.h>
  14. #define READ_ONLY BIT(31)
  15. /*
  16. * Mapping between EFI variables and u-boot variables:
  17. *
  18. * efi_$guid_$varname = {attributes}(type)value
  19. *
  20. * For example:
  21. *
  22. * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
  23. * "{ro,boot,run}(blob)0000000000000000"
  24. * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
  25. * "(blob)00010000"
  26. *
  27. * The attributes are a comma separated list of these possible
  28. * attributes:
  29. *
  30. * + ro - read-only
  31. * + boot - boot-services access
  32. * + run - runtime access
  33. *
  34. * NOTE: with current implementation, no variables are available after
  35. * ExitBootServices, and all are persisted (if possible).
  36. *
  37. * If not specified, the attributes default to "{boot}".
  38. *
  39. * The required type is one of:
  40. *
  41. * + utf8 - raw utf8 string
  42. * + blob - arbitrary length hex string
  43. *
  44. * Maybe a utf16 type would be useful to for a string value to be auto
  45. * converted to utf16?
  46. */
  47. #define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
  48. /**
  49. * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
  50. * variable name
  51. *
  52. * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
  53. * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
  54. * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
  55. *
  56. * @native: pointer to pointer to U-Boot variable name
  57. * @variable_name: UEFI variable name
  58. * @vendor: vendor GUID
  59. * Return: status code
  60. */
  61. static efi_status_t efi_to_native(char **native, const u16 *variable_name,
  62. const efi_guid_t *vendor)
  63. {
  64. size_t len;
  65. char *pos;
  66. len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
  67. *native = malloc(len);
  68. if (!*native)
  69. return EFI_OUT_OF_RESOURCES;
  70. pos = *native;
  71. pos += sprintf(pos, "efi_%pUl_", vendor);
  72. utf16_utf8_strcpy(&pos, variable_name);
  73. return EFI_SUCCESS;
  74. }
  75. /**
  76. * prefix() - skip over prefix
  77. *
  78. * Skip over a prefix string.
  79. *
  80. * @str: string with prefix
  81. * @prefix: prefix string
  82. * Return: string without prefix, or NULL if prefix not found
  83. */
  84. static const char *prefix(const char *str, const char *prefix)
  85. {
  86. size_t n = strlen(prefix);
  87. if (!strncmp(prefix, str, n))
  88. return str + n;
  89. return NULL;
  90. }
  91. /**
  92. * parse_attr() - decode attributes part of variable value
  93. *
  94. * Convert the string encoded attributes of a UEFI variable to a bit mask.
  95. * TODO: Several attributes are not supported.
  96. *
  97. * @str: value of U-Boot variable
  98. * @attrp: pointer to UEFI attributes
  99. * Return: pointer to remainder of U-Boot variable value
  100. */
  101. static const char *parse_attr(const char *str, u32 *attrp)
  102. {
  103. u32 attr = 0;
  104. char sep = '{';
  105. if (*str != '{') {
  106. *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
  107. return str;
  108. }
  109. while (*str == sep) {
  110. const char *s;
  111. str++;
  112. if ((s = prefix(str, "ro"))) {
  113. attr |= READ_ONLY;
  114. } else if ((s = prefix(str, "nv"))) {
  115. attr |= EFI_VARIABLE_NON_VOLATILE;
  116. } else if ((s = prefix(str, "boot"))) {
  117. attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
  118. } else if ((s = prefix(str, "run"))) {
  119. attr |= EFI_VARIABLE_RUNTIME_ACCESS;
  120. } else {
  121. printf("invalid attribute: %s\n", str);
  122. break;
  123. }
  124. str = s;
  125. sep = ',';
  126. }
  127. str++;
  128. *attrp = attr;
  129. return str;
  130. }
  131. /**
  132. * efi_get_variable() - retrieve value of a UEFI variable
  133. *
  134. * This function implements the GetVariable runtime service.
  135. *
  136. * See the Unified Extensible Firmware Interface (UEFI) specification for
  137. * details.
  138. *
  139. * @variable_name: name of the variable
  140. * @vendor: vendor GUID
  141. * @attributes: attributes of the variable
  142. * @data_size: size of the buffer to which the variable value is copied
  143. * @data: buffer to which the variable value is copied
  144. * Return: status code
  145. */
  146. efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
  147. const efi_guid_t *vendor, u32 *attributes,
  148. efi_uintn_t *data_size, void *data)
  149. {
  150. char *native_name;
  151. efi_status_t ret;
  152. unsigned long in_size;
  153. const char *val, *s;
  154. u32 attr;
  155. EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
  156. data_size, data);
  157. if (!variable_name || !vendor || !data_size)
  158. return EFI_EXIT(EFI_INVALID_PARAMETER);
  159. ret = efi_to_native(&native_name, variable_name, vendor);
  160. if (ret)
  161. return EFI_EXIT(ret);
  162. EFI_PRINT("get '%s'\n", native_name);
  163. val = env_get(native_name);
  164. free(native_name);
  165. if (!val)
  166. return EFI_EXIT(EFI_NOT_FOUND);
  167. val = parse_attr(val, &attr);
  168. in_size = *data_size;
  169. if ((s = prefix(val, "(blob)"))) {
  170. size_t len = strlen(s);
  171. /* number of hexadecimal digits must be even */
  172. if (len & 1)
  173. return EFI_EXIT(EFI_DEVICE_ERROR);
  174. /* two characters per byte: */
  175. len /= 2;
  176. *data_size = len;
  177. if (in_size < len) {
  178. ret = EFI_BUFFER_TOO_SMALL;
  179. goto out;
  180. }
  181. if (!data)
  182. return EFI_EXIT(EFI_INVALID_PARAMETER);
  183. if (hex2bin(data, s, len))
  184. return EFI_EXIT(EFI_DEVICE_ERROR);
  185. EFI_PRINT("got value: \"%s\"\n", s);
  186. } else if ((s = prefix(val, "(utf8)"))) {
  187. unsigned len = strlen(s) + 1;
  188. *data_size = len;
  189. if (in_size < len) {
  190. ret = EFI_BUFFER_TOO_SMALL;
  191. goto out;
  192. }
  193. if (!data)
  194. return EFI_EXIT(EFI_INVALID_PARAMETER);
  195. memcpy(data, s, len);
  196. ((char *)data)[len] = '\0';
  197. EFI_PRINT("got value: \"%s\"\n", (char *)data);
  198. } else {
  199. EFI_PRINT("invalid value: '%s'\n", val);
  200. return EFI_EXIT(EFI_DEVICE_ERROR);
  201. }
  202. out:
  203. if (attributes)
  204. *attributes = attr & EFI_VARIABLE_MASK;
  205. return EFI_EXIT(ret);
  206. }
  207. static char *efi_variables_list;
  208. static char *efi_cur_variable;
  209. /**
  210. * parse_uboot_variable() - parse a u-boot variable and get uefi-related
  211. * information
  212. * @variable: whole data of u-boot variable (ie. name=value)
  213. * @variable_name_size: size of variable_name buffer in byte
  214. * @variable_name: name of uefi variable in u16, null-terminated
  215. * @vendor: vendor's guid
  216. * @attributes: attributes
  217. *
  218. * A uefi variable is encoded into a u-boot variable as described above.
  219. * This function parses such a u-boot variable and retrieve uefi-related
  220. * information into respective parameters. In return, variable_name_size
  221. * is the size of variable name including NULL.
  222. *
  223. * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
  224. * the entire variable list has been returned,
  225. * otherwise non-zero status code
  226. */
  227. static efi_status_t parse_uboot_variable(char *variable,
  228. efi_uintn_t *variable_name_size,
  229. u16 *variable_name,
  230. const efi_guid_t *vendor,
  231. u32 *attributes)
  232. {
  233. char *guid, *name, *end, c;
  234. unsigned long name_len;
  235. u16 *p;
  236. guid = strchr(variable, '_');
  237. if (!guid)
  238. return EFI_INVALID_PARAMETER;
  239. guid++;
  240. name = strchr(guid, '_');
  241. if (!name)
  242. return EFI_INVALID_PARAMETER;
  243. name++;
  244. end = strchr(name, '=');
  245. if (!end)
  246. return EFI_INVALID_PARAMETER;
  247. name_len = end - name;
  248. if (*variable_name_size < (name_len + 1)) {
  249. *variable_name_size = name_len + 1;
  250. return EFI_BUFFER_TOO_SMALL;
  251. }
  252. end++; /* point to value */
  253. /* variable name */
  254. p = variable_name;
  255. utf8_utf16_strncpy(&p, name, name_len);
  256. variable_name[name_len] = 0;
  257. *variable_name_size = name_len + 1;
  258. /* guid */
  259. c = *(name - 1);
  260. *(name - 1) = '\0'; /* guid need be null-terminated here */
  261. uuid_str_to_bin(guid, (unsigned char *)vendor, UUID_STR_FORMAT_GUID);
  262. *(name - 1) = c;
  263. /* attributes */
  264. parse_attr(end, attributes);
  265. return EFI_SUCCESS;
  266. }
  267. /**
  268. * efi_get_next_variable_name() - enumerate the current variable names
  269. *
  270. * @variable_name_size: size of variable_name buffer in byte
  271. * @variable_name: name of uefi variable's name in u16
  272. * @vendor: vendor's guid
  273. *
  274. * This function implements the GetNextVariableName service.
  275. *
  276. * See the Unified Extensible Firmware Interface (UEFI) specification for
  277. * details.
  278. *
  279. * Return: status code
  280. */
  281. efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
  282. u16 *variable_name,
  283. const efi_guid_t *vendor)
  284. {
  285. char *native_name, *variable;
  286. ssize_t name_len, list_len;
  287. char regex[256];
  288. char * const regexlist[] = {regex};
  289. u32 attributes;
  290. int i;
  291. efi_status_t ret;
  292. EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
  293. if (!variable_name_size || !variable_name || !vendor)
  294. return EFI_EXIT(EFI_INVALID_PARAMETER);
  295. if (variable_name[0]) {
  296. /* check null-terminated string */
  297. for (i = 0; i < *variable_name_size; i++)
  298. if (!variable_name[i])
  299. break;
  300. if (i >= *variable_name_size)
  301. return EFI_EXIT(EFI_INVALID_PARAMETER);
  302. /* search for the last-returned variable */
  303. ret = efi_to_native(&native_name, variable_name, vendor);
  304. if (ret)
  305. return EFI_EXIT(ret);
  306. name_len = strlen(native_name);
  307. for (variable = efi_variables_list; variable && *variable;) {
  308. if (!strncmp(variable, native_name, name_len) &&
  309. variable[name_len] == '=')
  310. break;
  311. variable = strchr(variable, '\n');
  312. if (variable)
  313. variable++;
  314. }
  315. free(native_name);
  316. if (!(variable && *variable))
  317. return EFI_EXIT(EFI_INVALID_PARAMETER);
  318. /* next variable */
  319. variable = strchr(variable, '\n');
  320. if (variable)
  321. variable++;
  322. if (!(variable && *variable))
  323. return EFI_EXIT(EFI_NOT_FOUND);
  324. } else {
  325. /*
  326. *new search: free a list used in the previous search
  327. */
  328. free(efi_variables_list);
  329. efi_variables_list = NULL;
  330. efi_cur_variable = NULL;
  331. snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
  332. list_len = hexport_r(&env_htab, '\n',
  333. H_MATCH_REGEX | H_MATCH_KEY,
  334. &efi_variables_list, 0, 1, regexlist);
  335. /* 1 indicates that no match was found */
  336. if (list_len <= 1)
  337. return EFI_EXIT(EFI_NOT_FOUND);
  338. variable = efi_variables_list;
  339. }
  340. ret = parse_uboot_variable(variable, variable_name_size, variable_name,
  341. vendor, &attributes);
  342. return EFI_EXIT(ret);
  343. }
  344. /**
  345. * efi_set_variable() - set value of a UEFI variable
  346. *
  347. * This function implements the SetVariable runtime service.
  348. *
  349. * See the Unified Extensible Firmware Interface (UEFI) specification for
  350. * details.
  351. *
  352. * @variable_name: name of the variable
  353. * @vendor: vendor GUID
  354. * @attributes: attributes of the variable
  355. * @data_size: size of the buffer with the variable value
  356. * @data: buffer with the variable value
  357. * Return: status code
  358. */
  359. efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
  360. const efi_guid_t *vendor, u32 attributes,
  361. efi_uintn_t data_size, const void *data)
  362. {
  363. char *native_name = NULL, *val = NULL, *s;
  364. const char *old_val;
  365. size_t old_size;
  366. efi_status_t ret = EFI_SUCCESS;
  367. u32 attr;
  368. EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
  369. data_size, data);
  370. if (!variable_name || !*variable_name || !vendor ||
  371. ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
  372. !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
  373. ret = EFI_INVALID_PARAMETER;
  374. goto out;
  375. }
  376. ret = efi_to_native(&native_name, variable_name, vendor);
  377. if (ret)
  378. goto out;
  379. old_val = env_get(native_name);
  380. if (old_val) {
  381. old_val = parse_attr(old_val, &attr);
  382. /* check read-only first */
  383. if (attr & READ_ONLY) {
  384. ret = EFI_WRITE_PROTECTED;
  385. goto out;
  386. }
  387. if ((data_size == 0 &&
  388. !(attributes & EFI_VARIABLE_APPEND_WRITE)) ||
  389. !attributes) {
  390. /* delete the variable: */
  391. env_set(native_name, NULL);
  392. ret = EFI_SUCCESS;
  393. goto out;
  394. }
  395. /* attributes won't be changed */
  396. if (attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) {
  397. ret = EFI_INVALID_PARAMETER;
  398. goto out;
  399. }
  400. if (attributes & EFI_VARIABLE_APPEND_WRITE) {
  401. if (!prefix(old_val, "(blob)")) {
  402. ret = EFI_DEVICE_ERROR;
  403. goto out;
  404. }
  405. old_size = strlen(old_val);
  406. } else {
  407. old_size = 0;
  408. }
  409. } else {
  410. if (data_size == 0 || !attributes ||
  411. (attributes & EFI_VARIABLE_APPEND_WRITE)) {
  412. /*
  413. * Trying to delete or to update a non-existent
  414. * variable.
  415. */
  416. ret = EFI_NOT_FOUND;
  417. goto out;
  418. }
  419. old_size = 0;
  420. }
  421. val = malloc(old_size + 2 * data_size
  422. + strlen("{ro,run,boot,nv}(blob)") + 1);
  423. if (!val) {
  424. ret = EFI_OUT_OF_RESOURCES;
  425. goto out;
  426. }
  427. s = val;
  428. /* store attributes */
  429. attributes &= (EFI_VARIABLE_NON_VOLATILE |
  430. EFI_VARIABLE_BOOTSERVICE_ACCESS |
  431. EFI_VARIABLE_RUNTIME_ACCESS);
  432. s += sprintf(s, "{");
  433. while (attributes) {
  434. u32 attr = 1 << (ffs(attributes) - 1);
  435. if (attr == EFI_VARIABLE_NON_VOLATILE)
  436. s += sprintf(s, "nv");
  437. else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)
  438. s += sprintf(s, "boot");
  439. else if (attr == EFI_VARIABLE_RUNTIME_ACCESS)
  440. s += sprintf(s, "run");
  441. attributes &= ~attr;
  442. if (attributes)
  443. s += sprintf(s, ",");
  444. }
  445. s += sprintf(s, "}");
  446. if (old_size)
  447. /* APPEND_WRITE */
  448. s += sprintf(s, old_val);
  449. else
  450. s += sprintf(s, "(blob)");
  451. /* store payload: */
  452. s = bin2hex(s, data, data_size);
  453. *s = '\0';
  454. EFI_PRINT("setting: %s=%s\n", native_name, val);
  455. if (env_set(native_name, val))
  456. ret = EFI_DEVICE_ERROR;
  457. out:
  458. free(native_name);
  459. free(val);
  460. return EFI_EXIT(ret);
  461. }
  462. /**
  463. * efi_query_variable_info() - get information about EFI variables
  464. *
  465. * This function implements the QueryVariableInfo() runtime service.
  466. *
  467. * See the Unified Extensible Firmware Interface (UEFI) specification for
  468. * details.
  469. *
  470. * @attributes: bitmask to select variables to be
  471. * queried
  472. * @maximum_variable_storage_size: maximum size of storage area for the
  473. * selected variable types
  474. * @remaining_variable_storage_size: remaining size of storage are for the
  475. * selected variable types
  476. * @maximum_variable_size: maximum size of a variable of the
  477. * selected type
  478. * Returns: status code
  479. */
  480. efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
  481. u32 attributes,
  482. u64 *maximum_variable_storage_size,
  483. u64 *remaining_variable_storage_size,
  484. u64 *maximum_variable_size)
  485. {
  486. return EFI_UNSUPPORTED;
  487. }
  488. /**
  489. * efi_get_variable_runtime() - runtime implementation of GetVariable()
  490. *
  491. * @variable_name: name of the variable
  492. * @vendor: vendor GUID
  493. * @attributes: attributes of the variable
  494. * @data_size: size of the buffer to which the variable value is copied
  495. * @data: buffer to which the variable value is copied
  496. * Return: status code
  497. */
  498. static efi_status_t __efi_runtime EFIAPI
  499. efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
  500. u32 *attributes, efi_uintn_t *data_size, void *data)
  501. {
  502. return EFI_UNSUPPORTED;
  503. }
  504. /**
  505. * efi_get_next_variable_name_runtime() - runtime implementation of
  506. * GetNextVariable()
  507. *
  508. * @variable_name_size: size of variable_name buffer in byte
  509. * @variable_name: name of uefi variable's name in u16
  510. * @vendor: vendor's guid
  511. * Return: status code
  512. */
  513. static efi_status_t __efi_runtime EFIAPI
  514. efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
  515. u16 *variable_name, const efi_guid_t *vendor)
  516. {
  517. return EFI_UNSUPPORTED;
  518. }
  519. /**
  520. * efi_set_variable_runtime() - runtime implementation of SetVariable()
  521. *
  522. * @variable_name: name of the variable
  523. * @vendor: vendor GUID
  524. * @attributes: attributes of the variable
  525. * @data_size: size of the buffer with the variable value
  526. * @data: buffer with the variable value
  527. * Return: status code
  528. */
  529. static efi_status_t __efi_runtime EFIAPI
  530. efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
  531. u32 attributes, efi_uintn_t data_size,
  532. const void *data)
  533. {
  534. return EFI_UNSUPPORTED;
  535. }
  536. /**
  537. * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
  538. */
  539. void efi_variables_boot_exit_notify(void)
  540. {
  541. efi_runtime_services.get_variable = efi_get_variable_runtime;
  542. efi_runtime_services.get_next_variable_name =
  543. efi_get_next_variable_name_runtime;
  544. efi_runtime_services.set_variable = efi_set_variable_runtime;
  545. efi_update_table_header_crc32(&efi_runtime_services.hdr);
  546. }
  547. /**
  548. * efi_init_variables() - initialize variable services
  549. *
  550. * Return: status code
  551. */
  552. efi_status_t efi_init_variables(void)
  553. {
  554. return EFI_SUCCESS;
  555. }