efi_variable.c 16 KB

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