fwu.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2022, Linaro Limited
  4. */
  5. #include <dm.h>
  6. #include <efi.h>
  7. #include <efi_loader.h>
  8. #include <efi_variable.h>
  9. #include <event.h>
  10. #include <fwu.h>
  11. #include <fwu_mdata.h>
  12. #include <malloc.h>
  13. #include <linux/errno.h>
  14. #include <linux/types.h>
  15. #include <u-boot/crc.h>
  16. static struct fwu_mdata g_mdata; /* = {0} makes uninit crc32 always invalid */
  17. static struct udevice *g_dev;
  18. static u8 in_trial;
  19. static u8 boottime_check;
  20. enum {
  21. IMAGE_ACCEPT_SET = 1,
  22. IMAGE_ACCEPT_CLEAR,
  23. };
  24. enum {
  25. PRIMARY_PART = 1,
  26. SECONDARY_PART,
  27. BOTH_PARTS,
  28. };
  29. static int trial_counter_update(u16 *trial_state_ctr)
  30. {
  31. bool delete;
  32. u32 var_attr;
  33. efi_status_t status;
  34. efi_uintn_t var_size;
  35. delete = !trial_state_ctr ? true : false;
  36. var_size = !trial_state_ctr ? 0 : (efi_uintn_t)sizeof(*trial_state_ctr);
  37. var_attr = !trial_state_ctr ? 0 : EFI_VARIABLE_NON_VOLATILE |
  38. EFI_VARIABLE_BOOTSERVICE_ACCESS;
  39. status = efi_set_variable_int(u"TrialStateCtr",
  40. &efi_global_variable_guid,
  41. var_attr,
  42. var_size, trial_state_ctr, false);
  43. if ((delete && (status != EFI_NOT_FOUND &&
  44. status != EFI_SUCCESS)) ||
  45. (!delete && status != EFI_SUCCESS))
  46. return -1;
  47. return 0;
  48. }
  49. static int trial_counter_read(u16 *trial_state_ctr)
  50. {
  51. efi_status_t status;
  52. efi_uintn_t var_size;
  53. var_size = (efi_uintn_t)sizeof(trial_state_ctr);
  54. status = efi_get_variable_int(u"TrialStateCtr",
  55. &efi_global_variable_guid,
  56. NULL,
  57. &var_size, trial_state_ctr,
  58. NULL);
  59. if (status != EFI_SUCCESS) {
  60. log_err("Unable to read TrialStateCtr variable\n");
  61. return -1;
  62. }
  63. return 0;
  64. }
  65. static int fwu_trial_count_update(void)
  66. {
  67. int ret;
  68. u16 trial_state_ctr;
  69. ret = trial_counter_read(&trial_state_ctr);
  70. if (ret) {
  71. log_debug("Unable to read trial_state_ctr\n");
  72. goto out;
  73. }
  74. ++trial_state_ctr;
  75. if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) {
  76. log_info("Trial State count exceeded. Revert back to previous_active_index\n");
  77. ret = fwu_revert_boot_index();
  78. if (ret)
  79. log_err("Unable to revert active_index\n");
  80. ret = 1;
  81. } else {
  82. log_info("Trial State count: attempt %d out of %d\n",
  83. trial_state_ctr, CONFIG_FWU_TRIAL_STATE_CNT);
  84. ret = trial_counter_update(&trial_state_ctr);
  85. if (ret)
  86. log_err("Unable to increment TrialStateCtr variable\n");
  87. }
  88. out:
  89. return ret;
  90. }
  91. static int in_trial_state(struct fwu_mdata *mdata)
  92. {
  93. u32 i, active_bank;
  94. struct fwu_image_entry *img_entry;
  95. struct fwu_image_bank_info *img_bank_info;
  96. active_bank = mdata->active_index;
  97. img_entry = &mdata->img_entry[0];
  98. for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
  99. img_bank_info = &img_entry[i].img_bank_info[active_bank];
  100. if (!img_bank_info->accepted) {
  101. log_info("System booting in Trial State\n");
  102. return 1;
  103. }
  104. }
  105. return 0;
  106. }
  107. static int fwu_get_image_type_id(u8 *image_index, efi_guid_t *image_type_id)
  108. {
  109. u8 index;
  110. int i;
  111. struct efi_fw_image *image;
  112. index = *image_index;
  113. image = update_info.images;
  114. for (i = 0; i < update_info.num_images; i++) {
  115. if (index == image[i].image_index) {
  116. guidcpy(image_type_id, &image[i].image_type_id);
  117. return 0;
  118. }
  119. }
  120. return -ENOENT;
  121. }
  122. /**
  123. * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided
  124. * @mdata: FWU metadata structure
  125. * @part: Bitmask of FWU metadata partitions to be written to
  126. *
  127. * Return: 0 if OK, -ve on error
  128. */
  129. static int fwu_sync_mdata(struct fwu_mdata *mdata, int part)
  130. {
  131. void *buf = &mdata->version;
  132. int err;
  133. if (part == BOTH_PARTS) {
  134. err = fwu_sync_mdata(mdata, SECONDARY_PART);
  135. if (err)
  136. return err;
  137. part = PRIMARY_PART;
  138. }
  139. /*
  140. * Calculate the crc32 for the updated FWU metadata
  141. * and put the updated value in the FWU metadata crc32
  142. * field
  143. */
  144. mdata->crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
  145. err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART);
  146. if (err) {
  147. log_err("Unable to write %s mdata\n",
  148. part == PRIMARY_PART ? "primary" : "secondary");
  149. return err;
  150. }
  151. /* update the cached copy of meta-data */
  152. memcpy(&g_mdata, mdata, sizeof(struct fwu_mdata));
  153. return 0;
  154. }
  155. static inline int mdata_crc_check(struct fwu_mdata *mdata)
  156. {
  157. void *buf = &mdata->version;
  158. u32 calc_crc32 = crc32(0, buf, sizeof(*mdata) - sizeof(u32));
  159. return calc_crc32 == mdata->crc32 ? 0 : -EINVAL;
  160. }
  161. /**
  162. * fwu_get_mdata() - Read, verify and return the FWU metadata
  163. * @mdata: Output FWU metadata read or NULL
  164. *
  165. * Read both the metadata copies from the storage media, verify their checksum,
  166. * and ascertain that both copies match. If one of the copies has gone bad,
  167. * restore it from the good copy.
  168. *
  169. * Return: 0 if OK, -ve on error
  170. */
  171. int fwu_get_mdata(struct fwu_mdata *mdata)
  172. {
  173. int err;
  174. bool parts_ok[2] = { false };
  175. struct fwu_mdata s, *parts_mdata[2];
  176. parts_mdata[0] = &g_mdata;
  177. parts_mdata[1] = &s;
  178. /* if mdata already read and ready */
  179. err = mdata_crc_check(parts_mdata[0]);
  180. if (!err)
  181. goto ret_mdata;
  182. /* else read, verify and, if needed, fix mdata */
  183. for (int i = 0; i < 2; i++) {
  184. parts_ok[i] = false;
  185. err = fwu_read_mdata(g_dev, parts_mdata[i], !i);
  186. if (!err) {
  187. err = mdata_crc_check(parts_mdata[i]);
  188. if (!err)
  189. parts_ok[i] = true;
  190. else
  191. log_debug("mdata : %s crc32 failed\n", i ? "secondary" : "primary");
  192. }
  193. }
  194. if (parts_ok[0] && parts_ok[1]) {
  195. /*
  196. * Before returning, check that both the
  197. * FWU metadata copies are the same.
  198. */
  199. err = memcmp(parts_mdata[0], parts_mdata[1], sizeof(struct fwu_mdata));
  200. if (!err)
  201. goto ret_mdata;
  202. /*
  203. * If not, populate the secondary partition from the
  204. * primary partition copy.
  205. */
  206. log_info("Both FWU metadata copies are valid but do not match.");
  207. log_info(" Restoring the secondary partition from the primary\n");
  208. parts_ok[1] = false;
  209. }
  210. for (int i = 0; i < 2; i++) {
  211. if (parts_ok[i])
  212. continue;
  213. memcpy(parts_mdata[i], parts_mdata[1 - i], sizeof(struct fwu_mdata));
  214. err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART);
  215. if (err) {
  216. log_debug("mdata : %s write failed\n", i ? "secondary" : "primary");
  217. return err;
  218. }
  219. }
  220. ret_mdata:
  221. if (!err && mdata)
  222. memcpy(mdata, parts_mdata[0], sizeof(struct fwu_mdata));
  223. return err;
  224. }
  225. /**
  226. * fwu_get_active_index() - Get active_index from the FWU metadata
  227. * @active_idx: active_index value to be read
  228. *
  229. * Read the active_index field from the FWU metadata and place it in
  230. * the variable pointed to be the function argument.
  231. *
  232. * Return: 0 if OK, -ve on error
  233. *
  234. */
  235. int fwu_get_active_index(uint *active_idx)
  236. {
  237. int ret = 0;
  238. struct fwu_mdata *mdata = &g_mdata;
  239. /*
  240. * Found the FWU metadata partition, now read the active_index
  241. * value
  242. */
  243. *active_idx = mdata->active_index;
  244. if (*active_idx >= CONFIG_FWU_NUM_BANKS) {
  245. log_debug("Active index value read is incorrect\n");
  246. ret = -EINVAL;
  247. }
  248. return ret;
  249. }
  250. /**
  251. * fwu_set_active_index() - Set active_index in the FWU metadata
  252. * @active_idx: active_index value to be set
  253. *
  254. * Update the active_index field in the FWU metadata
  255. *
  256. * Return: 0 if OK, -ve on error
  257. *
  258. */
  259. int fwu_set_active_index(uint active_idx)
  260. {
  261. int ret;
  262. struct fwu_mdata *mdata = &g_mdata;
  263. if (active_idx >= CONFIG_FWU_NUM_BANKS) {
  264. log_debug("Invalid active index value\n");
  265. return -EINVAL;
  266. }
  267. /*
  268. * Update the active index and previous_active_index fields
  269. * in the FWU metadata
  270. */
  271. mdata->previous_active_index = mdata->active_index;
  272. mdata->active_index = active_idx;
  273. /*
  274. * Now write this updated FWU metadata to both the
  275. * FWU metadata partitions
  276. */
  277. ret = fwu_sync_mdata(mdata, BOTH_PARTS);
  278. if (ret) {
  279. log_debug("Failed to update FWU metadata partitions\n");
  280. ret = -EIO;
  281. }
  282. return ret;
  283. }
  284. /**
  285. * fwu_get_image_index() - Get the Image Index to be used for capsule update
  286. * @image_index: The Image Index for the image
  287. *
  288. * The FWU multi bank update feature computes the value of image_index at
  289. * runtime, based on the bank to which the image needs to be written to.
  290. * Derive the image_index value for the image.
  291. *
  292. * Currently, the capsule update driver uses the DFU framework for
  293. * the updates. This function gets the DFU alt number which is to
  294. * be used as the Image Index
  295. *
  296. * Return: 0 if OK, -ve on error
  297. *
  298. */
  299. int fwu_get_image_index(u8 *image_index)
  300. {
  301. int ret, i;
  302. u8 alt_num;
  303. uint update_bank;
  304. efi_guid_t *image_guid, image_type_id;
  305. struct fwu_mdata *mdata = &g_mdata;
  306. struct fwu_image_entry *img_entry;
  307. struct fwu_image_bank_info *img_bank_info;
  308. ret = fwu_plat_get_update_index(&update_bank);
  309. if (ret) {
  310. log_debug("Failed to get the FWU update bank\n");
  311. goto out;
  312. }
  313. ret = fwu_get_image_type_id(image_index, &image_type_id);
  314. if (ret) {
  315. log_debug("Unable to get image_type_id for image_index %u\n",
  316. *image_index);
  317. goto out;
  318. }
  319. ret = -EINVAL;
  320. /*
  321. * The FWU metadata has been read. Now get the image_uuid for the
  322. * image with the update_bank.
  323. */
  324. for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
  325. if (!guidcmp(&image_type_id,
  326. &mdata->img_entry[i].image_type_uuid)) {
  327. img_entry = &mdata->img_entry[i];
  328. img_bank_info = &img_entry->img_bank_info[update_bank];
  329. image_guid = &img_bank_info->image_uuid;
  330. ret = fwu_plat_get_alt_num(g_dev, image_guid, &alt_num);
  331. if (ret) {
  332. log_debug("alt_num not found for partition with GUID %pUs\n",
  333. image_guid);
  334. } else {
  335. log_debug("alt_num %d for partition %pUs\n",
  336. alt_num, image_guid);
  337. *image_index = alt_num + 1;
  338. }
  339. goto out;
  340. }
  341. }
  342. log_err("Partition with the image type %pUs not found\n",
  343. &image_type_id);
  344. out:
  345. return ret;
  346. }
  347. /**
  348. * fwu_revert_boot_index() - Revert the active index in the FWU metadata
  349. *
  350. * Revert the active_index value in the FWU metadata, by swapping the values
  351. * of active_index and previous_active_index in both copies of the
  352. * FWU metadata.
  353. *
  354. * Return: 0 if OK, -ve on error
  355. *
  356. */
  357. int fwu_revert_boot_index(void)
  358. {
  359. int ret;
  360. u32 cur_active_index;
  361. struct fwu_mdata *mdata = &g_mdata;
  362. /*
  363. * Swap the active index and previous_active_index fields
  364. * in the FWU metadata
  365. */
  366. cur_active_index = mdata->active_index;
  367. mdata->active_index = mdata->previous_active_index;
  368. mdata->previous_active_index = cur_active_index;
  369. /*
  370. * Now write this updated FWU metadata to both the
  371. * FWU metadata partitions
  372. */
  373. ret = fwu_sync_mdata(mdata, BOTH_PARTS);
  374. if (ret) {
  375. log_debug("Failed to update FWU metadata partitions\n");
  376. ret = -EIO;
  377. }
  378. return ret;
  379. }
  380. /**
  381. * fwu_clrset_image_accept() - Set or Clear the Acceptance bit for the image
  382. * @img_type_id: GUID of the image type for which the accepted bit is to be
  383. * set or cleared
  384. * @bank: Bank of which the image's Accept bit is to be set or cleared
  385. * @action: Action which specifies whether image's Accept bit is to be set or
  386. * cleared
  387. *
  388. * Set/Clear the accepted bit for the image specified by the img_guid parameter.
  389. * This indicates acceptance or rejection of image for subsequent boots by some
  390. * governing component like OS(or firmware).
  391. *
  392. * Return: 0 if OK, -ve on error
  393. *
  394. */
  395. static int fwu_clrset_image_accept(efi_guid_t *img_type_id, u32 bank, u8 action)
  396. {
  397. int ret, i;
  398. struct fwu_mdata *mdata = &g_mdata;
  399. struct fwu_image_entry *img_entry;
  400. struct fwu_image_bank_info *img_bank_info;
  401. img_entry = &mdata->img_entry[0];
  402. for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
  403. if (!guidcmp(&img_entry[i].image_type_uuid, img_type_id)) {
  404. img_bank_info = &img_entry[i].img_bank_info[bank];
  405. if (action == IMAGE_ACCEPT_SET)
  406. img_bank_info->accepted |= FWU_IMAGE_ACCEPTED;
  407. else
  408. img_bank_info->accepted = 0;
  409. ret = fwu_sync_mdata(mdata, BOTH_PARTS);
  410. goto out;
  411. }
  412. }
  413. /* Image not found */
  414. ret = -ENOENT;
  415. out:
  416. return ret;
  417. }
  418. /**
  419. * fwu_accept_image() - Set the Acceptance bit for the image
  420. * @img_type_id: GUID of the image type for which the accepted bit is to be
  421. * cleared
  422. * @bank: Bank of which the image's Accept bit is to be set
  423. *
  424. * Set the accepted bit for the image specified by the img_guid parameter. This
  425. * indicates acceptance of image for subsequent boots by some governing component
  426. * like OS(or firmware).
  427. *
  428. * Return: 0 if OK, -ve on error
  429. *
  430. */
  431. int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
  432. {
  433. return fwu_clrset_image_accept(img_type_id, bank,
  434. IMAGE_ACCEPT_SET);
  435. }
  436. /**
  437. * fwu_clear_accept_image() - Clear the Acceptance bit for the image
  438. * @img_type_id: GUID of the image type for which the accepted bit is to be
  439. * cleared
  440. * @bank: Bank of which the image's Accept bit is to be cleared
  441. *
  442. * Clear the accepted bit for the image type specified by the img_type_id parameter.
  443. * This function is called after the image has been updated. The accepted bit is
  444. * cleared to be set subsequently after passing the image acceptance criteria, by
  445. * either the OS(or firmware)
  446. *
  447. * Return: 0 if OK, -ve on error
  448. *
  449. */
  450. int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
  451. {
  452. return fwu_clrset_image_accept(img_type_id, bank,
  453. IMAGE_ACCEPT_CLEAR);
  454. }
  455. /**
  456. * fwu_plat_get_update_index() - Get the value of the update bank
  457. * @update_idx: Bank number to which images are to be updated
  458. *
  459. * Get the value of the bank(partition) to which the update needs to be
  460. * made.
  461. *
  462. * Note: This is a weak function and platforms can override this with
  463. * their own implementation for selection of the update bank.
  464. *
  465. * Return: 0 if OK, -ve on error
  466. *
  467. */
  468. __weak int fwu_plat_get_update_index(uint *update_idx)
  469. {
  470. int ret;
  471. u32 active_idx;
  472. ret = fwu_get_active_index(&active_idx);
  473. if (ret < 0)
  474. return -1;
  475. *update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS;
  476. return ret;
  477. }
  478. /**
  479. * fwu_plat_get_bootidx() - Get the value of the boot index
  480. * @boot_idx: Boot index value
  481. *
  482. * Get the value of the bank(partition) from which the platform
  483. * has booted. This value is passed to U-Boot from the earlier
  484. * stage bootloader which loads and boots all the relevant
  485. * firmware images
  486. */
  487. __weak void fwu_plat_get_bootidx(uint *boot_idx)
  488. {
  489. int ret;
  490. ret = fwu_get_active_index(boot_idx);
  491. if (ret < 0)
  492. *boot_idx = 0; /* Dummy value */
  493. }
  494. /**
  495. * fwu_update_checks_pass() - Check if FWU update can be done
  496. *
  497. * Check if the FWU update can be executed. The updates are
  498. * allowed only when the platform is not in Trial State and
  499. * the boot time checks have passed
  500. *
  501. * Return: 1 if OK, 0 if checks do not pass
  502. *
  503. */
  504. u8 fwu_update_checks_pass(void)
  505. {
  506. return !in_trial && boottime_check;
  507. }
  508. /**
  509. * fwu_empty_capsule_checks_pass() - Check if empty capsule can be processed
  510. *
  511. * Check if the empty capsule can be processed to either accept or revert
  512. * an earlier executed update. The empty capsules need to be processed
  513. * only when the platform is in Trial State and the boot time checks have
  514. * passed
  515. *
  516. * Return: 1 if OK, 0 if not to be allowed
  517. *
  518. */
  519. u8 fwu_empty_capsule_checks_pass(void)
  520. {
  521. return in_trial && boottime_check;
  522. }
  523. /**
  524. * fwu_trial_state_ctr_start() - Start the Trial State counter
  525. *
  526. * Start the counter to identify the platform booting in the
  527. * Trial State. The counter is implemented as an EFI variable.
  528. *
  529. * Return: 0 if OK, -ve on error
  530. *
  531. */
  532. int fwu_trial_state_ctr_start(void)
  533. {
  534. int ret;
  535. u16 trial_state_ctr;
  536. trial_state_ctr = 0;
  537. ret = trial_counter_update(&trial_state_ctr);
  538. if (ret)
  539. log_err("Unable to initialise TrialStateCtr\n");
  540. return ret;
  541. }
  542. static int fwu_boottime_checks(void *ctx, struct event *event)
  543. {
  544. int ret;
  545. u32 boot_idx, active_idx;
  546. /* Don't have boot time checks on sandbox */
  547. if (IS_ENABLED(CONFIG_SANDBOX)) {
  548. boottime_check = 1;
  549. return 0;
  550. }
  551. ret = uclass_first_device_err(UCLASS_FWU_MDATA, &g_dev);
  552. if (ret) {
  553. log_debug("Cannot find fwu device\n");
  554. return ret;
  555. }
  556. ret = fwu_get_mdata(NULL);
  557. if (ret) {
  558. log_debug("Unable to read meta-data\n");
  559. return ret;
  560. }
  561. /*
  562. * Get the Boot Index, i.e. the bank from
  563. * which the platform has booted. This value
  564. * gets passed from the ealier stage bootloader
  565. * which booted u-boot, e.g. tf-a. If the
  566. * boot index is not the same as the
  567. * active_index read from the FWU metadata,
  568. * update the active_index.
  569. */
  570. fwu_plat_get_bootidx(&boot_idx);
  571. if (boot_idx >= CONFIG_FWU_NUM_BANKS) {
  572. log_err("Received incorrect value of boot_index\n");
  573. return 0;
  574. }
  575. ret = fwu_get_active_index(&active_idx);
  576. if (ret) {
  577. log_err("Unable to read active_index\n");
  578. return 0;
  579. }
  580. if (boot_idx != active_idx) {
  581. log_info("Boot idx %u is not matching active idx %u, changing active_idx\n",
  582. boot_idx, active_idx);
  583. ret = fwu_set_active_index(boot_idx);
  584. if (!ret)
  585. boottime_check = 1;
  586. }
  587. if (efi_init_obj_list() != EFI_SUCCESS)
  588. return 0;
  589. in_trial = in_trial_state(&g_mdata);
  590. if (!in_trial || (ret = fwu_trial_count_update()) > 0)
  591. ret = trial_counter_update(NULL);
  592. if (!ret)
  593. boottime_check = 1;
  594. return 0;
  595. }
  596. EVENT_SPY(EVT_MAIN_LOOP, fwu_boottime_checks);