hab.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
  4. */
  5. #include <common.h>
  6. #include <command.h>
  7. #include <config.h>
  8. #include <fuse.h>
  9. #include <mapmem.h>
  10. #include <image.h>
  11. #include <asm/io.h>
  12. #include <asm/global_data.h>
  13. #include <asm/system.h>
  14. #include <asm/arch/clock.h>
  15. #include <asm/arch/sys_proto.h>
  16. #include <asm/mach-imx/hab.h>
  17. #include <linux/arm-smccc.h>
  18. DECLARE_GLOBAL_DATA_PTR;
  19. #define ALIGN_SIZE 0x1000
  20. #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
  21. #define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0
  22. #define MX6SL_PU_IROM_MMU_EN_VAR 0x00901c60
  23. #define IS_HAB_ENABLED_BIT \
  24. (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \
  25. ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2))
  26. #ifdef CONFIG_MX7ULP
  27. #define HAB_M4_PERSISTENT_START ((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \
  28. 0x20008180)
  29. #define HAB_M4_PERSISTENT_BYTES 0xB80
  30. #endif
  31. static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
  32. {
  33. printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str,
  34. ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version);
  35. return 1;
  36. }
  37. static int verify_ivt_header(struct ivt_header *ivt_hdr)
  38. {
  39. int result = 0;
  40. if (ivt_hdr->magic != IVT_HEADER_MAGIC)
  41. result = ivt_header_error("bad magic", ivt_hdr);
  42. if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
  43. result = ivt_header_error("bad length", ivt_hdr);
  44. if ((ivt_hdr->version & HAB_MAJ_MASK) != HAB_MAJ_VER)
  45. result = ivt_header_error("bad version", ivt_hdr);
  46. return result;
  47. }
  48. #ifdef CONFIG_ARM64
  49. #define FSL_SIP_HAB 0xC2000007
  50. #define FSL_SIP_HAB_AUTHENTICATE 0x00
  51. #define FSL_SIP_HAB_ENTRY 0x01
  52. #define FSL_SIP_HAB_EXIT 0x02
  53. #define FSL_SIP_HAB_REPORT_EVENT 0x03
  54. #define FSL_SIP_HAB_REPORT_STATUS 0x04
  55. #define FSL_SIP_HAB_FAILSAFE 0x05
  56. #define FSL_SIP_HAB_CHECK_TARGET 0x06
  57. static volatile gd_t *gd_save;
  58. #endif
  59. static inline void save_gd(void)
  60. {
  61. #ifdef CONFIG_ARM64
  62. gd_save = gd;
  63. #endif
  64. }
  65. static inline void restore_gd(void)
  66. {
  67. #ifdef CONFIG_ARM64
  68. /*
  69. * Make will already error that reserving x18 is not supported at the
  70. * time of writing, clang: error: unknown argument: '-ffixed-x18'
  71. */
  72. __asm__ volatile("mov x18, %0\n" : : "r" (gd_save));
  73. #endif
  74. }
  75. enum hab_status hab_rvt_report_event(enum hab_status status, u32 index,
  76. u8 *event, size_t *bytes)
  77. {
  78. enum hab_status ret;
  79. hab_rvt_report_event_t *hab_rvt_report_event_func;
  80. struct arm_smccc_res res __maybe_unused;
  81. hab_rvt_report_event_func = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
  82. #if defined(CONFIG_ARM64)
  83. if (current_el() != 3) {
  84. /* call sip */
  85. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index,
  86. (unsigned long)event, (unsigned long)bytes, 0, 0, 0, &res);
  87. return (enum hab_status)res.a0;
  88. }
  89. #endif
  90. save_gd();
  91. ret = hab_rvt_report_event_func(status, index, event, bytes);
  92. restore_gd();
  93. return ret;
  94. }
  95. enum hab_status hab_rvt_report_status(enum hab_config *config, enum hab_state *state)
  96. {
  97. enum hab_status ret;
  98. hab_rvt_report_status_t *hab_rvt_report_status_func;
  99. struct arm_smccc_res res __maybe_unused;
  100. hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
  101. #if defined(CONFIG_ARM64)
  102. if (current_el() != 3) {
  103. /* call sip */
  104. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, (unsigned long)config,
  105. (unsigned long)state, 0, 0, 0, 0, &res);
  106. return (enum hab_status)res.a0;
  107. }
  108. #endif
  109. save_gd();
  110. ret = hab_rvt_report_status_func(config, state);
  111. restore_gd();
  112. return ret;
  113. }
  114. enum hab_status hab_rvt_entry(void)
  115. {
  116. enum hab_status ret;
  117. hab_rvt_entry_t *hab_rvt_entry_func;
  118. struct arm_smccc_res res __maybe_unused;
  119. hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
  120. #if defined(CONFIG_ARM64)
  121. if (current_el() != 3) {
  122. /* call sip */
  123. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0, 0, 0, 0, &res);
  124. return (enum hab_status)res.a0;
  125. }
  126. #endif
  127. save_gd();
  128. ret = hab_rvt_entry_func();
  129. restore_gd();
  130. return ret;
  131. }
  132. enum hab_status hab_rvt_exit(void)
  133. {
  134. enum hab_status ret;
  135. hab_rvt_exit_t *hab_rvt_exit_func;
  136. struct arm_smccc_res res __maybe_unused;
  137. hab_rvt_exit_func = (hab_rvt_exit_t *)HAB_RVT_EXIT;
  138. #if defined(CONFIG_ARM64)
  139. if (current_el() != 3) {
  140. /* call sip */
  141. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0, 0, 0, 0, &res);
  142. return (enum hab_status)res.a0;
  143. }
  144. #endif
  145. save_gd();
  146. ret = hab_rvt_exit_func();
  147. restore_gd();
  148. return ret;
  149. }
  150. void hab_rvt_failsafe(void)
  151. {
  152. hab_rvt_failsafe_t *hab_rvt_failsafe_func;
  153. hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE;
  154. #if defined(CONFIG_ARM64)
  155. if (current_el() != 3) {
  156. /* call sip */
  157. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0, 0, 0, 0, NULL);
  158. return;
  159. }
  160. #endif
  161. save_gd();
  162. hab_rvt_failsafe_func();
  163. restore_gd();
  164. }
  165. enum hab_status hab_rvt_check_target(enum hab_target type, const void *start,
  166. size_t bytes)
  167. {
  168. enum hab_status ret;
  169. hab_rvt_check_target_t *hab_rvt_check_target_func;
  170. struct arm_smccc_res res __maybe_unused;
  171. hab_rvt_check_target_func = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
  172. #if defined(CONFIG_ARM64)
  173. if (current_el() != 3) {
  174. /* call sip */
  175. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type,
  176. (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
  177. return (enum hab_status)res.a0;
  178. }
  179. #endif
  180. save_gd();
  181. ret = hab_rvt_check_target_func(type, start, bytes);
  182. restore_gd();
  183. return ret;
  184. }
  185. void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset,
  186. void **start, size_t *bytes, hab_loader_callback_f_t loader)
  187. {
  188. void *ret;
  189. hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func;
  190. struct arm_smccc_res res __maybe_unused;
  191. hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
  192. #if defined(CONFIG_ARM64)
  193. if (current_el() != 3) {
  194. /* call sip */
  195. arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset,
  196. (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res);
  197. return (void *)res.a0;
  198. }
  199. #endif
  200. save_gd();
  201. ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start, bytes, loader);
  202. restore_gd();
  203. return ret;
  204. }
  205. #if !defined(CONFIG_SPL_BUILD)
  206. #define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */
  207. struct record {
  208. uint8_t tag; /* Tag */
  209. uint8_t len[2]; /* Length */
  210. uint8_t par; /* Version */
  211. uint8_t contents[MAX_RECORD_BYTES];/* Record Data */
  212. bool any_rec_flag;
  213. };
  214. static char *rsn_str[] = {
  215. "RSN = HAB_RSN_ANY (0x00)\n",
  216. "RSN = HAB_ENG_FAIL (0x30)\n",
  217. "RSN = HAB_INV_ADDRESS (0x22)\n",
  218. "RSN = HAB_INV_ASSERTION (0x0C)\n",
  219. "RSN = HAB_INV_CALL (0x28)\n",
  220. "RSN = HAB_INV_CERTIFICATE (0x21)\n",
  221. "RSN = HAB_INV_COMMAND (0x06)\n",
  222. "RSN = HAB_INV_CSF (0x11)\n",
  223. "RSN = HAB_INV_DCD (0x27)\n",
  224. "RSN = HAB_INV_INDEX (0x0F)\n",
  225. "RSN = HAB_INV_IVT (0x05)\n",
  226. "RSN = HAB_INV_KEY (0x1D)\n",
  227. "RSN = HAB_INV_RETURN (0x1E)\n",
  228. "RSN = HAB_INV_SIGNATURE (0x18)\n",
  229. "RSN = HAB_INV_SIZE (0x17)\n",
  230. "RSN = HAB_MEM_FAIL (0x2E)\n",
  231. "RSN = HAB_OVR_COUNT (0x2B)\n",
  232. "RSN = HAB_OVR_STORAGE (0x2D)\n",
  233. "RSN = HAB_UNS_ALGORITHM (0x12)\n",
  234. "RSN = HAB_UNS_COMMAND (0x03)\n",
  235. "RSN = HAB_UNS_ENGINE (0x0A)\n",
  236. "RSN = HAB_UNS_ITEM (0x24)\n",
  237. "RSN = HAB_UNS_KEY (0x1B)\n",
  238. "RSN = HAB_UNS_PROTOCOL (0x14)\n",
  239. "RSN = HAB_UNS_STATE (0x09)\n",
  240. "RSN = INVALID\n",
  241. NULL
  242. };
  243. static char *sts_str[] = {
  244. "STS = HAB_SUCCESS (0xF0)\n",
  245. "STS = HAB_FAILURE (0x33)\n",
  246. "STS = HAB_WARNING (0x69)\n",
  247. "STS = INVALID\n",
  248. NULL
  249. };
  250. static char *eng_str[] = {
  251. "ENG = HAB_ENG_ANY (0x00)\n",
  252. "ENG = HAB_ENG_SCC (0x03)\n",
  253. "ENG = HAB_ENG_RTIC (0x05)\n",
  254. "ENG = HAB_ENG_SAHARA (0x06)\n",
  255. "ENG = HAB_ENG_CSU (0x0A)\n",
  256. "ENG = HAB_ENG_SRTC (0x0C)\n",
  257. "ENG = HAB_ENG_DCP (0x1B)\n",
  258. "ENG = HAB_ENG_CAAM (0x1D)\n",
  259. "ENG = HAB_ENG_SNVS (0x1E)\n",
  260. "ENG = HAB_ENG_OCOTP (0x21)\n",
  261. "ENG = HAB_ENG_DTCP (0x22)\n",
  262. "ENG = HAB_ENG_ROM (0x36)\n",
  263. "ENG = HAB_ENG_HDCP (0x24)\n",
  264. "ENG = HAB_ENG_RTL (0x77)\n",
  265. "ENG = HAB_ENG_SW (0xFF)\n",
  266. "ENG = INVALID\n",
  267. NULL
  268. };
  269. static char *ctx_str[] = {
  270. "CTX = HAB_CTX_ANY(0x00)\n",
  271. "CTX = HAB_CTX_FAB (0xFF)\n",
  272. "CTX = HAB_CTX_ENTRY (0xE1)\n",
  273. "CTX = HAB_CTX_TARGET (0x33)\n",
  274. "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
  275. "CTX = HAB_CTX_DCD (0xDD)\n",
  276. "CTX = HAB_CTX_CSF (0xCF)\n",
  277. "CTX = HAB_CTX_COMMAND (0xC0)\n",
  278. "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
  279. "CTX = HAB_CTX_ASSERT (0xA0)\n",
  280. "CTX = HAB_CTX_EXIT (0xEE)\n",
  281. "CTX = INVALID\n",
  282. NULL
  283. };
  284. static uint8_t hab_statuses[5] = {
  285. HAB_STS_ANY,
  286. HAB_FAILURE,
  287. HAB_WARNING,
  288. HAB_SUCCESS,
  289. -1
  290. };
  291. static uint8_t hab_reasons[26] = {
  292. HAB_RSN_ANY,
  293. HAB_ENG_FAIL,
  294. HAB_INV_ADDRESS,
  295. HAB_INV_ASSERTION,
  296. HAB_INV_CALL,
  297. HAB_INV_CERTIFICATE,
  298. HAB_INV_COMMAND,
  299. HAB_INV_CSF,
  300. HAB_INV_DCD,
  301. HAB_INV_INDEX,
  302. HAB_INV_IVT,
  303. HAB_INV_KEY,
  304. HAB_INV_RETURN,
  305. HAB_INV_SIGNATURE,
  306. HAB_INV_SIZE,
  307. HAB_MEM_FAIL,
  308. HAB_OVR_COUNT,
  309. HAB_OVR_STORAGE,
  310. HAB_UNS_ALGORITHM,
  311. HAB_UNS_COMMAND,
  312. HAB_UNS_ENGINE,
  313. HAB_UNS_ITEM,
  314. HAB_UNS_KEY,
  315. HAB_UNS_PROTOCOL,
  316. HAB_UNS_STATE,
  317. -1
  318. };
  319. static uint8_t hab_contexts[12] = {
  320. HAB_CTX_ANY,
  321. HAB_CTX_FAB,
  322. HAB_CTX_ENTRY,
  323. HAB_CTX_TARGET,
  324. HAB_CTX_AUTHENTICATE,
  325. HAB_CTX_DCD,
  326. HAB_CTX_CSF,
  327. HAB_CTX_COMMAND,
  328. HAB_CTX_AUT_DAT,
  329. HAB_CTX_ASSERT,
  330. HAB_CTX_EXIT,
  331. -1
  332. };
  333. static uint8_t hab_engines[16] = {
  334. HAB_ENG_ANY,
  335. HAB_ENG_SCC,
  336. HAB_ENG_RTIC,
  337. HAB_ENG_SAHARA,
  338. HAB_ENG_CSU,
  339. HAB_ENG_SRTC,
  340. HAB_ENG_DCP,
  341. HAB_ENG_CAAM,
  342. HAB_ENG_SNVS,
  343. HAB_ENG_OCOTP,
  344. HAB_ENG_DTCP,
  345. HAB_ENG_ROM,
  346. HAB_ENG_HDCP,
  347. HAB_ENG_RTL,
  348. HAB_ENG_SW,
  349. -1
  350. };
  351. static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
  352. {
  353. uint8_t idx = 0;
  354. uint8_t element = list[idx];
  355. while (element != -1) {
  356. if (element == tgt)
  357. return idx;
  358. element = list[++idx];
  359. }
  360. return -1;
  361. }
  362. static void process_event_record(uint8_t *event_data, size_t bytes)
  363. {
  364. struct record *rec = (struct record *)event_data;
  365. printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
  366. printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
  367. printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
  368. printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
  369. }
  370. static void display_event(uint8_t *event_data, size_t bytes)
  371. {
  372. uint32_t i;
  373. if (!(event_data && bytes > 0))
  374. return;
  375. for (i = 0; i < bytes; i++) {
  376. if (i == 0)
  377. printf("\t0x%02x", event_data[i]);
  378. else if ((i % 8) == 0)
  379. printf("\n\t0x%02x", event_data[i]);
  380. else
  381. printf(" 0x%02x", event_data[i]);
  382. }
  383. process_event_record(event_data, bytes);
  384. }
  385. static int get_hab_status(void)
  386. {
  387. uint32_t index = 0; /* Loop index */
  388. uint8_t event_data[128]; /* Event data buffer */
  389. size_t bytes = sizeof(event_data); /* Event size in bytes */
  390. enum hab_config config = 0;
  391. enum hab_state state = 0;
  392. if (imx_hab_is_enabled())
  393. puts("\nSecure boot enabled\n");
  394. else
  395. puts("\nSecure boot disabled\n");
  396. /* Check HAB status */
  397. if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
  398. printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
  399. config, state);
  400. /* Display HAB events */
  401. while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
  402. &bytes) == HAB_SUCCESS) {
  403. puts("\n");
  404. printf("--------- HAB Event %d -----------------\n",
  405. index + 1);
  406. puts("event data:\n");
  407. display_event(event_data, bytes);
  408. puts("\n");
  409. bytes = sizeof(event_data);
  410. index++;
  411. }
  412. }
  413. /* Display message if no HAB events are found */
  414. else {
  415. printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
  416. config, state);
  417. puts("No HAB Events Found!\n\n");
  418. }
  419. return 0;
  420. }
  421. #ifdef CONFIG_MX7ULP
  422. static int get_record_len(struct record *rec)
  423. {
  424. return (size_t)((rec->len[0] << 8) + (rec->len[1]));
  425. }
  426. static int get_hab_status_m4(void)
  427. {
  428. unsigned int index = 0;
  429. uint8_t event_data[128];
  430. size_t record_len, offset = 0;
  431. enum hab_config config = 0;
  432. enum hab_state state = 0;
  433. if (imx_hab_is_enabled())
  434. puts("\nSecure boot enabled\n");
  435. else
  436. puts("\nSecure boot disabled\n");
  437. /*
  438. * HAB in both A7 and M4 gather the security state
  439. * and configuration of the chip from
  440. * shared SNVS module
  441. */
  442. hab_rvt_report_status(&config, &state);
  443. printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
  444. config, state);
  445. struct record *rec = (struct record *)(HAB_M4_PERSISTENT_START);
  446. record_len = get_record_len(rec);
  447. /* Check if HAB persistent memory is valid */
  448. if (rec->tag != HAB_TAG_EVT_DEF ||
  449. record_len != sizeof(struct evt_def) ||
  450. (rec->par & HAB_MAJ_MASK) != HAB_MAJ_VER) {
  451. puts("\nERROR: Invalid HAB persistent memory\n");
  452. return 1;
  453. }
  454. /* Parse events in HAB M4 persistent memory region */
  455. while (offset < HAB_M4_PERSISTENT_BYTES) {
  456. rec = (struct record *)(HAB_M4_PERSISTENT_START + offset);
  457. record_len = get_record_len(rec);
  458. if (rec->tag == HAB_TAG_EVT) {
  459. memcpy(&event_data, rec, record_len);
  460. puts("\n");
  461. printf("--------- HAB Event %d -----------------\n",
  462. index + 1);
  463. puts("event data:\n");
  464. display_event(event_data, record_len);
  465. puts("\n");
  466. index++;
  467. }
  468. offset += record_len;
  469. /* Ensure all records start on a word boundary */
  470. if ((offset % 4) != 0)
  471. offset = offset + (4 - (offset % 4));
  472. }
  473. if (!index)
  474. puts("No HAB Events Found!\n\n");
  475. return 0;
  476. }
  477. #endif
  478. static int do_hab_status(struct cmd_tbl *cmdtp, int flag, int argc,
  479. char *const argv[])
  480. {
  481. #ifdef CONFIG_MX7ULP
  482. if ((argc > 2)) {
  483. cmd_usage(cmdtp);
  484. return 1;
  485. }
  486. if (strcmp("m4", argv[1]) == 0)
  487. get_hab_status_m4();
  488. else
  489. get_hab_status();
  490. #else
  491. if ((argc != 1)) {
  492. cmd_usage(cmdtp);
  493. return 1;
  494. }
  495. get_hab_status();
  496. #endif
  497. return 0;
  498. }
  499. static ulong get_image_ivt_offset(ulong img_addr)
  500. {
  501. const void *buf;
  502. buf = map_sysmem(img_addr, 0);
  503. switch (genimg_get_format(buf)) {
  504. #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
  505. case IMAGE_FORMAT_LEGACY:
  506. return (image_get_image_size((image_header_t *)img_addr)
  507. + 0x1000 - 1) & ~(0x1000 - 1);
  508. #endif
  509. #if IMAGE_ENABLE_FIT
  510. case IMAGE_FORMAT_FIT:
  511. return (fit_get_size(buf) + 0x1000 - 1) & ~(0x1000 - 1);
  512. #endif
  513. default:
  514. return 0;
  515. }
  516. }
  517. static int do_authenticate_image(struct cmd_tbl *cmdtp, int flag, int argc,
  518. char *const argv[])
  519. {
  520. ulong addr, length, ivt_offset;
  521. int rcode = 0;
  522. if (argc < 3)
  523. return CMD_RET_USAGE;
  524. addr = hextoul(argv[1], NULL);
  525. length = hextoul(argv[2], NULL);
  526. if (argc == 3)
  527. ivt_offset = get_image_ivt_offset(addr);
  528. else
  529. ivt_offset = hextoul(argv[3], NULL);
  530. rcode = imx_hab_authenticate_image(addr, length, ivt_offset);
  531. if (rcode == 0)
  532. rcode = CMD_RET_SUCCESS;
  533. else
  534. rcode = CMD_RET_FAILURE;
  535. return rcode;
  536. }
  537. static int do_hab_failsafe(struct cmd_tbl *cmdtp, int flag, int argc,
  538. char *const argv[])
  539. {
  540. if (argc != 1) {
  541. cmd_usage(cmdtp);
  542. return 1;
  543. }
  544. hab_rvt_failsafe();
  545. return 0;
  546. }
  547. static int do_hab_version(struct cmd_tbl *cmdtp, int flag, int argc,
  548. char *const argv[])
  549. {
  550. struct hab_hdr *hdr = (struct hab_hdr *)HAB_RVT_BASE;
  551. if (hdr->tag != HAB_TAG_RVT) {
  552. printf("Unexpected header tag: %x\n", hdr->tag);
  553. return CMD_RET_FAILURE;
  554. }
  555. printf("HAB version: %d.%d\n", hdr->par >> 4, hdr->par & 0xf);
  556. return 0;
  557. }
  558. static int do_authenticate_image_or_failover(struct cmd_tbl *cmdtp, int flag,
  559. int argc, char *const argv[])
  560. {
  561. int ret = CMD_RET_FAILURE;
  562. if (argc != 4) {
  563. ret = CMD_RET_USAGE;
  564. goto error;
  565. }
  566. if (!imx_hab_is_enabled()) {
  567. printf("error: secure boot disabled\n");
  568. goto error;
  569. }
  570. if (do_authenticate_image(NULL, flag, argc, argv) != CMD_RET_SUCCESS) {
  571. fprintf(stderr, "authentication fail -> %s %s %s %s\n",
  572. argv[0], argv[1], argv[2], argv[3]);
  573. do_hab_failsafe(0, 0, 1, NULL);
  574. };
  575. ret = CMD_RET_SUCCESS;
  576. error:
  577. return ret;
  578. }
  579. #ifdef CONFIG_MX7ULP
  580. U_BOOT_CMD(
  581. hab_status, CONFIG_SYS_MAXARGS, 2, do_hab_status,
  582. "display HAB status and events",
  583. "hab_status - A7 HAB event and status\n"
  584. "hab_status m4 - M4 HAB event and status"
  585. );
  586. #else
  587. U_BOOT_CMD(
  588. hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
  589. "display HAB status",
  590. ""
  591. );
  592. #endif
  593. U_BOOT_CMD(
  594. hab_auth_img, 4, 0, do_authenticate_image,
  595. "authenticate image via HAB",
  596. "addr length ivt_offset\n"
  597. "addr - image hex address\n"
  598. "length - image hex length\n"
  599. "ivt_offset - hex offset of IVT in the image"
  600. );
  601. U_BOOT_CMD(
  602. hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
  603. "run BootROM failsafe routine",
  604. ""
  605. );
  606. U_BOOT_CMD(
  607. hab_auth_img_or_fail, 4, 0,
  608. do_authenticate_image_or_failover,
  609. "authenticate image via HAB on failure drop to USB BootROM mode",
  610. "addr length ivt_offset\n"
  611. "addr - image hex address\n"
  612. "length - image hex length\n"
  613. "ivt_offset - hex offset of IVT in the image"
  614. );
  615. U_BOOT_CMD(
  616. hab_version, 1, 0, do_hab_version,
  617. "print HAB major/minor version",
  618. ""
  619. );
  620. #endif /* !defined(CONFIG_SPL_BUILD) */
  621. /* Get CSF Header length */
  622. static int get_hab_hdr_len(struct hab_hdr *hdr)
  623. {
  624. return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
  625. }
  626. /* Check whether addr lies between start and
  627. * end and is within the length of the image
  628. */
  629. static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
  630. {
  631. size_t csf_size = (size_t)((end + 1) - addr);
  632. return (addr && (addr >= start) && (addr <= end) &&
  633. (csf_size >= bytes));
  634. }
  635. /* Get Length of each command in CSF */
  636. static int get_csf_cmd_hdr_len(u8 *csf_hdr)
  637. {
  638. if (*csf_hdr == HAB_CMD_HDR)
  639. return sizeof(struct hab_hdr);
  640. return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
  641. }
  642. /* Check if CSF is valid */
  643. static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes)
  644. {
  645. u8 *start = (u8 *)start_addr;
  646. u8 *csf_hdr;
  647. u8 *end;
  648. size_t csf_hdr_len;
  649. size_t cmd_hdr_len;
  650. size_t offset = 0;
  651. if (bytes != 0)
  652. end = start + bytes - 1;
  653. else
  654. end = start;
  655. /* Verify if CSF pointer content is zero */
  656. if (!ivt->csf) {
  657. puts("Error: CSF pointer is NULL\n");
  658. return false;
  659. }
  660. csf_hdr = (u8 *)(ulong)ivt->csf;
  661. /* Verify if CSF Header exist */
  662. if (*csf_hdr != HAB_CMD_HDR) {
  663. puts("Error: CSF header command not found\n");
  664. return false;
  665. }
  666. csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
  667. /* Check if the CSF lies within the image bounds */
  668. if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
  669. puts("Error: CSF lies outside the image bounds\n");
  670. return false;
  671. }
  672. do {
  673. struct hab_hdr *cmd;
  674. cmd = (struct hab_hdr *)&csf_hdr[offset];
  675. switch (cmd->tag) {
  676. case (HAB_CMD_WRT_DAT):
  677. puts("Error: Deprecated write command found\n");
  678. return false;
  679. case (HAB_CMD_CHK_DAT):
  680. puts("Error: Deprecated check command found\n");
  681. return false;
  682. case (HAB_CMD_SET):
  683. if (cmd->par == HAB_PAR_MID) {
  684. puts("Error: Deprecated Set MID command found\n");
  685. return false;
  686. }
  687. default:
  688. break;
  689. }
  690. cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
  691. if (!cmd_hdr_len) {
  692. puts("Error: Invalid command length\n");
  693. return false;
  694. }
  695. offset += cmd_hdr_len;
  696. } while (offset < csf_hdr_len);
  697. return true;
  698. }
  699. /*
  700. * Validate IVT structure of the image being authenticated
  701. */
  702. static int validate_ivt(struct ivt *ivt_initial)
  703. {
  704. struct ivt_header *ivt_hdr = &ivt_initial->hdr;
  705. if ((ulong)ivt_initial & 0x3) {
  706. puts("Error: Image's start address is not 4 byte aligned\n");
  707. return 0;
  708. }
  709. /* Check IVT fields before allowing authentication */
  710. if ((!verify_ivt_header(ivt_hdr)) && \
  711. (ivt_initial->entry != 0x0) && \
  712. (ivt_initial->reserved1 == 0x0) && \
  713. (ivt_initial->self == \
  714. (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \
  715. (ivt_initial->csf != 0x0) && \
  716. (ivt_initial->reserved2 == 0x0)) {
  717. /* Report boot failure if DCD pointer is found in IVT */
  718. if (ivt_initial->dcd != 0x0)
  719. puts("Error: DCD pointer must be 0\n");
  720. else
  721. return 1;
  722. }
  723. puts("Error: Invalid IVT structure\n");
  724. debug("\nAllowed IVT structure:\n");
  725. debug("IVT HDR = 0x4X2000D1\n");
  726. debug("IVT ENTRY = 0xXXXXXXXX\n");
  727. debug("IVT RSV1 = 0x0\n");
  728. debug("IVT DCD = 0x0\n"); /* Recommended */
  729. debug("IVT BOOT_DATA = 0xXXXXXXXX\n"); /* Commonly 0x0 */
  730. debug("IVT SELF = 0xXXXXXXXX\n"); /* = ddr_start + ivt_offset */
  731. debug("IVT CSF = 0xXXXXXXXX\n");
  732. debug("IVT RSV2 = 0x0\n");
  733. /* Invalid IVT structure */
  734. return 0;
  735. }
  736. bool imx_hab_is_enabled(void)
  737. {
  738. struct imx_sec_config_fuse_t *fuse =
  739. (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
  740. uint32_t reg;
  741. int ret;
  742. ret = fuse_read(fuse->bank, fuse->word, &reg);
  743. if (ret) {
  744. puts("\nSecure boot fuse read error\n");
  745. return ret;
  746. }
  747. return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
  748. }
  749. int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size,
  750. uint32_t ivt_offset)
  751. {
  752. ulong load_addr = 0;
  753. size_t bytes;
  754. ulong ivt_addr = 0;
  755. int result = 1;
  756. ulong start;
  757. struct ivt *ivt;
  758. enum hab_status status;
  759. if (!imx_hab_is_enabled())
  760. puts("hab fuse not enabled\n");
  761. printf("\nAuthenticate image from DDR location 0x%x...\n",
  762. ddr_start);
  763. hab_caam_clock_enable(1);
  764. /* Calculate IVT address header */
  765. ivt_addr = (ulong) (ddr_start + ivt_offset);
  766. ivt = (struct ivt *)ivt_addr;
  767. /* Verify IVT header bugging out on error */
  768. if (!validate_ivt(ivt))
  769. goto hab_authentication_exit;
  770. start = ddr_start;
  771. bytes = image_size;
  772. /* Verify CSF */
  773. if (!csf_is_valid(ivt, start, bytes))
  774. goto hab_authentication_exit;
  775. if (hab_rvt_entry() != HAB_SUCCESS) {
  776. puts("hab entry function fail\n");
  777. goto hab_exit_failure_print_status;
  778. }
  779. status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes);
  780. if (status != HAB_SUCCESS) {
  781. printf("HAB check target 0x%08x-0x%08lx fail\n",
  782. ddr_start, ddr_start + (ulong)bytes);
  783. goto hab_exit_failure_print_status;
  784. }
  785. #ifdef DEBUG
  786. printf("\nivt_offset = 0x%x, ivt addr = 0x%lx\n", ivt_offset, ivt_addr);
  787. printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry,
  788. ivt->dcd, ivt->csf);
  789. puts("Dumping IVT\n");
  790. print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0);
  791. puts("Dumping CSF Header\n");
  792. print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0);
  793. #if !defined(CONFIG_SPL_BUILD)
  794. get_hab_status();
  795. #endif
  796. puts("\nCalling authenticate_image in ROM\n");
  797. printf("\tivt_offset = 0x%x\n", ivt_offset);
  798. printf("\tstart = 0x%08lx\n", start);
  799. printf("\tbytes = 0x%x\n", bytes);
  800. #endif
  801. #ifndef CONFIG_ARM64
  802. /*
  803. * If the MMU is enabled, we have to notify the ROM
  804. * code, or it won't flush the caches when needed.
  805. * This is done, by setting the "pu_irom_mmu_enabled"
  806. * word to 1. You can find its address by looking in
  807. * the ROM map. This is critical for
  808. * authenticate_image(). If MMU is enabled, without
  809. * setting this bit, authentication will fail and may
  810. * crash.
  811. */
  812. /* Check MMU enabled */
  813. if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
  814. if (is_mx6dq()) {
  815. /*
  816. * This won't work on Rev 1.0.0 of
  817. * i.MX6Q/D, since their ROM doesn't
  818. * do cache flushes. don't think any
  819. * exist, so we ignore them.
  820. */
  821. if (!is_mx6dqp())
  822. writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
  823. } else if (is_mx6sdl()) {
  824. writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
  825. } else if (is_mx6sl()) {
  826. writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
  827. }
  828. }
  829. #endif
  830. load_addr = (ulong)hab_rvt_authenticate_image(
  831. HAB_CID_UBOOT,
  832. ivt_offset, (void **)&start,
  833. (size_t *)&bytes, NULL);
  834. if (hab_rvt_exit() != HAB_SUCCESS) {
  835. puts("hab exit function fail\n");
  836. load_addr = 0;
  837. }
  838. hab_exit_failure_print_status:
  839. #if !defined(CONFIG_SPL_BUILD)
  840. get_hab_status();
  841. #endif
  842. hab_authentication_exit:
  843. if (load_addr != 0 || !imx_hab_is_enabled())
  844. result = 0;
  845. return result;
  846. }
  847. int authenticate_image(u32 ddr_start, u32 raw_image_size)
  848. {
  849. u32 ivt_offset;
  850. size_t bytes;
  851. ivt_offset = (raw_image_size + ALIGN_SIZE - 1) &
  852. ~(ALIGN_SIZE - 1);
  853. bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
  854. return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset);
  855. }