ec_sync_tests.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * Tests for vboot_api_kernel, part 3 - software sync
  6. */
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "2sysincludes.h"
  11. #include "2common.h"
  12. #include "2misc.h"
  13. #include "2nvstorage.h"
  14. #include "ec_sync.h"
  15. #include "gbb_header.h"
  16. #include "host_common.h"
  17. #include "load_kernel_fw.h"
  18. #include "rollback_index.h"
  19. #include "test_common.h"
  20. #include "vboot_audio.h"
  21. #include "vboot_common.h"
  22. #include "vboot_display.h"
  23. #include "vboot_kernel.h"
  24. #include "vboot_nvstorage.h"
  25. #include "vboot_struct.h"
  26. /* Mock data */
  27. static VbCommonParams cparams;
  28. static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
  29. static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
  30. static GoogleBinaryBlockHeader gbb;
  31. static int trust_ec;
  32. static int mock_in_rw;
  33. static VbError_t in_rw_retval;
  34. static int protect_retval;
  35. static int ec_ro_protected;
  36. static int ec_rw_protected;
  37. static int run_retval;
  38. static int ec_run_image;
  39. static int update_retval;
  40. static int ec_ro_updated;
  41. static int ec_rw_updated;
  42. static int get_expected_retval;
  43. static int shutdown_request_calls_left;
  44. static uint8_t mock_ec_ro_hash[32];
  45. static uint8_t mock_ec_rw_hash[32];
  46. static int mock_ec_ro_hash_size;
  47. static int mock_ec_rw_hash_size;
  48. static uint8_t want_ec_hash[32];
  49. static uint8_t update_hash;
  50. static int want_ec_hash_size;
  51. static struct vb2_context ctx;
  52. static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE];
  53. static struct vb2_shared_data *sd;
  54. static uint32_t screens_displayed[8];
  55. static uint32_t screens_count = 0;
  56. /* Reset mock data (for use before each test) */
  57. static void ResetMocks(void)
  58. {
  59. memset(&cparams, 0, sizeof(cparams));
  60. cparams.shared_data_size = sizeof(shared_data);
  61. cparams.shared_data_blob = shared_data;
  62. cparams.gbb_data = &gbb;
  63. memset(&gbb, 0, sizeof(gbb));
  64. gbb.major_version = GBB_MAJOR_VER;
  65. gbb.minor_version = GBB_MINOR_VER;
  66. gbb.flags = GBB_FLAG_DISABLE_PD_SOFTWARE_SYNC;
  67. cparams.gbb = &gbb;
  68. memset(&ctx, 0, sizeof(ctx));
  69. ctx.workbuf = workbuf;
  70. ctx.workbuf_size = sizeof(workbuf);
  71. vb2_init_context(&ctx);
  72. vb2_nv_init(&ctx);
  73. sd = vb2_get_sd(&ctx);
  74. memset(&shared_data, 0, sizeof(shared_data));
  75. VbSharedDataInit(shared, sizeof(shared_data));
  76. shared->flags = VBSD_EC_SOFTWARE_SYNC;
  77. trust_ec = 0;
  78. mock_in_rw = 0;
  79. ec_ro_protected = 0;
  80. ec_rw_protected = 0;
  81. ec_run_image = 0; /* 0 = RO, 1 = RW */
  82. ec_ro_updated = 0;
  83. ec_rw_updated = 0;
  84. in_rw_retval = VBERROR_SUCCESS;
  85. protect_retval = VBERROR_SUCCESS;
  86. update_retval = VBERROR_SUCCESS;
  87. run_retval = VBERROR_SUCCESS;
  88. get_expected_retval = VBERROR_SUCCESS;
  89. shutdown_request_calls_left = -1;
  90. memset(mock_ec_ro_hash, 0, sizeof(mock_ec_ro_hash));
  91. mock_ec_ro_hash[0] = 42;
  92. mock_ec_ro_hash_size = sizeof(mock_ec_ro_hash);
  93. memset(mock_ec_rw_hash, 0, sizeof(mock_ec_rw_hash));
  94. mock_ec_rw_hash[0] = 42;
  95. mock_ec_rw_hash_size = sizeof(mock_ec_rw_hash);
  96. memset(want_ec_hash, 0, sizeof(want_ec_hash));
  97. want_ec_hash[0] = 42;
  98. want_ec_hash_size = sizeof(want_ec_hash);
  99. update_hash = 42;
  100. // TODO: ensure these are actually needed
  101. memset(screens_displayed, 0, sizeof(screens_displayed));
  102. screens_count = 0;
  103. }
  104. /* Mock functions */
  105. uint32_t VbExIsShutdownRequested(void)
  106. {
  107. if (shutdown_request_calls_left == 0)
  108. return 1;
  109. else if (shutdown_request_calls_left > 0)
  110. shutdown_request_calls_left--;
  111. return 0;
  112. }
  113. int VbExTrustEC(int devidx)
  114. {
  115. return trust_ec;
  116. }
  117. VbError_t VbExEcRunningRW(int devidx, int *in_rw)
  118. {
  119. *in_rw = mock_in_rw;
  120. return in_rw_retval;
  121. }
  122. VbError_t VbExEcProtect(int devidx, enum VbSelectFirmware_t select)
  123. {
  124. if (select == VB_SELECT_FIRMWARE_READONLY)
  125. ec_ro_protected = 1;
  126. else
  127. ec_rw_protected = 1;
  128. return protect_retval;
  129. }
  130. VbError_t VbExEcDisableJump(int devidx)
  131. {
  132. return run_retval;
  133. }
  134. VbError_t VbExEcJumpToRW(int devidx)
  135. {
  136. ec_run_image = 1;
  137. mock_in_rw = 1;
  138. return run_retval;
  139. }
  140. VbError_t VbExEcHashImage(int devidx, enum VbSelectFirmware_t select,
  141. const uint8_t **hash, int *hash_size)
  142. {
  143. *hash = select == VB_SELECT_FIRMWARE_READONLY ?
  144. mock_ec_ro_hash : mock_ec_rw_hash;
  145. *hash_size = select == VB_SELECT_FIRMWARE_READONLY ?
  146. mock_ec_ro_hash_size : mock_ec_rw_hash_size;
  147. return *hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED;
  148. }
  149. VbError_t VbExEcGetExpectedImage(int devidx, enum VbSelectFirmware_t select,
  150. const uint8_t **image, int *image_size)
  151. {
  152. static uint8_t fake_image[64] = {5, 6, 7, 8};
  153. *image = fake_image;
  154. *image_size = sizeof(fake_image);
  155. return get_expected_retval;
  156. }
  157. VbError_t VbExEcGetExpectedImageHash(int devidx, enum VbSelectFirmware_t select,
  158. const uint8_t **hash, int *hash_size)
  159. {
  160. *hash = want_ec_hash;
  161. *hash_size = want_ec_hash_size;
  162. return want_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED;
  163. }
  164. VbError_t VbExEcUpdateImage(int devidx, enum VbSelectFirmware_t select,
  165. const uint8_t *image, int image_size)
  166. {
  167. if (select == VB_SELECT_FIRMWARE_READONLY) {
  168. ec_ro_updated = 1;
  169. mock_ec_ro_hash[0] = update_hash;
  170. } else {
  171. ec_rw_updated = 1;
  172. mock_ec_rw_hash[0] = update_hash;
  173. }
  174. return update_retval;
  175. }
  176. VbError_t VbDisplayScreen(struct vb2_context *ctx, VbCommonParams *cparams,
  177. uint32_t screen, int force)
  178. {
  179. if (screens_count < ARRAY_SIZE(screens_displayed))
  180. screens_displayed[screens_count++] = screen;
  181. return VBERROR_SUCCESS;
  182. }
  183. static void test_ssync(VbError_t retval, int recovery_reason, const char *desc)
  184. {
  185. TEST_EQ(ec_sync_all(&ctx, &cparams), retval, desc);
  186. TEST_EQ(vb2_nv_get(&ctx, VB2_NV_RECOVERY_REQUEST),
  187. recovery_reason, " recovery reason");
  188. }
  189. /* Tests */
  190. static void VbSoftwareSyncTest(void)
  191. {
  192. /* Recovery cases */
  193. ResetMocks();
  194. sd->recovery_reason = 123;
  195. test_ssync(0, 0, "In recovery, EC-RO");
  196. TEST_EQ(ec_rw_protected, 0, " ec rw protected");
  197. ResetMocks();
  198. sd->recovery_reason = 123;
  199. mock_in_rw = 1;
  200. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  201. 123, "Recovery needs EC-RO");
  202. /* AP-RO cases */
  203. ResetMocks();
  204. in_rw_retval = VBERROR_SIMULATED;
  205. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  206. VBNV_RECOVERY_EC_UNKNOWN_IMAGE, "Unknown EC image");
  207. /* Calculate hashes */
  208. ResetMocks();
  209. mock_ec_rw_hash_size = 0;
  210. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  211. VBNV_RECOVERY_EC_HASH_FAILED, "Bad EC hash");
  212. ResetMocks();
  213. mock_ec_rw_hash_size = 16;
  214. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  215. VBNV_RECOVERY_EC_HASH_SIZE, "Bad EC hash size");
  216. ResetMocks();
  217. want_ec_hash_size = 0;
  218. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  219. VBNV_RECOVERY_EC_EXPECTED_HASH, "Bad precalculated hash");
  220. ResetMocks();
  221. want_ec_hash_size = 16;
  222. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  223. VBNV_RECOVERY_EC_HASH_SIZE,
  224. "Hash size mismatch");
  225. ResetMocks();
  226. want_ec_hash_size = 4;
  227. mock_ec_rw_hash_size = 4;
  228. test_ssync(0, 0, "Custom hash size");
  229. /* Updates required */
  230. ResetMocks();
  231. mock_in_rw = 1;
  232. mock_ec_rw_hash[0]++;
  233. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  234. 0, "Pending update needs reboot");
  235. ResetMocks();
  236. mock_ec_rw_hash[0]++;
  237. vb2_nv_set(&ctx, VB2_NV_TRY_RO_SYNC, 1);
  238. test_ssync(0, 0, "Update rw without reboot");
  239. TEST_EQ(ec_rw_protected, 1, " ec rw protected");
  240. TEST_EQ(ec_run_image, 1, " ec run image");
  241. TEST_EQ(ec_rw_updated, 1, " ec rw updated");
  242. TEST_EQ(ec_ro_protected, 1, " ec ro protected");
  243. TEST_EQ(ec_ro_updated, 0, " ec ro updated");
  244. ResetMocks();
  245. mock_ec_rw_hash[0]++;
  246. mock_ec_ro_hash[0]++;
  247. vb2_nv_set(&ctx, VB2_NV_TRY_RO_SYNC, 1);
  248. test_ssync(0, 0, "Update rw and ro images without reboot");
  249. TEST_EQ(ec_rw_protected, 1, " ec rw protected");
  250. TEST_EQ(ec_run_image, 1, " ec run image");
  251. TEST_EQ(ec_rw_updated, 1, " ec rw updated");
  252. TEST_EQ(ec_ro_protected, 1, " ec ro protected");
  253. TEST_EQ(ec_ro_updated, 1, " ec ro updated");
  254. ResetMocks();
  255. shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED;
  256. vb2_nv_set(&ctx, VB2_NV_TRY_RO_SYNC, 1);
  257. mock_ec_rw_hash[0]++;
  258. mock_ec_ro_hash[0]++;
  259. test_ssync(0, 0, "WP enabled");
  260. TEST_EQ(ec_rw_protected, 1, " ec rw protected");
  261. TEST_EQ(ec_run_image, 1, " ec run image");
  262. TEST_EQ(ec_rw_updated, 1, " ec rw updated");
  263. TEST_EQ(ec_ro_protected, 1, " ec ro protected");
  264. TEST_EQ(ec_ro_updated, 0, " ec ro updated");
  265. ResetMocks();
  266. vb2_nv_set(&ctx, VB2_NV_TRY_RO_SYNC, 1);
  267. mock_ec_ro_hash[0]++;
  268. test_ssync(0, 0, "rw update not needed");
  269. TEST_EQ(ec_rw_protected, 1, " ec rw protected");
  270. TEST_EQ(ec_run_image, 1, " ec run image");
  271. TEST_EQ(ec_rw_updated, 0, " ec rw not updated");
  272. TEST_EQ(ec_ro_protected, 1, " ec ro protected");
  273. TEST_EQ(ec_ro_updated, 1, " ec ro updated");
  274. ResetMocks();
  275. mock_ec_rw_hash[0]++;
  276. mock_ec_ro_hash[0]++;
  277. test_ssync(0, 0, "ro update not requested");
  278. TEST_EQ(ec_rw_protected, 1, " ec rw protected");
  279. TEST_EQ(ec_run_image, 1, " ec run image");
  280. TEST_EQ(ec_rw_updated, 1, " ec rw updated");
  281. TEST_EQ(ec_ro_protected, 1, " ec ro protected");
  282. TEST_EQ(ec_ro_updated, 0, " ec ro updated");
  283. ResetMocks();
  284. mock_ec_rw_hash[0]++;
  285. update_hash++;
  286. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  287. VBNV_RECOVERY_EC_UPDATE, "updated hash mismatch");
  288. TEST_EQ(ec_rw_protected, 0, " ec rw protected");
  289. TEST_EQ(ec_run_image, 0, " ec run image");
  290. TEST_EQ(ec_rw_updated, 1, " ec rw updated");
  291. TEST_EQ(ec_ro_protected, 0, " ec ro protected");
  292. TEST_EQ(ec_ro_updated, 0, " ec ro updated");
  293. ResetMocks();
  294. mock_ec_rw_hash[0]++;
  295. update_retval = VBERROR_EC_REBOOT_TO_RO_REQUIRED;
  296. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  297. 0, "Reboot after rw update");
  298. TEST_EQ(ec_rw_updated, 1, " ec rw updated");
  299. TEST_EQ(ec_ro_updated, 0, " ec rw updated");
  300. ResetMocks();
  301. mock_ec_rw_hash[0]++;
  302. update_retval = VBERROR_SIMULATED;
  303. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  304. VBNV_RECOVERY_EC_UPDATE, "Update failed");
  305. ResetMocks();
  306. mock_ec_rw_hash[0]++;
  307. shared->flags |= VBSD_EC_SLOW_UPDATE;
  308. test_ssync(0, 0, "Slow update");
  309. TEST_EQ(screens_displayed[0], VB_SCREEN_WAIT, " wait screen");
  310. /* RW cases, no update */
  311. ResetMocks();
  312. mock_in_rw = 1;
  313. test_ssync(0, 0, "AP-RW, EC-RW");
  314. ResetMocks();
  315. test_ssync(0, 0, "AP-RW, EC-RO -> EC-RW");
  316. TEST_EQ(ec_rw_protected, 1, " ec rw protected");
  317. TEST_EQ(ec_run_image, 1, " ec run image");
  318. TEST_EQ(ec_rw_updated, 0, " ec rw updated");
  319. TEST_EQ(ec_ro_protected, 1, " ec ro protected");
  320. TEST_EQ(ec_ro_updated, 0, " ec ro updated");
  321. ResetMocks();
  322. run_retval = VBERROR_SIMULATED;
  323. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  324. VBNV_RECOVERY_EC_JUMP_RW, "Jump to RW fail");
  325. ResetMocks();
  326. run_retval = VBERROR_EC_REBOOT_TO_RO_REQUIRED;
  327. test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  328. 0, "Jump to RW fail because locked");
  329. ResetMocks();
  330. protect_retval = VBERROR_SIMULATED;
  331. test_ssync(VBERROR_SIMULATED,
  332. VBNV_RECOVERY_EC_PROTECT, "Protect error");
  333. /* No longer check for shutdown requested */
  334. ResetMocks();
  335. shutdown_request_calls_left = 0;
  336. test_ssync(0, 0,
  337. "AP-RW, EC-RO -> EC-RW shutdown requested");
  338. ResetMocks();
  339. mock_in_rw = 1;
  340. shutdown_request_calls_left = 0;
  341. test_ssync(0, 0, "AP-RW shutdown requested");
  342. }
  343. int main(void)
  344. {
  345. VbSoftwareSyncTest();
  346. return gTestSuccess ? 0 : 255;
  347. }