tlcl_generator.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /* Copyright (c) 2012 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. /* This program generates partially filled TPM datagrams and other compile-time
  6. * constants (e.g. structure sizes and offsets). Compile this file---and ONLY
  7. * this file---with -fpack-struct. We take advantage of the fact that the
  8. * (packed) TPM structures layout (mostly) match the TPM request and response
  9. * datagram layout. When they don't completely match, some fixing is necessary
  10. * (see PCR_SELECTION_FIX below).
  11. */
  12. #include <assert.h>
  13. #include <stddef.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include "sysincludes.h"
  17. #include "tlcl_internal.h"
  18. #include "tpmextras.h"
  19. #include "tss_constants.h"
  20. /* See struct Command below. This structure represent a field in a TPM
  21. * command. [name] is the field name. [visible] is 1 if the field is
  22. * modified by the run-time. Non-visible fields are initialized at build time
  23. * and remain constant. [size] is the field size in bytes. [value] is the
  24. * fixed value of non-visible fields.
  25. */
  26. typedef struct Field {
  27. const char* name;
  28. int visible;
  29. int offset;
  30. int size;
  31. uint32_t value; /* large enough for all initializers */
  32. struct Field* next;
  33. } Field;
  34. /* This structure is used to build (at build time) and manipulate (at firmware
  35. * or emulation run time) buffers containing TPM datagrams. [name] is the name
  36. * of a TPM command. [size] is the size of the command buffer in bytes, when
  37. * known. [max_size] is the maximum size allowed for variable-length commands
  38. * (such as Read and Write). [fields] is a link-list of command fields.
  39. */
  40. typedef struct Command {
  41. const char* name;
  42. int size;
  43. int max_size;
  44. Field* fields;
  45. struct Command* next;
  46. } Command;
  47. /* Adds a field to a command, and makes its offset visible. The fields must be
  48. * added at increasing offsets.
  49. */
  50. static void AddVisibleField(Command* cmd, const char* name, int offset) {
  51. Field* fld = (Field*) calloc(1, sizeof(Field));
  52. if (cmd->fields != NULL) {
  53. assert(offset > fn->offset);
  54. }
  55. fld->next = cmd->fields;
  56. cmd->fields = fld;
  57. fld->name = name;
  58. fld->visible = 1;
  59. fld->offset = offset;
  60. }
  61. /* Adds a constant field with its value. The fields must be added at
  62. * increasing offsets.
  63. */
  64. static void AddInitializedField(Command* cmd, int offset,
  65. int size, uint32_t value) {
  66. Field* fld = (Field*) calloc(1, sizeof(Field));
  67. fld->next = cmd->fields;
  68. cmd->fields = fld;
  69. fld->name = NULL;
  70. fld->visible = 0;
  71. fld->size = size;
  72. fld->offset = offset;
  73. fld->value = value;
  74. }
  75. /* Create a structure representing a TPM command datagram.
  76. */
  77. Command* newCommand(TPM_COMMAND_CODE code, int size) {
  78. Command* cmd = (Command*) calloc(1, sizeof(Command));
  79. cmd->size = size;
  80. AddInitializedField(cmd, 0, sizeof(TPM_TAG), TPM_TAG_RQU_COMMAND);
  81. AddInitializedField(cmd, sizeof(TPM_TAG), sizeof(uint32_t), size);
  82. AddInitializedField(cmd, sizeof(TPM_TAG) + sizeof(uint32_t),
  83. sizeof(TPM_COMMAND_CODE), code);
  84. return cmd;
  85. }
  86. /* The TPM_PCR_SELECTION structure in /usr/include/tss/tpm.h contains a pointer
  87. * instead of an array[3] of bytes, so we need to adjust sizes and offsets
  88. * accordingly.
  89. */
  90. #define PCR_SELECTION_FIX (3 - sizeof(char *))
  91. /* BuildXXX builds TPM command XXX.
  92. */
  93. Command* BuildDefineSpaceCommand(void) {
  94. int nv_data_public = kTpmRequestHeaderLength;
  95. int nv_index = nv_data_public + offsetof(TPM_NV_DATA_PUBLIC, nvIndex);
  96. int nv_pcr_info_read = nv_data_public +
  97. offsetof(TPM_NV_DATA_PUBLIC, pcrInfoRead);
  98. /*
  99. * Here we need to carefully add PCR_SELECTION_FIX (or twice that much) in
  100. * all the places where the offset calculation would be wrong without it.
  101. * The mismatch occurs in the TPM_PCR_SELECTION structure, and it must be
  102. * accounted for in all the structures that include it, directly or
  103. * indirectly.
  104. */
  105. int read_locality = nv_pcr_info_read +
  106. offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX;
  107. int nv_pcr_info_write = nv_data_public +
  108. offsetof(TPM_NV_DATA_PUBLIC, pcrInfoWrite) + PCR_SELECTION_FIX;
  109. int write_locality = nv_pcr_info_write +
  110. offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX;
  111. int nv_permission = nv_data_public +
  112. offsetof(TPM_NV_DATA_PUBLIC, permission) + 2 * PCR_SELECTION_FIX;
  113. int nv_permission_tag =
  114. nv_permission + offsetof(TPM_NV_ATTRIBUTES, tag);
  115. int nv_permission_attributes =
  116. nv_permission + offsetof(TPM_NV_ATTRIBUTES, attributes);
  117. int nv_datasize = nv_data_public +
  118. offsetof(TPM_NV_DATA_PUBLIC, dataSize) + 2 * PCR_SELECTION_FIX;
  119. int size = kTpmRequestHeaderLength + sizeof(TPM_NV_DATA_PUBLIC) +
  120. 2 * PCR_SELECTION_FIX + kEncAuthLength;
  121. Command* cmd = newCommand(TPM_ORD_NV_DefineSpace, size);
  122. cmd->name = "tpm_nv_definespace_cmd";
  123. AddVisibleField(cmd, "index", nv_index);
  124. AddVisibleField(cmd, "perm", nv_permission_attributes);
  125. AddVisibleField(cmd, "size", nv_datasize);
  126. AddInitializedField(cmd, nv_data_public, sizeof(uint16_t),
  127. TPM_TAG_NV_DATA_PUBLIC);
  128. AddInitializedField(cmd, nv_pcr_info_read, sizeof(uint16_t), 3);
  129. AddInitializedField(cmd, read_locality, sizeof(TPM_LOCALITY_SELECTION),
  130. TPM_ALL_LOCALITIES);
  131. AddInitializedField(cmd, nv_pcr_info_write, sizeof(uint16_t), 3);
  132. AddInitializedField(cmd, write_locality, sizeof(TPM_LOCALITY_SELECTION),
  133. TPM_ALL_LOCALITIES);
  134. AddInitializedField(cmd, nv_permission_tag, sizeof(TPM_STRUCTURE_TAG),
  135. TPM_TAG_NV_ATTRIBUTES);
  136. return cmd;
  137. }
  138. /* BuildXXX builds TPM command XXX.
  139. */
  140. Command* BuildWriteCommand(void) {
  141. Command* cmd = newCommand(TPM_ORD_NV_WriteValue, 0);
  142. cmd->name = "tpm_nv_write_cmd";
  143. cmd->max_size = TPM_LARGE_ENOUGH_COMMAND_SIZE;
  144. AddVisibleField(cmd, "index", kTpmRequestHeaderLength);
  145. AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8);
  146. AddVisibleField(cmd, "data", kTpmRequestHeaderLength + 12);
  147. return cmd;
  148. }
  149. Command* BuildReadCommand(void) {
  150. int size = kTpmRequestHeaderLength + kTpmReadInfoLength;
  151. Command* cmd = newCommand(TPM_ORD_NV_ReadValue, size);
  152. cmd->name = "tpm_nv_read_cmd";
  153. AddVisibleField(cmd, "index", kTpmRequestHeaderLength);
  154. AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8);
  155. return cmd;
  156. }
  157. Command* BuildPCRReadCommand(void) {
  158. int size = kTpmRequestHeaderLength + sizeof(uint32_t);
  159. Command* cmd = newCommand(TPM_ORD_PcrRead, size);
  160. cmd->name = "tpm_pcr_read_cmd";
  161. AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength);
  162. return cmd;
  163. }
  164. Command* BuildPPAssertCommand(void) {
  165. int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
  166. Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
  167. cmd->name = "tpm_ppassert_cmd";
  168. AddInitializedField(cmd, kTpmRequestHeaderLength,
  169. sizeof(TPM_PHYSICAL_PRESENCE),
  170. TPM_PHYSICAL_PRESENCE_PRESENT);
  171. return cmd;
  172. }
  173. Command* BuildPPEnableCommand(void) {
  174. int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
  175. Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
  176. cmd->name = "tpm_ppenable_cmd";
  177. AddInitializedField(cmd, kTpmRequestHeaderLength,
  178. sizeof(TPM_PHYSICAL_PRESENCE),
  179. TPM_PHYSICAL_PRESENCE_CMD_ENABLE);
  180. return cmd;
  181. }
  182. Command* BuildFinalizePPCommand(void) {
  183. int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
  184. Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
  185. cmd->name = "tpm_finalizepp_cmd";
  186. AddInitializedField(cmd, kTpmRequestHeaderLength,
  187. sizeof(TPM_PHYSICAL_PRESENCE),
  188. TPM_PHYSICAL_PRESENCE_CMD_ENABLE |
  189. TPM_PHYSICAL_PRESENCE_HW_DISABLE |
  190. TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK);
  191. return cmd;
  192. }
  193. Command* BuildPPLockCommand(void) {
  194. int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
  195. Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
  196. cmd->name = "tpm_pplock_cmd";
  197. AddInitializedField(cmd, kTpmRequestHeaderLength,
  198. sizeof(TPM_PHYSICAL_PRESENCE),
  199. TPM_PHYSICAL_PRESENCE_LOCK);
  200. return cmd;
  201. }
  202. Command* BuildStartupCommand(void) {
  203. int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE);
  204. Command* cmd = newCommand(TPM_ORD_Startup, size);
  205. cmd->name = "tpm_startup_cmd";
  206. AddInitializedField(cmd, kTpmRequestHeaderLength,
  207. sizeof(TPM_STARTUP_TYPE),
  208. TPM_ST_CLEAR);
  209. return cmd;
  210. }
  211. Command* BuildSaveStateCommand(void) {
  212. int size = kTpmRequestHeaderLength;
  213. Command* cmd = newCommand(TPM_ORD_SaveState, size);
  214. cmd->name = "tpm_savestate_cmd";
  215. return cmd;
  216. }
  217. Command* BuildResumeCommand(void) {
  218. int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE);
  219. Command* cmd = newCommand(TPM_ORD_Startup, size);
  220. cmd->name = "tpm_resume_cmd";
  221. AddInitializedField(cmd, kTpmRequestHeaderLength,
  222. sizeof(TPM_STARTUP_TYPE),
  223. TPM_ST_STATE);
  224. return cmd;
  225. }
  226. Command* BuildSelftestfullCommand(void) {
  227. int size = kTpmRequestHeaderLength;
  228. Command* cmd = newCommand(TPM_ORD_SelfTestFull, size);
  229. cmd->name = "tpm_selftestfull_cmd";
  230. return cmd;
  231. }
  232. Command* BuildContinueSelfTestCommand(void) {
  233. int size = kTpmRequestHeaderLength;
  234. Command* cmd = newCommand(TPM_ORD_ContinueSelfTest, size);
  235. cmd->name = "tpm_continueselftest_cmd";
  236. return cmd;
  237. }
  238. Command* BuildReadPubekCommand(void) {
  239. int size = kTpmRequestHeaderLength + sizeof(TPM_NONCE);
  240. Command* cmd = newCommand(TPM_ORD_ReadPubek, size);
  241. cmd->name = "tpm_readpubek_cmd";
  242. return cmd;
  243. }
  244. Command* BuildForceClearCommand(void) {
  245. int size = kTpmRequestHeaderLength;
  246. Command* cmd = newCommand(TPM_ORD_ForceClear, size);
  247. cmd->name = "tpm_forceclear_cmd";
  248. return cmd;
  249. }
  250. Command* BuildPhysicalEnableCommand(void) {
  251. int size = kTpmRequestHeaderLength;
  252. Command* cmd = newCommand(TPM_ORD_PhysicalEnable, size);
  253. cmd->name = "tpm_physicalenable_cmd";
  254. return cmd;
  255. }
  256. Command* BuildPhysicalDisableCommand(void) {
  257. int size = kTpmRequestHeaderLength;
  258. Command* cmd = newCommand(TPM_ORD_PhysicalDisable, size);
  259. cmd->name = "tpm_physicaldisable_cmd";
  260. return cmd;
  261. }
  262. Command* BuildPhysicalSetDeactivatedCommand(void) {
  263. int size = kTpmRequestHeaderLength + sizeof(uint8_t);
  264. Command* cmd = newCommand(TPM_ORD_PhysicalSetDeactivated, size);
  265. cmd->name = "tpm_physicalsetdeactivated_cmd";
  266. AddVisibleField(cmd, "deactivated", kTpmRequestHeaderLength);
  267. return cmd;
  268. }
  269. Command* BuildExtendCommand(void) {
  270. int size = kTpmRequestHeaderLength + sizeof(uint32_t) + kPcrDigestLength;
  271. Command* cmd = newCommand(TPM_ORD_Extend, size);
  272. cmd->name = "tpm_extend_cmd";
  273. AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength);
  274. AddVisibleField(cmd, "inDigest", kTpmRequestHeaderLength + sizeof(uint32_t));
  275. return cmd;
  276. }
  277. Command* BuildGetFlagsCommand(void) {
  278. int size = (kTpmRequestHeaderLength +
  279. sizeof(TPM_CAPABILITY_AREA) + /* capArea */
  280. sizeof(uint32_t) + /* subCapSize */
  281. sizeof(uint32_t)); /* subCap */
  282. Command* cmd = newCommand(TPM_ORD_GetCapability, size);
  283. cmd->name = "tpm_getflags_cmd";
  284. AddInitializedField(cmd, kTpmRequestHeaderLength,
  285. sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
  286. AddInitializedField(cmd, kTpmRequestHeaderLength +
  287. sizeof(TPM_CAPABILITY_AREA),
  288. sizeof(uint32_t), sizeof(uint32_t));
  289. AddInitializedField(cmd, kTpmRequestHeaderLength +
  290. sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
  291. sizeof(uint32_t), TPM_CAP_FLAG_PERMANENT);
  292. return cmd;
  293. }
  294. Command* BuildGetSTClearFlagsCommand(void) {
  295. int size = (kTpmRequestHeaderLength +
  296. sizeof(TPM_CAPABILITY_AREA) + /* capArea */
  297. sizeof(uint32_t) + /* subCapSize */
  298. sizeof(uint32_t)); /* subCap */
  299. Command* cmd = newCommand(TPM_ORD_GetCapability, size);
  300. cmd->name = "tpm_getstclearflags_cmd";
  301. AddInitializedField(cmd, kTpmRequestHeaderLength,
  302. sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
  303. AddInitializedField(cmd, kTpmRequestHeaderLength +
  304. sizeof(TPM_CAPABILITY_AREA),
  305. sizeof(uint32_t), sizeof(uint32_t));
  306. AddInitializedField(cmd, kTpmRequestHeaderLength +
  307. sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
  308. sizeof(uint32_t), TPM_CAP_FLAG_VOLATILE);
  309. return cmd;
  310. }
  311. Command* BuildGetPermissionsCommand(void) {
  312. int size = (kTpmRequestHeaderLength +
  313. sizeof(TPM_CAPABILITY_AREA) + /* capArea */
  314. sizeof(uint32_t) + /* subCapSize */
  315. sizeof(uint32_t)); /* subCap */
  316. Command* cmd = newCommand(TPM_ORD_GetCapability, size);
  317. cmd->name = "tpm_getpermissions_cmd";
  318. AddInitializedField(cmd, kTpmRequestHeaderLength,
  319. sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX);
  320. AddInitializedField(cmd, kTpmRequestHeaderLength +
  321. sizeof(TPM_CAPABILITY_AREA),
  322. sizeof(uint32_t), sizeof(uint32_t));
  323. AddVisibleField(cmd, "index", kTpmRequestHeaderLength +
  324. sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t));
  325. return cmd;
  326. }
  327. Command* BuildGetOwnershipCommand(void) {
  328. int size = (kTpmRequestHeaderLength +
  329. sizeof(TPM_CAPABILITY_AREA) + /* capArea */
  330. sizeof(uint32_t) + /* subCapSize */
  331. sizeof(uint32_t)); /* subCap */
  332. Command* cmd = newCommand(TPM_ORD_GetCapability, size);
  333. cmd->name = "tpm_getownership_cmd";
  334. AddInitializedField(cmd, kTpmRequestHeaderLength,
  335. sizeof(TPM_CAPABILITY_AREA), TPM_CAP_PROPERTY);
  336. AddInitializedField(cmd, kTpmRequestHeaderLength +
  337. sizeof(TPM_CAPABILITY_AREA),
  338. sizeof(uint32_t), sizeof(uint32_t));
  339. AddInitializedField(cmd, kTpmRequestHeaderLength +
  340. sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
  341. sizeof(uint32_t), TPM_CAP_PROP_OWNER);
  342. return cmd;
  343. }
  344. Command* BuildGetRandomCommand(void) {
  345. int size = kTpmRequestHeaderLength + sizeof(uint32_t);
  346. Command* cmd = newCommand(TPM_ORD_GetRandom, size);
  347. cmd->name = "tpm_get_random_cmd";
  348. AddVisibleField(cmd, "bytesRequested", kTpmRequestHeaderLength);
  349. return cmd;
  350. }
  351. /* Output the fields of a structure.
  352. */
  353. void OutputFields(Field* fld) {
  354. /*
  355. * Field order is reversed.
  356. */
  357. if (fld != NULL) {
  358. OutputFields(fld->next);
  359. if (fld->visible) {
  360. printf(" uint16_t %s;\n", fld->name);
  361. }
  362. }
  363. }
  364. /* Outputs a structure initializer.
  365. */
  366. int OutputBytes_(Command* cmd, Field* fld) {
  367. int cursor = 0;
  368. int i;
  369. /*
  370. * Field order is reversed.
  371. */
  372. if (fld != NULL) {
  373. cursor = OutputBytes_(cmd, fld->next);
  374. } else {
  375. return 0;
  376. }
  377. if (!fld->visible) {
  378. /*
  379. * Catch up missing fields.
  380. */
  381. assert(fld->offset >= cursor);
  382. for (i = 0; i < fld->offset - cursor; i++) {
  383. printf("0, ");
  384. }
  385. cursor = fld->offset;
  386. switch (fld->size) {
  387. case 1:
  388. printf("0x%x, ", fld->value);
  389. cursor += 1;
  390. break;
  391. case 2:
  392. printf("0x%x, 0x%x, ", fld->value >> 8, fld->value & 0xff);
  393. cursor += 2;
  394. break;
  395. case 4:
  396. printf("0x%x, 0x%x, 0x%x, 0x%x, ", fld->value >> 24,
  397. (fld->value >> 16) & 0xff,
  398. (fld->value >> 8) & 0xff,
  399. fld->value & 0xff);
  400. cursor += 4;
  401. break;
  402. default:
  403. fprintf(stderr, "invalid field size %d\n", fld->size);
  404. exit(1);
  405. break;
  406. }
  407. }
  408. return cursor;
  409. }
  410. /* Helper to output a structure initializer.
  411. */
  412. void OutputBytes(Command* cmd) {
  413. (void) OutputBytes_(cmd, cmd->fields);
  414. }
  415. void OutputFieldPointers(Command* cmd, Field* fld) {
  416. if (fld == NULL) {
  417. return;
  418. } else {
  419. OutputFieldPointers(cmd, fld->next);
  420. if (fld->visible) {
  421. printf("%d, ", fld->offset);
  422. }
  423. }
  424. }
  425. /* Outputs the structure initializers for all commands.
  426. */
  427. void OutputCommands(Command* cmd) {
  428. if (cmd == NULL) {
  429. return;
  430. } else {
  431. printf("const struct s_%s{\n uint8_t buffer[%d];\n",
  432. cmd->name, cmd->size == 0 ? cmd->max_size : cmd->size);
  433. OutputFields(cmd->fields);
  434. printf("} %s = {{", cmd->name);
  435. OutputBytes(cmd);
  436. printf("},\n");
  437. OutputFieldPointers(cmd, cmd->fields);
  438. printf("};\n\n");
  439. }
  440. OutputCommands(cmd->next);
  441. }
  442. Command* (*builders[])(void) = {
  443. BuildDefineSpaceCommand,
  444. BuildWriteCommand,
  445. BuildReadCommand,
  446. BuildPCRReadCommand,
  447. BuildPPAssertCommand,
  448. BuildPPEnableCommand,
  449. BuildPPLockCommand,
  450. BuildFinalizePPCommand,
  451. BuildStartupCommand,
  452. BuildSaveStateCommand,
  453. BuildResumeCommand,
  454. BuildSelftestfullCommand,
  455. BuildContinueSelfTestCommand,
  456. BuildReadPubekCommand,
  457. BuildForceClearCommand,
  458. BuildPhysicalDisableCommand,
  459. BuildPhysicalEnableCommand,
  460. BuildPhysicalSetDeactivatedCommand,
  461. BuildGetFlagsCommand,
  462. BuildGetSTClearFlagsCommand,
  463. BuildGetPermissionsCommand,
  464. BuildGetOwnershipCommand,
  465. BuildGetRandomCommand,
  466. BuildExtendCommand,
  467. };
  468. static void FreeFields(Field* fld) {
  469. if (fld != NULL) {
  470. Field* next_field = fld->next;
  471. free(fld);
  472. FreeFields(next_field);
  473. }
  474. }
  475. static void FreeCommands(Command* cmd) {
  476. if (cmd != NULL) {
  477. Command* next_command = cmd->next;
  478. FreeFields(cmd->fields);
  479. free(cmd);
  480. FreeCommands(next_command);
  481. }
  482. }
  483. int main(void) {
  484. Command* commands = NULL;
  485. int i;
  486. for (i = 0; i < sizeof(builders) / sizeof(builders[0]); i++) {
  487. Command* cmd = builders[i]();
  488. cmd->next = commands;
  489. commands = cmd;
  490. }
  491. printf("/* This file is automatically generated */\n\n");
  492. OutputCommands(commands);
  493. printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO));
  494. printf("const int kNvDataPublicPermissionsOffset = %d;\n",
  495. (int) (offsetof(TPM_NV_DATA_PUBLIC, permission) +
  496. 2 * PCR_SELECTION_FIX +
  497. offsetof(TPM_NV_ATTRIBUTES, attributes)));
  498. FreeCommands(commands);
  499. return 0;
  500. }