vboot_nvstorage.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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. /* Non-volatile storage routines.
  6. */
  7. #include "sysincludes.h"
  8. #include "2crc8.h"
  9. #include "utility.h"
  10. #include "vboot_common.h"
  11. #include "vboot_nvstorage.h"
  12. /*
  13. * Constants for NV storage. We use this rather than structs and bitfields so
  14. * the data format is consistent across platforms and compilers.
  15. *
  16. * These constants must match the equivalent constants in 2lib/2nvstorage.c.
  17. * (We currently don't share a common header file because we're tring to keep
  18. * the two libs independent, and we hope to deprecate this one.)
  19. */
  20. #define HEADER_OFFSET 0
  21. #define HEADER_MASK 0xC0
  22. #define HEADER_SIGNATURE 0x40
  23. #define HEADER_FIRMWARE_SETTINGS_RESET 0x20
  24. #define HEADER_KERNEL_SETTINGS_RESET 0x10
  25. #define HEADER_WIPEOUT 0x08
  26. #define BOOT_OFFSET 1
  27. #define BOOT_DEBUG_RESET_MODE 0x80
  28. #define BOOT_DISABLE_DEV_REQUEST 0x40
  29. #define BOOT_OPROM_NEEDED 0x20
  30. #define BOOT_BACKUP_NVRAM 0x10
  31. #define BOOT_TRY_B_COUNT_MASK 0x0F
  32. #define RECOVERY_OFFSET 2
  33. #define LOCALIZATION_OFFSET 3
  34. #define DEV_FLAGS_OFFSET 4
  35. #define DEV_BOOT_USB_MASK 0x01
  36. #define DEV_BOOT_SIGNED_ONLY_MASK 0x02
  37. #define DEV_BOOT_LEGACY_MASK 0x04
  38. #define DEV_BOOT_FASTBOOT_FULL_CAP_MASK 0x08
  39. #define DEV_DEFAULT_BOOT_MASK 0x30
  40. #define DEV_DEFAULT_BOOT_SHIFT 4 /* Number of bits to shift */
  41. #define TPM_FLAGS_OFFSET 5
  42. #define TPM_CLEAR_OWNER_REQUEST 0x01
  43. #define TPM_CLEAR_OWNER_DONE 0x02
  44. #define TPM_REBOOTED 0x04
  45. #define RECOVERY_SUBCODE_OFFSET 6
  46. #define BOOT2_OFFSET 7
  47. #define BOOT2_RESULT_MASK 0x03
  48. #define BOOT2_TRIED 0x04
  49. #define BOOT2_TRY_NEXT 0x08
  50. #define BOOT2_PREV_RESULT_MASK 0x30
  51. #define BOOT2_PREV_RESULT_SHIFT 4 /* Number of bits to shift result */
  52. #define BOOT2_PREV_TRIED 0x40
  53. #define MISC_OFFSET 8
  54. #define MISC_UNLOCK_FASTBOOT 0x01
  55. #define MISC_BOOT_ON_AC_DETECT 0x02
  56. #define MISC_TRY_RO_SYNC 0x04
  57. #define MISC_BATTERY_CUTOFF_REQUEST 0x08
  58. #define KERNEL_FIELD_OFFSET 11
  59. #define CRC_OFFSET 15
  60. int VbNvSetup(VbNvContext *context)
  61. {
  62. uint8_t *raw = context->raw;
  63. /* Nothing has changed yet. */
  64. context->raw_changed = 0;
  65. context->regenerate_crc = 0;
  66. /* Check data for consistency */
  67. if ((HEADER_SIGNATURE != (raw[HEADER_OFFSET] & HEADER_MASK))
  68. || (vb2_crc8(raw, CRC_OFFSET) != raw[CRC_OFFSET])) {
  69. /* Data is inconsistent (bad CRC or header); reset defaults */
  70. memset(raw, 0, VBNV_BLOCK_SIZE);
  71. raw[HEADER_OFFSET] = (HEADER_SIGNATURE |
  72. HEADER_FIRMWARE_SETTINGS_RESET |
  73. HEADER_KERNEL_SETTINGS_RESET);
  74. /* Regenerate CRC on exit */
  75. context->regenerate_crc = 1;
  76. }
  77. return 0;
  78. }
  79. int VbNvTeardown(VbNvContext *context)
  80. {
  81. if (context->regenerate_crc) {
  82. context->raw[CRC_OFFSET] = vb2_crc8(context->raw, CRC_OFFSET);
  83. context->regenerate_crc = 0;
  84. context->raw_changed = 1;
  85. }
  86. return 0;
  87. }
  88. int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest)
  89. {
  90. const uint8_t *raw = context->raw;
  91. switch (param) {
  92. case VBNV_FIRMWARE_SETTINGS_RESET:
  93. *dest = (raw[HEADER_OFFSET] & HEADER_FIRMWARE_SETTINGS_RESET ?
  94. 1 : 0);
  95. return 0;
  96. case VBNV_KERNEL_SETTINGS_RESET:
  97. *dest = (raw[HEADER_OFFSET] & HEADER_KERNEL_SETTINGS_RESET ?
  98. 1 : 0);
  99. return 0;
  100. case VBNV_DEBUG_RESET_MODE:
  101. *dest = (raw[BOOT_OFFSET] & BOOT_DEBUG_RESET_MODE ? 1 : 0);
  102. return 0;
  103. case VBNV_TRY_B_COUNT:
  104. case VBNV_FW_TRY_COUNT:
  105. *dest = raw[BOOT_OFFSET] & BOOT_TRY_B_COUNT_MASK;
  106. return 0;
  107. case VBNV_RECOVERY_REQUEST:
  108. *dest = raw[RECOVERY_OFFSET];
  109. return 0;
  110. case VBNV_RECOVERY_SUBCODE:
  111. *dest = raw[RECOVERY_SUBCODE_OFFSET];
  112. return 0;
  113. case VBNV_LOCALIZATION_INDEX:
  114. *dest = raw[LOCALIZATION_OFFSET];
  115. return 0;
  116. case VBNV_KERNEL_FIELD:
  117. *dest = (raw[KERNEL_FIELD_OFFSET]
  118. | (raw[KERNEL_FIELD_OFFSET + 1] << 8)
  119. | (raw[KERNEL_FIELD_OFFSET + 2] << 16)
  120. | (raw[KERNEL_FIELD_OFFSET + 3] << 24));
  121. return 0;
  122. case VBNV_DEV_BOOT_USB:
  123. *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_USB_MASK ? 1 : 0);
  124. return 0;
  125. case VBNV_DEV_BOOT_LEGACY:
  126. *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_LEGACY_MASK ? 1 : 0);
  127. return 0;
  128. case VBNV_DEV_DEFAULT_BOOT:
  129. *dest = (raw[DEV_FLAGS_OFFSET] & DEV_DEFAULT_BOOT_MASK)
  130. >> DEV_DEFAULT_BOOT_SHIFT;
  131. return 0;
  132. case VBNV_DEV_BOOT_SIGNED_ONLY:
  133. *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_SIGNED_ONLY_MASK ?
  134. 1 : 0);
  135. return 0;
  136. case VBNV_DEV_BOOT_FASTBOOT_FULL_CAP:
  137. *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_FASTBOOT_FULL_CAP_MASK
  138. ? 1 : 0);
  139. return 0;
  140. case VBNV_DISABLE_DEV_REQUEST:
  141. *dest = (raw[BOOT_OFFSET] & BOOT_DISABLE_DEV_REQUEST ? 1 : 0);
  142. return 0;
  143. case VBNV_OPROM_NEEDED:
  144. *dest = (raw[BOOT_OFFSET] & BOOT_OPROM_NEEDED ? 1 : 0);
  145. return 0;
  146. case VBNV_CLEAR_TPM_OWNER_REQUEST:
  147. *dest = (raw[TPM_FLAGS_OFFSET] & TPM_CLEAR_OWNER_REQUEST ?
  148. 1 : 0);
  149. return 0;
  150. case VBNV_CLEAR_TPM_OWNER_DONE:
  151. *dest = (raw[TPM_FLAGS_OFFSET] & TPM_CLEAR_OWNER_DONE ? 1 : 0);
  152. return 0;
  153. case VBNV_TPM_REQUESTED_REBOOT:
  154. *dest = (raw[TPM_FLAGS_OFFSET] & TPM_REBOOTED ? 1 : 0);
  155. return 0;
  156. case VBNV_BACKUP_NVRAM_REQUEST:
  157. *dest = (raw[BOOT_OFFSET] & BOOT_BACKUP_NVRAM ? 1 : 0);
  158. return 0;
  159. case VBNV_FW_TRY_NEXT:
  160. *dest = (raw[BOOT2_OFFSET] & BOOT2_TRY_NEXT ? 1 : 0);
  161. return 0;
  162. case VBNV_FW_TRIED:
  163. *dest = (raw[BOOT2_OFFSET] & BOOT2_TRIED ? 1 : 0);
  164. return 0;
  165. case VBNV_FW_RESULT:
  166. *dest = raw[BOOT2_OFFSET] & BOOT2_RESULT_MASK;
  167. return 0;
  168. case VBNV_FW_PREV_TRIED:
  169. *dest = (raw[BOOT2_OFFSET] & BOOT2_PREV_TRIED ? 1 : 0);
  170. return 0;
  171. case VBNV_FW_PREV_RESULT:
  172. *dest = (raw[BOOT2_OFFSET] & BOOT2_PREV_RESULT_MASK)
  173. >> BOOT2_PREV_RESULT_SHIFT;
  174. return 0;
  175. case VBNV_FW_REQ_WIPEOUT:
  176. *dest = (raw[HEADER_OFFSET] & HEADER_WIPEOUT) ? 1 : 0;
  177. return 0;
  178. case VBNV_FASTBOOT_UNLOCK_IN_FW:
  179. *dest = (raw[MISC_OFFSET] & MISC_UNLOCK_FASTBOOT) ? 1 : 0;
  180. return 0;
  181. case VBNV_BOOT_ON_AC_DETECT:
  182. *dest = (raw[MISC_OFFSET] & MISC_BOOT_ON_AC_DETECT) ? 1 : 0;
  183. return 0;
  184. case VBNV_TRY_RO_SYNC:
  185. *dest = (raw[MISC_OFFSET] & MISC_TRY_RO_SYNC) ? 1 : 0;
  186. return 0;
  187. case VBNV_BATTERY_CUTOFF_REQUEST:
  188. *dest = (raw[MISC_OFFSET] & MISC_BATTERY_CUTOFF_REQUEST)
  189. ? 1 : 0;
  190. return 0;
  191. default:
  192. return 1;
  193. }
  194. }
  195. int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
  196. {
  197. uint8_t *raw = context->raw;
  198. uint32_t current;
  199. /* If not changing the value, don't regenerate the CRC. */
  200. if (0 == VbNvGet(context, param, &current) && current == value)
  201. return 0;
  202. switch (param) {
  203. case VBNV_FIRMWARE_SETTINGS_RESET:
  204. if (value)
  205. raw[HEADER_OFFSET] |= HEADER_FIRMWARE_SETTINGS_RESET;
  206. else
  207. raw[HEADER_OFFSET] &= ~HEADER_FIRMWARE_SETTINGS_RESET;
  208. break;
  209. case VBNV_KERNEL_SETTINGS_RESET:
  210. if (value)
  211. raw[HEADER_OFFSET] |= HEADER_KERNEL_SETTINGS_RESET;
  212. else
  213. raw[HEADER_OFFSET] &= ~HEADER_KERNEL_SETTINGS_RESET;
  214. break;
  215. case VBNV_DEBUG_RESET_MODE:
  216. if (value)
  217. raw[BOOT_OFFSET] |= BOOT_DEBUG_RESET_MODE;
  218. else
  219. raw[BOOT_OFFSET] &= ~BOOT_DEBUG_RESET_MODE;
  220. break;
  221. case VBNV_TRY_B_COUNT:
  222. case VBNV_FW_TRY_COUNT:
  223. /* Clip to valid range. */
  224. if (value > BOOT_TRY_B_COUNT_MASK)
  225. value = BOOT_TRY_B_COUNT_MASK;
  226. raw[BOOT_OFFSET] &= ~BOOT_TRY_B_COUNT_MASK;
  227. raw[BOOT_OFFSET] |= (uint8_t)value;
  228. break;
  229. case VBNV_RECOVERY_REQUEST:
  230. /*
  231. * Map values outside the valid range to the legacy reason,
  232. * since we can't determine if we're called from kernel or user
  233. * mode.
  234. */
  235. if (value > 0xFF)
  236. value = VBNV_RECOVERY_LEGACY;
  237. raw[RECOVERY_OFFSET] = (uint8_t)value;
  238. break;
  239. case VBNV_RECOVERY_SUBCODE:
  240. raw[RECOVERY_SUBCODE_OFFSET] = (uint8_t)value;
  241. break;
  242. case VBNV_LOCALIZATION_INDEX:
  243. /* Map values outside the valid range to the default index. */
  244. if (value > 0xFF)
  245. value = 0;
  246. raw[LOCALIZATION_OFFSET] = (uint8_t)value;
  247. break;
  248. case VBNV_KERNEL_FIELD:
  249. raw[KERNEL_FIELD_OFFSET] = (uint8_t)(value);
  250. raw[KERNEL_FIELD_OFFSET + 1] = (uint8_t)(value >> 8);
  251. raw[KERNEL_FIELD_OFFSET + 2] = (uint8_t)(value >> 16);
  252. raw[KERNEL_FIELD_OFFSET + 3] = (uint8_t)(value >> 24);
  253. break;
  254. case VBNV_DEV_BOOT_USB:
  255. if (value)
  256. raw[DEV_FLAGS_OFFSET] |= DEV_BOOT_USB_MASK;
  257. else
  258. raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_USB_MASK;
  259. break;
  260. case VBNV_DEV_BOOT_LEGACY:
  261. if (value)
  262. raw[DEV_FLAGS_OFFSET] |= DEV_BOOT_LEGACY_MASK;
  263. else
  264. raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_LEGACY_MASK;
  265. break;
  266. case VBNV_DEV_DEFAULT_BOOT:
  267. /* Map out of range values to boot disk */
  268. if (value > (DEV_DEFAULT_BOOT_MASK >>
  269. DEV_DEFAULT_BOOT_SHIFT))
  270. value = VBNV_DEV_DEFAULT_BOOT_DISK;
  271. raw[DEV_FLAGS_OFFSET] &= ~DEV_DEFAULT_BOOT_MASK;
  272. raw[DEV_FLAGS_OFFSET] |= (uint8_t)value <<
  273. DEV_DEFAULT_BOOT_SHIFT;
  274. break;
  275. case VBNV_DEV_BOOT_SIGNED_ONLY:
  276. if (value)
  277. raw[DEV_FLAGS_OFFSET] |= DEV_BOOT_SIGNED_ONLY_MASK;
  278. else
  279. raw[DEV_FLAGS_OFFSET] &= ~DEV_BOOT_SIGNED_ONLY_MASK;
  280. break;
  281. case VBNV_DEV_BOOT_FASTBOOT_FULL_CAP:
  282. if (value)
  283. raw[DEV_FLAGS_OFFSET] |=
  284. DEV_BOOT_FASTBOOT_FULL_CAP_MASK;
  285. else
  286. raw[DEV_FLAGS_OFFSET] &=
  287. ~DEV_BOOT_FASTBOOT_FULL_CAP_MASK;
  288. break;
  289. case VBNV_DISABLE_DEV_REQUEST:
  290. if (value)
  291. raw[BOOT_OFFSET] |= BOOT_DISABLE_DEV_REQUEST;
  292. else
  293. raw[BOOT_OFFSET] &= ~BOOT_DISABLE_DEV_REQUEST;
  294. break;
  295. case VBNV_OPROM_NEEDED:
  296. if (value)
  297. raw[BOOT_OFFSET] |= BOOT_OPROM_NEEDED;
  298. else
  299. raw[BOOT_OFFSET] &= ~BOOT_OPROM_NEEDED;
  300. break;
  301. case VBNV_CLEAR_TPM_OWNER_REQUEST:
  302. if (value)
  303. raw[TPM_FLAGS_OFFSET] |= TPM_CLEAR_OWNER_REQUEST;
  304. else
  305. raw[TPM_FLAGS_OFFSET] &= ~TPM_CLEAR_OWNER_REQUEST;
  306. break;
  307. case VBNV_CLEAR_TPM_OWNER_DONE:
  308. if (value)
  309. raw[TPM_FLAGS_OFFSET] |= TPM_CLEAR_OWNER_DONE;
  310. else
  311. raw[TPM_FLAGS_OFFSET] &= ~TPM_CLEAR_OWNER_DONE;
  312. break;
  313. case VBNV_TPM_REQUESTED_REBOOT:
  314. if (value)
  315. raw[TPM_FLAGS_OFFSET] |= TPM_REBOOTED;
  316. else
  317. raw[TPM_FLAGS_OFFSET] &= ~TPM_REBOOTED;
  318. break;
  319. case VBNV_BACKUP_NVRAM_REQUEST:
  320. if (value)
  321. raw[BOOT_OFFSET] |= BOOT_BACKUP_NVRAM;
  322. else
  323. raw[BOOT_OFFSET] &= ~BOOT_BACKUP_NVRAM;
  324. break;
  325. case VBNV_FW_TRY_NEXT:
  326. if (value)
  327. raw[BOOT2_OFFSET] |= BOOT2_TRY_NEXT;
  328. else
  329. raw[BOOT2_OFFSET] &= ~BOOT2_TRY_NEXT;
  330. break;
  331. case VBNV_FW_TRIED:
  332. if (value)
  333. raw[BOOT2_OFFSET] |= BOOT2_TRIED;
  334. else
  335. raw[BOOT2_OFFSET] &= ~BOOT2_TRIED;
  336. break;
  337. case VBNV_FW_RESULT:
  338. /* Map out of range values to unknown */
  339. if (value > BOOT2_RESULT_MASK)
  340. value = VBNV_FW_RESULT_UNKNOWN;
  341. raw[BOOT2_OFFSET] &= ~BOOT2_RESULT_MASK;
  342. raw[BOOT2_OFFSET] |= (uint8_t)value;
  343. break;
  344. case VBNV_FW_PREV_TRIED:
  345. if (value)
  346. raw[BOOT2_OFFSET] |= BOOT2_PREV_TRIED;
  347. else
  348. raw[BOOT2_OFFSET] &= ~BOOT2_PREV_TRIED;
  349. break;
  350. case VBNV_FW_PREV_RESULT:
  351. /* Map out of range values to unknown */
  352. if (value > BOOT2_RESULT_MASK)
  353. value = VBNV_FW_RESULT_UNKNOWN;
  354. raw[BOOT2_OFFSET] &= ~BOOT2_PREV_RESULT_MASK;
  355. raw[BOOT2_OFFSET] |= (uint8_t)value << BOOT2_PREV_RESULT_SHIFT;
  356. break;
  357. case VBNV_FW_REQ_WIPEOUT:
  358. if (value)
  359. raw[HEADER_OFFSET] |= HEADER_WIPEOUT;
  360. else
  361. raw[HEADER_OFFSET] &= ~HEADER_WIPEOUT;
  362. break;
  363. case VBNV_FASTBOOT_UNLOCK_IN_FW:
  364. if (value)
  365. raw[MISC_OFFSET] |= MISC_UNLOCK_FASTBOOT;
  366. else
  367. raw[MISC_OFFSET] &= ~MISC_UNLOCK_FASTBOOT;
  368. break;
  369. case VBNV_BOOT_ON_AC_DETECT:
  370. if (value)
  371. raw[MISC_OFFSET] |= MISC_BOOT_ON_AC_DETECT;
  372. else
  373. raw[MISC_OFFSET] &= ~MISC_BOOT_ON_AC_DETECT;
  374. break;
  375. case VBNV_TRY_RO_SYNC:
  376. if (value)
  377. raw[MISC_OFFSET] |= MISC_TRY_RO_SYNC;
  378. else
  379. raw[MISC_OFFSET] &= ~MISC_TRY_RO_SYNC;
  380. break;
  381. case VBNV_BATTERY_CUTOFF_REQUEST:
  382. if (value)
  383. raw[MISC_OFFSET] |= MISC_BATTERY_CUTOFF_REQUEST;
  384. else
  385. raw[MISC_OFFSET] &= ~MISC_BATTERY_CUTOFF_REQUEST;
  386. break;
  387. default:
  388. return 1;
  389. }
  390. /* Need to regenerate CRC, since the value changed. */
  391. context->regenerate_crc = 1;
  392. return 0;
  393. }