vboot_api_kernel4_tests.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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 4 - select and load kernel
  6. */
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include "ec_sync.h"
  11. #include "gbb_header.h"
  12. #include "host_common.h"
  13. #include "load_kernel_fw.h"
  14. #include "rollback_index.h"
  15. #include "test_common.h"
  16. #include "vboot_audio.h"
  17. #include "vboot_common.h"
  18. #include "vboot_kernel.h"
  19. #include "vboot_nvstorage.h"
  20. #include "vboot_struct.h"
  21. /* Mock data */
  22. static VbCommonParams cparams;
  23. static VbSelectAndLoadKernelParams kparams;
  24. static VbNvContext vnc;
  25. static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
  26. static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
  27. static GoogleBinaryBlockHeader gbb;
  28. static int ecsync_retval;
  29. static uint32_t rkr_version;
  30. static uint32_t new_version;
  31. static struct RollbackSpaceFwmp rfr_fwmp;
  32. static int rkr_retval, rkw_retval, rkl_retval, rfr_retval;
  33. static VbError_t vbboot_retval;
  34. /* Reset mock data (for use before each test) */
  35. static void ResetMocks(void)
  36. {
  37. memset(&cparams, 0, sizeof(cparams));
  38. cparams.shared_data_size = sizeof(shared_data);
  39. cparams.shared_data_blob = shared_data;
  40. cparams.gbb_data = &gbb;
  41. cparams.gbb_size = sizeof(gbb);
  42. memset(&kparams, 0, sizeof(kparams));
  43. memset(&gbb, 0, sizeof(gbb));
  44. gbb.major_version = GBB_MAJOR_VER;
  45. gbb.minor_version = GBB_MINOR_VER;
  46. gbb.flags = 0;
  47. memset(&vnc, 0, sizeof(vnc));
  48. VbNvSetup(&vnc);
  49. VbNvTeardown(&vnc); /* So CRC gets generated */
  50. memset(&shared_data, 0, sizeof(shared_data));
  51. VbSharedDataInit(shared, sizeof(shared_data));
  52. memset(&rfr_fwmp, 0, sizeof(rfr_fwmp));
  53. rfr_retval = TPM_SUCCESS;
  54. ecsync_retval = VBERROR_SUCCESS;
  55. rkr_version = new_version = 0x10002;
  56. rkr_retval = rkw_retval = rkl_retval = VBERROR_SUCCESS;
  57. vbboot_retval = VBERROR_SUCCESS;
  58. }
  59. /* Mock functions */
  60. VbError_t VbExNvStorageRead(uint8_t *buf)
  61. {
  62. memcpy(buf, vnc.raw, sizeof(vnc.raw));
  63. return VBERROR_SUCCESS;
  64. }
  65. VbError_t VbExNvStorageWrite(const uint8_t *buf)
  66. {
  67. memcpy(vnc.raw, buf, sizeof(vnc.raw));
  68. return VBERROR_SUCCESS;
  69. }
  70. VbError_t VbExEcRunningRW(int devidx, int *in_rw)
  71. {
  72. return ecsync_retval;
  73. }
  74. uint32_t RollbackKernelRead(uint32_t *version)
  75. {
  76. *version = rkr_version;
  77. return rkr_retval;
  78. }
  79. uint32_t RollbackKernelWrite(uint32_t version)
  80. {
  81. TEST_EQ(version, new_version, "RollbackKernelWrite new version");
  82. rkr_version = version;
  83. return rkw_retval;
  84. }
  85. uint32_t RollbackKernelLock(int recovery_mode)
  86. {
  87. return rkl_retval;
  88. }
  89. uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
  90. {
  91. memcpy(fwmp, &rfr_fwmp, sizeof(*fwmp));
  92. return rfr_retval;
  93. }
  94. uint32_t VbTryLoadKernel(struct vb2_context *ctx, VbCommonParams *cparams,
  95. uint32_t get_info_flags)
  96. {
  97. shared->kernel_version_tpm = new_version;
  98. if (vbboot_retval == -1)
  99. return VBERROR_SIMULATED;
  100. return vbboot_retval;
  101. }
  102. VbError_t VbBootDeveloper(struct vb2_context *ctx, VbCommonParams *cparams)
  103. {
  104. shared->kernel_version_tpm = new_version;
  105. if (vbboot_retval == -2)
  106. return VBERROR_SIMULATED;
  107. return vbboot_retval;
  108. }
  109. VbError_t VbBootRecovery(struct vb2_context *ctx, VbCommonParams *cparams)
  110. {
  111. shared->kernel_version_tpm = new_version;
  112. if (vbboot_retval == -3)
  113. return VBERROR_SIMULATED;
  114. return vbboot_retval;
  115. }
  116. static void test_slk(VbError_t retval, int recovery_reason, const char *desc)
  117. {
  118. uint32_t u;
  119. TEST_EQ(VbSelectAndLoadKernel(&cparams, &kparams), retval, desc);
  120. VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
  121. TEST_EQ(u, recovery_reason, " recovery reason");
  122. }
  123. /* Tests */
  124. static void VbSlkTest(void)
  125. {
  126. ResetMocks();
  127. test_slk(0, 0, "Normal");
  128. /* Mock error early in software sync */
  129. ResetMocks();
  130. shared->flags |= VBSD_EC_SOFTWARE_SYNC;
  131. ecsync_retval = VBERROR_SIMULATED;
  132. test_slk(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
  133. VBNV_RECOVERY_EC_UNKNOWN_IMAGE, "EC sync bad");
  134. /*
  135. * If shared->flags doesn't ask for software sync, we won't notice
  136. * that error.
  137. */
  138. ResetMocks();
  139. ecsync_retval = VBERROR_SIMULATED;
  140. test_slk(0, 0, "EC sync not done");
  141. /* Same if shared->flags asks for sync, but it's overridden by GBB */
  142. ResetMocks();
  143. shared->flags |= VBSD_EC_SOFTWARE_SYNC;
  144. gbb.flags |= GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC;
  145. ecsync_retval = VBERROR_SIMULATED;
  146. test_slk(0, 0, "EC sync disabled by GBB");
  147. /* Rollback kernel version */
  148. ResetMocks();
  149. rkr_retval = 123;
  150. test_slk(VBERROR_TPM_READ_KERNEL,
  151. VBNV_RECOVERY_RW_TPM_R_ERROR, "Read kernel rollback");
  152. ResetMocks();
  153. new_version = 0x20003;
  154. test_slk(0, 0, "Roll forward");
  155. TEST_EQ(rkr_version, 0x20003, " version");
  156. ResetMocks();
  157. new_version = 0x20003;
  158. shared->flags |= VBSD_FWB_TRIED;
  159. shared->firmware_index = 1;
  160. test_slk(0, 0, "Don't roll forward during try B");
  161. TEST_EQ(rkr_version, 0x10002, " version");
  162. ResetMocks();
  163. vbboot_retval = VBERROR_INVALID_KERNEL_FOUND;
  164. VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
  165. VbNvTeardown(&vnc);
  166. shared->flags |= VBSD_FWB_TRIED;
  167. shared->firmware_index = 1;
  168. test_slk(VBERROR_INVALID_KERNEL_FOUND,
  169. 0, "Don't go to recovery if try b fails to find a kernel");
  170. ResetMocks();
  171. new_version = 0x20003;
  172. rkw_retval = 123;
  173. test_slk(VBERROR_TPM_WRITE_KERNEL,
  174. VBNV_RECOVERY_RW_TPM_W_ERROR, "Write kernel rollback");
  175. ResetMocks();
  176. rkl_retval = 123;
  177. test_slk(VBERROR_TPM_LOCK_KERNEL,
  178. VBNV_RECOVERY_RW_TPM_L_ERROR, "Lock kernel rollback");
  179. /* Boot normal */
  180. ResetMocks();
  181. vbboot_retval = -1;
  182. test_slk(VBERROR_SIMULATED, 0, "Normal boot bad");
  183. /* Boot dev */
  184. ResetMocks();
  185. shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
  186. vbboot_retval = -2;
  187. test_slk(VBERROR_SIMULATED, 0, "Dev boot bad");
  188. ResetMocks();
  189. shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
  190. new_version = 0x20003;
  191. test_slk(0, 0, "Dev doesn't roll forward");
  192. TEST_EQ(rkr_version, 0x10002, " version");
  193. /* Boot recovery */
  194. ResetMocks();
  195. shared->recovery_reason = 123;
  196. vbboot_retval = -3;
  197. test_slk(VBERROR_SIMULATED, 0, "Recovery boot bad");
  198. ResetMocks();
  199. shared->recovery_reason = 123;
  200. new_version = 0x20003;
  201. test_slk(0, 0, "Recovery doesn't roll forward");
  202. TEST_EQ(rkr_version, 0x10002, " version");
  203. ResetMocks();
  204. shared->recovery_reason = 123;
  205. rkr_retval = rkw_retval = rkl_retval = VBERROR_SIMULATED;
  206. test_slk(0, 0, "Recovery ignore TPM errors");
  207. ResetMocks();
  208. shared->recovery_reason = VBNV_RECOVERY_TRAIN_AND_REBOOT;
  209. test_slk(VBERROR_REBOOT_REQUIRED, 0, "Recovery train and reboot");
  210. // todo: rkr/w/l fail ignored if recovery
  211. }
  212. int main(void)
  213. {
  214. VbSlkTest();
  215. return gTestSuccess ? 0 : 255;
  216. }