2 * This file is part of the OpenPTS project.
4 * The Initial Developer of the Original Code is International
5 * Business Machines Corporation. Portions created by IBM
6 * Corporation are Copyright (C) 2010 International Business
7 * Machines Corporation. All Rights Reserved.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the Common Public License as published by
11 * IBM Corporation; either version 1 of the License, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * Common Public License for more details.
19 * You should have received a copy of the Common Public License
20 * along with this program; if not, a copy can be viewed at
21 * http://www.opensource.org/licenses/cpl1.0.php.
26 * \brief Finite State Machine
27 * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
29 * cleanup 2011-01-21 SM
30 * refactoring 2011-07-20 SM
46 #include <libxml/encoding.h>
47 #include <libxml/xmlwriter.h>
48 #include <libxml/parser.h>
53 * create new FSM context
55 OPENPTS_FSM_CONTEXT *newFsmContext() {
56 OPENPTS_FSM_CONTEXT *ctx = NULL;
59 ctx = (OPENPTS_FSM_CONTEXT *) xmalloc(sizeof(OPENPTS_FSM_CONTEXT));
61 LOG(LOG_ERR, "no memory");
65 memset(ctx, 0 , sizeof(OPENPTS_FSM_CONTEXT));
67 ctx->fsm_trans = NULL;
70 ctx->subvertex_num = 0;
71 ctx->transition_num = 0;
76 * Free OPENPTS_FSM_Transition chain
78 void freeFsmTransitionChain(OPENPTS_FSM_Transition *fsm_trans) {
80 if (fsm_trans == NULL) {
81 LOG(LOG_ERR, "null input");
86 if (fsm_trans->next != NULL) {
87 freeFsmTransitionChain(fsm_trans->next);
91 if (fsm_trans->digest != NULL) {
92 xfree(fsm_trans->digest);
99 * Free OPENPTS_FSM_Subvertex chain
101 void freeFsmSubvertexChain(OPENPTS_FSM_Subvertex *fsm_sub) {
104 if (fsm_sub == NULL) {
105 LOG(LOG_ERR, "null input");
110 if (fsm_sub->next != NULL) {
111 freeFsmSubvertexChain(fsm_sub->next);
121 int freeFsmContext(OPENPTS_FSM_CONTEXT *ctx) {
125 LOG(LOG_ERR, "null input");
130 if (ctx->fsm_trans != NULL) {
131 freeFsmTransitionChain(ctx->fsm_trans);
132 ctx->fsm_trans = NULL;
136 if (ctx->fsm_sub != NULL) {
137 freeFsmSubvertexChain(ctx->fsm_sub);
142 if (ctx->uml_file != NULL) {
143 xfree(ctx->uml_file);
144 ctx->uml_file = NULL;
155 * reset FSM subvertex
157 void resetFsmSubvertex(OPENPTS_FSM_CONTEXT *ctx) {
160 LOG(LOG_ERR, "null input");
165 ctx->subvertex_num = 0;
169 * reset FSM transition
171 void resetFsmTransition(OPENPTS_FSM_CONTEXT *ctx) {
174 LOG(LOG_ERR, "null input");
179 ctx->transition_num = 0;
184 * add FMS subvertex to context
186 void addFsmSubvertex(
187 OPENPTS_FSM_CONTEXT *ctx,
193 OPENPTS_FSM_Subvertex *ptr = NULL;
194 OPENPTS_FSM_Subvertex *ptr_pre = NULL;
196 DEBUG_CAL("addFsmSubvertex - %d \n", ctx->subvertex_num);
200 LOG(LOG_ERR, "null input");
204 LOG(LOG_ERR, "null input");
208 LOG(LOG_ERR, "null input");
212 LOG(LOG_ERR, "null input");
215 if (action == NULL) {
216 LOG(LOG_ERR, "null input");
222 for (i = 0; i <= ctx->subvertex_num; i++) {
224 /* add new PENPTS_FSM_Subvertex */
225 DEBUG_FSM(" id=%s name=%s size=%d\n",
227 (int)sizeof(OPENPTS_FSM_Subvertex));
229 /* malloc OPENPTS_FSM_Subvertex */
230 ptr = (OPENPTS_FSM_Subvertex *)
231 xmalloc(sizeof(OPENPTS_FSM_Subvertex));
237 memset(ptr, 0, sizeof(OPENPTS_FSM_Subvertex));
238 /* setup new FSM_Subvertex */
239 memcpy(ptr->type, type, FSM_BUF_SIZE);
240 memcpy(ptr->id, id, FSM_BUF_SIZE);
241 memcpy(ptr->name, name, FSM_BUF_SIZE);
242 memcpy(ptr->action, action, FSM_BUF_SIZE);
245 ptr->num = ctx->subvertex_num;
246 ptr->incomming_num = 0;
248 if (ctx->subvertex_num == 0) { // first event
251 // NG must be Start event ctx->curr_state = ptr;
252 } else if (ptr_pre != NULL) {
253 ptr_pre->next = ptr; // else
256 LOG(LOG_ERR, "BAD, free last one");
257 xfree(ptr); // free last one
261 ctx->subvertex_num++;
270 * get Subvertex ptr by ID
272 OPENPTS_FSM_Subvertex * getSubvertex(OPENPTS_FSM_CONTEXT *ctx, char * id) {
273 OPENPTS_FSM_Subvertex *ptr;
277 LOG(LOG_ERR, "null input");
281 LOG(LOG_ERR, "null input");
286 if (!strcmp(id, "Final")) return NULL; // final state
290 while (ptr != NULL) {
291 if (!strcmp(id, ptr->id)) return ptr;
292 ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
299 * get Subvertex Name by ID
301 char * getSubvertexName(OPENPTS_FSM_CONTEXT *ctx, char * id) {
303 OPENPTS_FSM_Subvertex *ptr;
307 LOG(LOG_ERR, "null input");
311 LOG(LOG_ERR, "null input");
316 if (!strcmp(id, "Final")) return id;
319 for (i = 0;i <= ctx->subvertex_num; i++) {
320 if (!strcmp(id, ptr->id)) return ptr->name;
321 ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
328 * get Subvertex ID by Name
330 char * getSubvertexId(OPENPTS_FSM_CONTEXT *ctx, char * name) {
332 OPENPTS_FSM_Subvertex *ptr;
336 LOG(LOG_ERR, "null input");
340 LOG(LOG_ERR, "null input");
345 for (i = 0;i <= ctx->subvertex_num; i++) {
346 if (!strcmp(name, ptr->name)) return ptr->id;
347 ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
356 static char *skipWhiteSpace(char *str, int *len /* out */) {
357 char *cur = str, *end = str + *len;
361 LOG(LOG_ERR, "null input");
375 static int isEndOfString(char *str) {
378 LOG(LOG_ERR, "null input");
385 static char *skipParameter(char *str, int *len /* out */) {
386 char *cur = str, *end = str + *len;
390 LOG(LOG_ERR, "null input");
406 * <body>eventtype == 0x01, digest == base64</body>
412 * Unit Test : check_fsm.c / test_getTypeFlag
415 int getTypeFlag(char * cond, UINT32 *eventtype /* out */) {
419 long int val; // TODO uint64_t? but build fail on i386 platform
423 LOG(LOG_ERR, "null input");
428 loc = strstr(cond, "eventtype");
430 if (loc == NULL) { // miss
438 loc = skipWhiteSpace(loc, &len);
439 if (isEndOfString(loc)) {
445 LOG(LOG_ERR, "ERROR 001\n");
448 if ((loc[0] == '=') && (loc[1] == '=')) { // ==
450 } else if ((loc[0] == 'e') && (loc[1] == 'q')) { // ==
452 } else if ((loc[0] == '!') && (loc[1] == '=')) { // !=
454 } else if ((loc[0] == 'n') && (loc[1] == 'e')) { // !=
457 LOG(LOG_ERR, "ERROR 002 %c %c \n", loc[0], loc[1]);
458 return -1; // unknown operand
463 loc = skipWhiteSpace(loc, &len);
464 if (isEndOfString(loc)) {
469 // 20110117 Ubuntu i386, 0x80000002 => 7FFFFFFF, => use strtoll
471 if ((loc[0] == '0') && (loc[1] == 'x')) { // 0x HEX
472 val = strtoll(loc, NULL, 16);
473 *eventtype = (UINT32)val;
474 // DEBUG("strtol [%s] => %X => %X\n", loc,val,*eventtype);
478 val = strtoll(loc, NULL, 10);
479 *eventtype = (UINT32)val;
480 // DEBUG("strtol [%s] => %X => %X\n", loc,val, *eventtype);
487 * Parse condition string and setup an internal digest condition structure
491 * 1: valid (=binary model), return the digest => freed at freeFsmTransitionChain()
492 * 2: ignore now (=behavior model or ignored digests in binary model)
495 * Unit Test : check_fsm.c / test_getDigestFlag
497 * TODO STA may complain the memory leak againt *digest.
499 int getDigestFlag(char * cond, BYTE **digest, int *digest_size) {
500 char * loc; // loc at value
505 DEBUG_CAL("getDigestFlag -");
509 LOG(LOG_ERR, "null input");
515 loc = strstr(cond, "digest");
516 if (loc == NULL) { // miss
518 return DIGEST_FLAG_SKIP;
524 loc = skipWhiteSpace(loc, &len);
525 if (isEndOfString(loc)) {
529 /* operation, "==" only */
531 LOG(LOG_ERR, "ERROR 001\n");
534 if ((loc[0] == '=') && (loc[1] == '=')) { // ==
537 LOG(LOG_ERR, "ERROR 002 [%c%c] not ==, (cond = %s)\n", loc[0], loc[1], cond);
538 return -1; // unknown operand
544 loc = skipWhiteSpace(loc, &len);
545 if (isEndOfString(loc)) {
549 if (NULL != strstr(loc, "base64!")) { // HIT, temp
551 return DIGEST_FLAG_IGNORE;
552 } else if (NULL != strstr(loc, "base64")) { // HIT, temp
554 return DIGEST_FLAG_IGNORE;
555 } else if (NULL != strstr(loc, "transparent!")) {
556 /* we have been told to ignore this digest from the binary model */
557 /* and use the behaviour version instead */
558 return DIGEST_FLAG_TRANSPARENT;
561 /* Base64 str -> BYTE[] */
564 SHA1_BASE64_DIGEST_SIZE,
567 LOG(LOG_ERR, "decodeBase64 fail");
571 } else if (buf_len == SHA1_DIGEST_SIZE) {
573 *digest_size = SHA1_DIGEST_SIZE;
574 return DIGEST_FLAG_EQUAL; // 1
576 LOG(LOG_ERR, "getDigestFlag() - decodeBase64() was failed \n");
587 * Parse condition string and setup an internal couter condition structure
592 * COUNTER_FLAG_SKIP 0: don't care
593 * COUNTER_FLAG_LT 1: < name
594 * COUNTER_FLAG_GTE 2: >= name
596 * Unit Test : check_fsm.c / test_getCounterFlag
598 int getCounterFlag(char *cond, char *name, char **flag /* out */) {
599 char * loc; // loc at value
600 char * loc2; // loc at flag
602 int rc = COUNTER_FLAG_SKIP;
606 LOG(LOG_ERR, "Null condition found");
610 LOG(LOG_ERR, "Null condition found");
616 loc = strstr(cond, name);
629 loc = skipWhiteSpace(loc, &len);
630 if (isEndOfString(loc)) {
631 goto error; //return -1;
634 /* operation, "<" ">=" only */
635 if ((len >= 2) && (loc[0] == 'l') && (loc[1] == 't')) { // <, lt
636 rc = COUNTER_FLAG_LT;
639 } else if ((len >= 2) && (loc[0] == 'l') && (loc[1] == 'e')) { // <=, le
640 rc = COUNTER_FLAG_LE;
643 } else if ((len >= 2) && (loc[0] == 'g') && (loc[1] == 't')) { // >, gt
644 rc = COUNTER_FLAG_GT;
647 } else if ((len >= 2) && (loc[0] == 'g') && (loc[1] == 'e')) { // >, gt
648 rc = COUNTER_FLAG_GE;
651 } else if ((len >= 2) && (loc[0] == '<') && (loc[1] == ' ')) { // <, lt
652 rc = COUNTER_FLAG_LT;
655 } else if ((len >= 2) && (loc[0] == '<') && (loc[1] == '=')) { // <=, le
656 rc = COUNTER_FLAG_LE;
659 } else if ((len >= 2) && (loc[0] == '>') && (loc[1] == ' ')) { // >, gt
660 rc = COUNTER_FLAG_GT;
663 } else if ((len >= 2) && (loc[0] == '>') && (loc[1] == '=')) { // >=
664 rc = COUNTER_FLAG_GE;
668 LOG(LOG_ERR, "unknown operand [%s]", &loc[0]);
669 goto error; //return -1;
672 loc = skipWhiteSpace(loc, &len);
673 if (isEndOfString(loc)) {
674 goto error; //return -1;
677 // TODO check the end, this code only support if counter is the last
679 loc2 = skipParameter(loc, &len);
680 param_len = loc2 - loc;
681 if (0 == param_len) {
682 /* we haven't moved along the string - no valid parameter found */
683 goto error; //return -1;
686 /* DEBUG_FSM("[%d][%s][%s]\n",len, loc, loc2); */
688 *flag = xmalloc(param_len + 1);
690 goto error; //return -1;
692 memset(*flag, 0, param_len + 1);
693 memcpy(*flag, loc, param_len);
696 DEBUG_FSM("getCounterFlag %s #=> %d %s\n", cond, rc, *flag);
701 LOG(LOG_ERR, "getCounterFlag(\"%s\",\"%s\") fail", cond, name);
708 * Parse condition string and setup an internal couter condition structure
714 * LAST_FLAG_SKIP 0: don't care
715 * LAST_FLAG_EQ 1: == last
716 * LAST_FLAG_NEQ 2: != last
718 * Unit Test : check_fsm.c / test_getCounterFlag
720 int getLastFlag(char * cond) {
721 char * loc; // loc at value
722 char * loc2; // loc at name
724 int rc = LAST_FLAG_SKIP;
728 LOG(LOG_ERR, "null input");
733 loc = strstr(cond, "last");
737 return LAST_FLAG_SKIP;
741 loc += 4; // 2011-12-30 5 => 4
744 loc = skipWhiteSpace(loc, &len);
745 if (isEndOfString(loc)) {
749 /* operation, "<" ">=" only */
750 if ((len >= 2) && (loc[0] == '=') && (loc[1] == '=')) {
755 } else if ((len >= 2) && (loc[0] == '!') && (loc[1] == '=')) {
761 LOG(LOG_ERR, "Unknown operation [%s], cond=[%s], BAD Validation Model\n", &loc[0], cond);
765 loc = skipWhiteSpace(loc, &len);
766 if (isEndOfString(loc)) {
767 LOG(LOG_ERR, "Unknown operation [%s]\n", &loc[0]);
775 if (!strncmp(loc2, "true", 4)) {
778 /* != true => false */
779 } else if (!strncmp(loc2, "false", 5)) {
780 // DEBUG("false %d\n",rc);
781 if (rc == LAST_FLAG_EQ) {
787 LOG(LOG_ERR, "unknown value, %s\n", loc2);
791 // DEBUG("getLastFlag %s #=> %d\n",cond, rc);
806 int addFsmTransition(
807 OPENPTS_FSM_CONTEXT *ctx,
812 OPENPTS_FSM_Transition *ptr = NULL;
813 OPENPTS_FSM_Transition *ptr_pre = NULL;
815 DEBUG_CAL("addFsmTransition - start\n");
819 LOG(LOG_ERR, "null input");
822 if (source == NULL) {
823 LOG(LOG_ERR, "null input");
826 if (target == NULL) {
827 LOG(LOG_ERR, "null input");
831 LOG(LOG_ERR, "null input");
836 ptr = ctx->fsm_trans;
837 for (i = 0; i <= ctx->transition_num; i++) {
838 if (ptr == NULL) { // new
839 DEBUG_FSM(" src=%s -> dst=%s cond[%s] %d\n",
840 source, target, cond,
841 (int)sizeof(OPENPTS_FSM_Transition));
843 /* malloc OPENPTS_FSM_Transition */
844 ptr = (OPENPTS_FSM_Transition *)
845 xmalloc(sizeof(OPENPTS_FSM_Transition));
847 LOG(LOG_ERR, "no memory");
848 return PTS_INTERNAL_ERROR;
851 memset(ptr, 0, sizeof(OPENPTS_FSM_Transition));
852 memcpy(ptr->source, source, FSM_BUF_SIZE);
853 memcpy(ptr->target, target, FSM_BUF_SIZE);
854 ptr->num = ctx->transition_num;
856 ptr->eventTypeFlag = 0;
857 ptr->digestFlag = DIGEST_FLAG_SKIP;
858 } else if (cond[0] == 0) {
859 ptr->eventTypeFlag = 0;
860 ptr->digestFlag = DIGEST_FLAG_SKIP;
861 memcpy(ptr->cond, cond, FSM_BUF_SIZE);
863 // 0:don't care, 1:care
864 ptr->eventTypeFlag = getTypeFlag(cond, &ptr->eventType);
865 // 0:don't care, 1:care, 2:temp, 3:transparent
866 ptr->digestFlag = getDigestFlag(cond, &ptr->digest, &ptr->digestSize);
867 // 0:don't care, 1:<, 2:>=
868 ptr->counter_flag = getCounterFlag(cond, "digest_count", &ptr->counter_name);
869 if (ptr->counter_flag < 0) {
870 LOG(LOG_ERR, "getCounterFlag() fail (%s => %s [%s])", source, target, cond);
872 // 0:don't care, 1:<, 2:>=
873 ptr->fatal_counter_flag = getCounterFlag(cond, "fatal_count", &ptr->fatal_counter_name);
874 if (ptr->fatal_counter_flag < 0) {
875 LOG(LOG_ERR, "getCounterFlag() fail (%s => %s [%s])", source, target, cond);
877 // 0:don't care 1: ==last 2: != last
878 ptr->last_flag = getLastFlag(cond);
879 memcpy(ptr->cond, cond, FSM_BUF_SIZE);
881 /* subvertex link (ptr) */
882 ptr->source_subvertex = getSubvertex(ctx, ptr->source);
883 ptr->target_subvertex = getSubvertex(ctx, ptr->target);
885 if (DIGEST_FLAG_TRANSPARENT == ptr->digestFlag) {
886 DEBUG_FSM("Found transparent digest\n");
887 ctx->numTransparencies++;
892 if (ctx->transition_num == 0) {
893 ctx->fsm_trans = ptr;
894 ptr->prev = NULL; // first trans
895 } else if (ptr_pre != NULL) {
898 ptr->next = NULL; // last trans
900 LOG(LOG_ERR, "BAD, free last one");
901 xfree(ptr); // free last one
902 return PTS_INTERNAL_ERROR;
904 ctx->transition_num++;
910 ptr = (OPENPTS_FSM_Transition *)ptr->next;
913 LOG(LOG_ERR, "missing?\n");
914 return PTS_INTERNAL_ERROR;
919 * get Event String (malloc) - obsolete function
921 char *getEventString(OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
923 int size = FSM_BUF_SIZE; // TODO fixed size
924 TSS_PCR_EVENT *event;
934 event = eventWrapper->event;
936 // len = snprintf(buf, size, "PCR[%d],TYPE=%d", (int)event->ulPcrIndex, event->eventType);
938 LOG(LOG_ERR, "NULL event\n"); // TODO(munetoh)
948 * get counter(int) value from property
954 * 1 : missing, invalid (e.g. minus)
957 int getCountFromProperty(OPENPTS_CONTEXT *ctx, char * name) {
958 int count = 0; // TODO get from prop
959 OPENPTS_PROPERTY *prop;
963 LOG(LOG_ERR, "null input");
967 LOG(LOG_ERR, "null input");
972 prop = getProperty(ctx, name);
974 /* Hit use this properties */
975 count = atoi(prop->value);
976 DEBUG_FSM("getCountFromProperty - prop %s = %d\n", name, count);
978 DEBUG("getCountFromProperty - prop %s is %d < 0. set count to 1\n", count, name);
984 DEBUG("getCountFromProperty - prop %s is missing. add property with count=1\n", name);
985 addProperty(ctx, name, "1");
992 * Drive FSM Transition by Event
994 * @parm eventWrapper NULL, push the FSM until Final state
1000 * OPENPTS_FSM_SUCCESS
1002 * OPENPTS_FSM_FINISH reach Final State, move to the next snapshot(=model)
1003 * OPENPTS_FSM_TRANSIT transit to next FSM
1004 * OPENPTS_FSM_ERROR_LOOP
1006 * if eventWrapper is NULL, create and use dummy event
1009 OPENPTS_CONTEXT *ctx,
1010 OPENPTS_FSM_CONTEXT *fsm,
1011 OPENPTS_PCR_EVENT_WRAPPER *eventWrapper
1013 int rc = OPENPTS_FSM_SUCCESS;
1014 OPENPTS_FSM_Subvertex *curr_state;
1015 OPENPTS_FSM_Transition *trans;
1016 TSS_PCR_EVENT *event;
1019 int fatal_counter_check;
1024 OPENPTS_FSM_Transition *hit_trans = NULL;
1026 DEBUG_CAL("updateFsm - start\n");
1030 LOG(LOG_ERR, "null input");
1034 LOG(LOG_ERR, "null input");
1038 curr_state = fsm->curr_state;
1039 if (curr_state == NULL) {
1040 DEBUG_FSM("[RM%02d-PCR%02d] updateFsm() - curr_state == NULL => set the FSM state to 'Start'\n",
1041 fsm->level, fsm->pcr_index);
1042 curr_state = getSubvertex(fsm, "Start");
1044 trans = fsm->fsm_trans;
1046 /* Null event -> push FSM until Final state */
1047 // TODO(munetoh) dummy event does not need event. just add flag to the wrapper
1048 if (eventWrapper == NULL) {
1049 DEBUG_FSM("[RM%02d-PCR%02d] create dummy event to flash the FSM\n",
1050 fsm->level, fsm->pcr_index);
1053 eventWrapper = (OPENPTS_PCR_EVENT_WRAPPER *)
1054 xmalloc_assert(sizeof(OPENPTS_PCR_EVENT_WRAPPER));
1055 memset(eventWrapper, 0, sizeof(OPENPTS_PCR_EVENT_WRAPPER));
1056 eventWrapper->event_type = OPENPTS_DUMMY_EVENT;
1057 eventWrapper->push_count = 0;
1058 eventWrapper->last = 1;
1061 rc = updateFsm(ctx, fsm, eventWrapper);
1062 if (rc == OPENPTS_FSM_ERROR) {
1063 LOG(LOG_ERR, "updateFsm() - updateFsm push was fail\n");
1065 if (rc == OPENPTS_FSM_ERROR_LOOP) {
1066 // DEBUG("updateFsm -- updateFsm push - loop \n");
1069 /* free dummy wrapper */
1070 xfree(eventWrapper);
1071 eventWrapper = NULL;
1073 } else if (eventWrapper->event == NULL) {
1074 if (eventWrapper->event_type == OPENPTS_DUMMY_EVENT) {
1076 eventWrapper->push_count++;
1079 if (eventWrapper->push_count > 10) {
1082 // DEBUG("LOOP?\n");
1083 return OPENPTS_FSM_ERROR_LOOP;
1086 LOG(LOG_ERR, "missing event body\n");
1087 return OPENPTS_FSM_ERROR;
1090 /* FSM update by event */
1091 event = eventWrapper->event;
1094 DEBUG_FSM("[RM%02d-PCR%02d] updateFsm() - State='%s', action='%s'\n",
1095 fsm->level, fsm->pcr_index,
1096 curr_state->name, curr_state->action);
1098 if ((event != NULL) && isDebugFlagSet(DEBUG_FSM_FLAG)) {
1099 hex = getHexString(event->rgbPcrValue, event->ulPcrValueLength);
1100 DEBUG_FSM("[RM%02d-PCR%02d] eventtype=0x%x, digest=0x%s\n",
1101 fsm->level, fsm->pcr_index,
1102 event->eventType, hex);
1106 if (eventWrapper->event_type == OPENPTS_DUMMY_EVENT) {
1107 // DEBUG("flash FSM\n");
1108 /* Flash the trans chain */
1110 while (trans != NULL) {
1111 if (!strcmp(trans->source, curr_state->id)) {
1112 /* ID HIT, this is the trans from current state */
1114 /* Is this Final (last)? */
1115 if (!strcmp(trans->target, UML2_SD_FINAL_STATE_STRING)) {
1116 /* Final state => PENPTS_FSM_FINISH_WO_HIT */
1117 DEBUG_FSM("[RM%02d-PCR%02d] Final state! move to the next snapshot\n",
1118 fsm->level, fsm->pcr_index);
1119 fsm->status = OPENPTS_FSM_FINISH;
1120 return OPENPTS_FSM_FINISH_WO_HIT;
1126 if (trans->last_flag == LAST_FLAG_EQ) {
1127 DEBUG_FSM("check last == true\n");
1128 if (eventWrapper->last == 1) {
1132 } else if (trans->last_flag == LAST_FLAG_NEQ) {
1133 DEBUG_FSM("check last != true\n");
1134 if (eventWrapper->last == 0) {
1139 // DEBUG_FSM("last - don't care\n");
1142 trans = trans->next;
1146 if (hit_trans != NULL) {
1147 // DEBUG("hit_trans\n");
1148 hit = 1; // SKIP with this trans
1149 DEBUG_FSM("[RM%02d-PCR%02d] '%s' -> '%s'\n",
1150 fsm->level, fsm->pcr_index,
1151 hit_trans->source, hit_trans->target);
1152 fsm->curr_state = getSubvertex(fsm, hit_trans->target);
1154 if (fsm->curr_state != NULL) {
1155 /* doActivity, update properties */
1156 rc = doActivity(ctx, (char *)fsm->curr_state->action, NULL); // action.c
1157 if (rc == OPENPTS_FSM_FLASH) {
1158 /* last event, Flash FSM */
1159 DEBUG_FSM("\t\tFlash FSM (don't care trans)\n");
1161 rc = updateFsm(ctx, fsm, NULL);
1163 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1164 rc = OPENPTS_FSM_FINISH;
1166 LOG(LOG_ERR, "updateFsm - flash FSM was failed\n");
1167 rc = OPENPTS_FSM_ERROR;
1169 } else if (rc == OPENPTS_FSM_TRANSIT) {
1171 DEBUG_FSM("\t\tFlash FSM before transit \n");
1173 rc = updateFsm(ctx, fsm, NULL); // flash FSM
1175 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1176 rc = OPENPTS_FSM_TRANSIT;
1178 LOG(LOG_ERR, "updateFsm - FSM did not finish\n");
1179 rc = OPENPTS_FSM_ERROR;
1181 } else if (rc == OPENPTS_FSM_ERROR) {
1182 LOG(LOG_ERR, "updateFsm - FSM doActivity False\n");
1184 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1185 LOG(LOG_TODO, "updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1187 } else if (rc == OPENPTS_FSM_SUCCESS) {
1188 rc = updateFsm(ctx, fsm, eventWrapper);
1189 } else if (rc == PTS_INTERNAL_ERROR) {
1190 // TODO << INFO:(TODO) action.c:97 addBIOSAction() - eventWrapper is NULL
1191 rc = updateFsm(ctx, fsm, eventWrapper);
1193 LOG(LOG_TODO, "updateFsm() - rc = %d, call updateFsm() again\n", rc);
1194 rc = updateFsm(ctx, fsm, eventWrapper);
1198 LOG(LOG_TODO, "no trans\n");
1201 /* check trans chain */
1202 // DEBUG("updateFsm - check trans\n");
1203 while (trans != NULL) {
1208 if (!strcmp(trans->source, curr_state->id)) {
1209 /* ID HIT, this is the trans from current state */
1211 /* check the last flag */
1215 if (trans->last_flag == LAST_FLAG_EQ) {
1216 DEBUG_FSM("check last == true\n");
1217 if (eventWrapper->last == 1) {
1223 } else if (trans->last_flag == LAST_FLAG_NEQ) {
1224 DEBUG_FSM("check last != true\n");
1225 if (eventWrapper->last == 0) {
1232 // DEBUG_FSM("last - don't care\n");
1235 if (last_check == 1) {
1236 DEBUG_FSM("last event push the FSM\n");
1238 // DEBUG("NOT last event??? last_check = %d\n", last_check);
1239 // DEBUG("NOT last event??? eventWrapper->last = %d\n", eventWrapper->last);
1240 // DEBUG("NOT last event??? trans->last_flag = %d\n", trans->last_flag);
1244 /* check the event type */
1246 if (trans->eventTypeFlag == EVENTTYPE_FLAG_EQUAL) {
1247 // DEBUG_FSM("eventtype == %d - ", trans->eventType);
1248 if (trans->eventType == event->eventType) {
1250 // DEBUG_FSM("- valid\n");
1253 // DEBUG_FSM("- invalid type %d(model) != %d(iml)\n", trans->eventType, event->eventType);
1256 } else if (trans->eventTypeFlag == EVENTTYPE_FLAG_NOT_EQUAL) {
1257 // DEBUG_FSM("eventtype != %d - ", trans->eventType);
1258 if (trans->eventType != event->eventType) {
1260 DEBUG_FSM("\t\t type %x(trans) != %x(event) \n", trans->eventType, event->eventType);
1263 // DEBUG_FSM("- invalid type %d(model) == %d(iml)\n", trans->eventType, event->eventType);
1267 // DEBUG_FSM("eventtype == %d - don't care\n", trans->eventType);
1272 /* check the digest */
1273 if (trans->digestFlag == DIGEST_FLAG_EQUAL) {
1274 // DEBUG_FSM("digest -");
1275 if (!memcmp(trans->digest,
1277 event->ulPcrValueLength)) {
1280 // DEBUG_FSM("- valid\n");
1283 // DEBUG_FSM("- invalid\n");
1285 } else if (trans->digestFlag == DIGEST_FLAG_IGNORE ||
1286 trans->digestFlag == DIGEST_FLAG_TRANSPARENT) {
1287 /* Behavior Model */
1288 // DEBUG_FSM("digest - ignore\n");
1291 // DEBUG_FSM("digest - don't care\n");
1296 /* check the counter */
1297 fatal_counter_check = 3;
1298 if (trans->fatal_counter_flag == COUNTER_FLAG_LT) {
1300 int fatal_count = getCountFromProperty(ctx, trans->fatal_counter_name);
1302 if (fatal_count < 0) {
1303 LOG(LOG_ERR, "getCountFromProperty() fail");
1304 } else if (ctx->count < fatal_count) {
1305 DEBUG_FSM("FATAL COUNTER %d < %d - HIT\n", ctx->count, fatal_count);
1306 fatal_counter_check = 1; // HIT
1308 DEBUG_FSM("FATAL COUNTER %d < %d - MISS\n", ctx->count, fatal_count);
1309 fatal_counter_check = -1; // MISS
1311 } else if (trans->fatal_counter_flag == COUNTER_FLAG_GE) {
1313 int fatal_count = getCountFromProperty(ctx, trans->fatal_counter_name);
1315 // TODO at this moment we ignore >= condition,
1316 if (fatal_count < 0) {
1317 LOG(LOG_ERR, "getCountFromProperty() fail");
1318 } else if (ctx->count >= fatal_count) {
1319 DEBUG_FSM("FATAL COUNTER %d >= %d - HIT\n", ctx->count, fatal_count);
1320 fatal_counter_check = 1; // HIT
1322 DEBUG_FSM("FATAL COUNTER %d >= %d - MISS\n", ctx->count, fatal_count);
1323 fatal_counter_check = -1; // MISS
1326 // DEBUG_FSM("counter - don't care\n");
1329 if (trans->counter_flag != COUNTER_FLAG_SKIP) {
1330 int thisCount = 1 + trans->event_num;
1331 int maxCount = getCountFromProperty(ctx, trans->counter_name);
1333 LOG(LOG_ERR, "getCountFromProperty() fail, trans->counter_flag=%d", trans->counter_flag);
1334 } else if (trans->counter_flag == COUNTER_FLAG_GE &&
1335 thisCount >= maxCount) {
1336 DEBUG_FSM("DIGEST COUNTER %d >= %d ('%s') - digest is transparent\n",
1337 thisCount, maxCount, trans->counter_name);
1338 eventWrapper->transparent = 1;
1339 } else if (trans->counter_flag == COUNTER_FLAG_LT &&
1340 thisCount < maxCount) {
1341 DEBUG_FSM("DIGEST COUNTER %d < %d ('%s') - digest is transparent\n",
1342 thisCount, maxCount, trans->counter_name);
1343 eventWrapper->transparent = 1;
1348 // if ((type_check == 1) && (digest_check == 1)) {
1349 if ((type_check > 0) &&
1350 (digest_check > 0) &&
1351 (fatal_counter_check > 0) &&
1353 /* Hit this Trans */
1354 /* If Final state, switch to next snapshot */
1355 if (!strcmp(trans->target, UML2_SD_FINAL_STATE_STRING)) {
1357 DEBUG_FSM("\tPCR[%d] level %d, Final state!! move to the next snapshot\n",
1358 fsm->pcr_index, fsm->level);
1359 // LOG(LOG_ERR, "PCR[%d] level %d, Final\n", fsm->pcr_index, fsm->level);
1360 fsm->status = OPENPTS_FSM_FINISH;
1361 return OPENPTS_FSM_FINISH_WO_HIT; // FINAL
1364 /* create FSM-IML link */
1365 eventWrapper->fsm_trans = trans;
1366 trans->event = (void *) event; // note) hold the last link of looped trans
1367 trans->event_num++; // # of shared trans > 1
1368 DEBUG_FSM("[RM%02d-PCR%02d] trans->event_num = %d\n",
1369 fsm->level, fsm->pcr_index, (int)trans->event_num);
1373 if (dont_care == 2) {
1374 // this transfer does not feed event,
1375 // just move to next state and check again
1376 DEBUG_FSM("[RM%02d-PCR%02d] '%s' -> '%s'\n",
1377 fsm->level, fsm->pcr_index,
1378 trans->source, trans->target);
1379 fsm->curr_state = getSubvertex(fsm, trans->target);
1381 if (fsm->curr_state != NULL) {
1382 /* doActivity, update properties */
1383 rc = doActivity(ctx, (char *)fsm->curr_state->action, NULL); // action.c
1384 if (rc == OPENPTS_FSM_FLASH) {
1385 /* last event, Flash FSM */
1386 DEBUG_FSM("\t\tFlash FSM (don't care trans)\n");
1388 rc = updateFsm(ctx, fsm, NULL);
1390 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1391 rc = OPENPTS_FSM_FINISH;
1393 LOG(LOG_ERR, "flash FSM was failed\n");
1394 rc = OPENPTS_FSM_ERROR;
1396 } else if (rc == OPENPTS_FSM_TRANSIT) {
1398 DEBUG_FSM("\t\tFlash FSM before transit \n");
1400 rc = updateFsm(ctx, fsm, NULL); // flash FSM
1402 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1403 rc = OPENPTS_FSM_TRANSIT;
1405 LOG(LOG_ERR, "updateFsm - FSM did not finish\n");
1406 rc = OPENPTS_FSM_ERROR;
1408 } else if (rc == OPENPTS_FSM_ERROR) {
1409 DEBUG("updateFsm - doActivity error\n");
1410 // INFO("FSM validation of doActivity() was failed.
1411 // (FSM state = %s)\n",fsm->curr_state->name);
1412 addReason(ctx, fsm->pcr_index, NLS(MS_OPENPTS, OPENPTS_FSM_ACTION_FAILED,
1413 "[PCR%02d-FSM] The action '%s' failed at state '%s'"),
1414 fsm->pcr_index, (char *)fsm->curr_state->action, fsm->curr_state->name);
1416 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1417 LOG(LOG_TODO, "updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1419 } else if (rc == OPENPTS_FSM_SUCCESS) {
1420 rc = updateFsm(ctx, fsm, eventWrapper);
1422 LOG(LOG_TODO, "rc = %d\n", rc);
1423 rc = updateFsm(ctx, fsm, eventWrapper);
1429 DEBUG_FSM("[RM%02d-PCR%02d] %s -> %s - HIT (type=%d, digest=%d)\n",
1430 fsm->level, fsm->pcr_index,
1433 type_check, digest_check);
1434 fsm->curr_state = getSubvertex(fsm, trans->target);
1436 if (fsm->curr_state != NULL) {
1437 /* doActivity, update properties */
1438 rc = doActivity(ctx, (char *)fsm->curr_state->action, eventWrapper); // action.c
1439 if (rc == OPENPTS_FSM_FLASH) {
1440 /* last event, Flash FSM */
1441 DEBUG_FSM("[RM%02d-PCR%02d] Flash this FSM\n",
1442 fsm->level, fsm->pcr_index);
1444 rc = updateFsm(ctx, fsm, NULL);
1446 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1447 rc = OPENPTS_FSM_FINISH;
1449 LOG(LOG_ERR, "updateFsm - flash FSM was failed, rc = %d\n", rc);
1450 rc = OPENPTS_FSM_ERROR;
1452 } else if (rc == OPENPTS_FSM_TRANSIT) {
1454 DEBUG_FSM("\t\tFlash FSM before transit \n");
1456 rc = updateFsm(ctx, fsm, NULL);
1458 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1459 rc = OPENPTS_FSM_TRANSIT;
1461 LOG(LOG_ERR, "updateFsm - FSM did not finish\n");
1462 rc = OPENPTS_FSM_ERROR;
1464 } else if (rc == OPENPTS_FSM_ERROR) {
1465 LOG(LOG_ERR, "updateFsm - FSM doActivity False, rc = %d\n", rc);
1467 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1468 // DEBUG("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1470 } else if (rc == OPENPTS_FSM_SUCCESS) {
1471 rc = OPENPTS_FSM_SUCCESS;
1474 // DEBUG("rc = %d -> 0\n"); // fsm.c:1070 rc = 6 -> 0
1475 rc = OPENPTS_FSM_SUCCESS;
1478 LOG(LOG_ERR, "curr_state is NULL, missing %s\n", trans->target);
1479 rc = OPENPTS_FSM_ERROR;
1488 trans = trans->next;
1494 // 20101118 SM Reason generated at iml.c
1495 DEBUG_FSM("[RM%02d-PCR%02d] No transition => rc = OPENPTS_FSM_ERROR\n",
1496 fsm->level, fsm->pcr_index);
1498 rc = OPENPTS_FSM_ERROR;
1513 OPENPTS_FSM_CONTEXT *copyFsm(OPENPTS_FSM_CONTEXT *src_fsm) {
1514 OPENPTS_FSM_CONTEXT * dst_fsm = NULL;
1516 OPENPTS_FSM_Subvertex *src_fsm_sub;
1517 OPENPTS_FSM_Subvertex *dst_fsm_sub = NULL;
1518 OPENPTS_FSM_Subvertex *dst_fsm_sub_prev = NULL;
1520 OPENPTS_FSM_Transition *src_fsm_trans;
1521 OPENPTS_FSM_Transition *dst_fsm_trans = NULL;
1522 OPENPTS_FSM_Transition *dst_fsm_trans_prev = NULL;
1526 DEBUG_FSM("copyFsm - start, PCR[%d]\n", src_fsm->pcrIndex);
1529 if (src_fsm == NULL) {
1530 DEBUG("src_fsm == NULL, SKIP COPY\n");
1535 dst_fsm = (OPENPTS_FSM_CONTEXT *) xmalloc(sizeof(OPENPTS_FSM_CONTEXT));
1536 if (dst_fsm == NULL) {
1539 memcpy((void *)dst_fsm, (void *)src_fsm, sizeof(OPENPTS_FSM_CONTEXT));
1541 /* delete BHV-FSM smalloc link */
1542 dst_fsm->uml_file = NULL;
1544 /* Copy Subvertexs */
1546 src_fsm_sub = src_fsm->fsm_sub;
1547 if (src_fsm_sub == NULL) {
1548 LOG(LOG_ERR, "ERROR No FSM SUB\n");
1552 while (src_fsm_sub != NULL) {
1553 /* malloc new sub */
1554 dst_fsm_sub = (OPENPTS_FSM_Subvertex *)
1555 xmalloc_assert(sizeof(OPENPTS_FSM_Subvertex));
1557 memcpy((void *)dst_fsm_sub,
1558 (void *)src_fsm_sub,
1559 sizeof(OPENPTS_FSM_Subvertex));
1562 if (dst_fsm_sub_prev != NULL) { // 2nd-
1563 dst_fsm_sub_prev->next = dst_fsm_sub;
1564 dst_fsm_sub->prev = dst_fsm_sub_prev;
1566 dst_fsm->fsm_sub = dst_fsm_sub;
1568 dst_fsm_sub_prev = dst_fsm_sub;
1571 dst_fsm_sub->link = src_fsm_sub;
1572 src_fsm_sub->link = dst_fsm_sub;
1575 src_fsm_sub = src_fsm_sub->next;
1579 DEBUG_FSM("%d Subvertex was copied\n", count);
1581 /* Copy Transitions */
1583 src_fsm_trans = src_fsm->fsm_trans;
1585 if (src_fsm_trans == NULL) {
1586 LOG(LOG_ERR, "ERROR No FSM TRANS\n");
1590 while (src_fsm_trans != NULL) {
1591 /* malloc new sub */
1592 dst_fsm_trans = (OPENPTS_FSM_Transition *)
1593 xmalloc_assert(sizeof(OPENPTS_FSM_Transition));
1595 memcpy((void *)dst_fsm_trans,
1596 (void *)src_fsm_trans,
1597 sizeof(OPENPTS_FSM_Transition));
1600 if (dst_fsm_trans_prev != NULL) { // 2nd-
1601 dst_fsm_trans_prev->next = dst_fsm_trans;
1602 dst_fsm_trans->prev = dst_fsm_trans_prev;
1604 dst_fsm->fsm_trans = dst_fsm_trans;
1606 dst_fsm_trans_prev = dst_fsm_trans;
1608 /* links to sub, Start and Final */
1609 // TODO(munetoh) does NULL check need?
1610 src_fsm_sub = src_fsm_trans->source_subvertex;
1611 if (src_fsm_sub != NULL) {
1612 dst_fsm_trans->source_subvertex = src_fsm_sub->link;
1614 LOG(LOG_ERR, "ERROR BHV trans %s source_subvertex is NULL\n",
1615 src_fsm_trans->source);
1618 src_fsm_sub = src_fsm_trans->target_subvertex;
1620 if (src_fsm_sub != NULL)
1621 dst_fsm_trans->target_subvertex = src_fsm_sub->link;
1623 /* link between BIN and BHV FSM */
1624 dst_fsm_trans->link = src_fsm_trans;
1625 src_fsm_trans->link = dst_fsm_trans;
1628 src_fsm_trans = src_fsm_trans->next;
1632 DEBUG_FSM("%d Transition was copied\n", count);
1633 DEBUG_FSM("copyFsm - done\n");
1638 if (dst_fsm != NULL) {
1648 S ----T--->New_Sub(--->Old_Sub)
1658 A---T---BN B--C << NG
1662 int changeTargetSubvertex(
1663 OPENPTS_FSM_CONTEXT *fsm_ctx,
1664 OPENPTS_FSM_Subvertex *old_sub, // B
1665 OPENPTS_FSM_Subvertex *new_sub) { // BN
1667 OPENPTS_FSM_Transition *fsm_trans;
1671 if (fsm_ctx == NULL) {
1672 LOG(LOG_ERR, "null input");
1675 if (old_sub == NULL) {
1676 LOG(LOG_ERR, "null input");
1679 if (new_sub == NULL) {
1680 LOG(LOG_ERR, "null input");
1685 fsm_trans = fsm_ctx->fsm_trans;
1687 /* check all trans to B */
1688 while (fsm_trans != NULL) {
1689 if (fsm_trans->target_subvertex == old_sub) {
1690 fsm_trans->target_subvertex = new_sub;
1691 snprintf(fsm_trans->target,
1692 sizeof(fsm_trans->target),
1695 fsm_trans = fsm_trans->next;
1706 S ----T--->New_Sub(--->Old_Sub)
1715 A---T---BN B--C << OK
1719 int changeTransTargetSubvertex(
1720 OPENPTS_FSM_CONTEXT *fsm_ctx,
1721 OPENPTS_FSM_Subvertex *old_sub, // B
1722 OPENPTS_FSM_Subvertex *new_sub) { // BN
1724 OPENPTS_FSM_Transition *fsm_trans;
1728 if (fsm_ctx == NULL) {
1729 LOG(LOG_ERR, "null input");
1732 if (old_sub == NULL) {
1733 LOG(LOG_ERR, "null input");
1736 if (new_sub == NULL) {
1737 LOG(LOG_ERR, "null input");
1742 fsm_trans = fsm_ctx->fsm_trans;
1744 /* check all trans to B */
1745 while (fsm_trans != NULL) {
1746 if (fsm_trans->target_subvertex == old_sub) {
1748 if (fsm_trans->target_subvertex == fsm_trans->source_subvertex) {
1749 // LOOP, belong to old sub
1750 DEBUG_FSM("changeTransTargetSubvertex - keep loop '%s) \n",
1754 fsm_trans->target_subvertex = new_sub;
1755 snprintf(fsm_trans->target,
1756 sizeof(fsm_trans->target),
1758 DEBUG_FSM("changeTransTargetSubvertex - trans move to new sub (%s -> %s)\n",
1759 fsm_trans->source, fsm_trans->target);
1762 fsm_trans = fsm_trans->next;
1777 FSM [A]---Ta---[B]---Tc---[C]
1783 FSM [A]---Ta---[B]---Tb---[B]---Tc---[C]
1788 Transfer Behavior to Binary FSM
1792 FSM [A]---Ta---[B0]---Tb0--[B]---Tb---[B]---Tc---[C]
1798 FSM [A]---Ta---[B0]---Tb0--[B1]---tb1--[B]---Tb---[B]---Tc---[C]
1804 FSM [A]---Ta---[B0]---Tb0--[B1]---tb1--[B2]---Tb---[B]---Tc---[C]
1812 OPENPTS_FSM_CONTEXT *fsm_ctx, // BIN-FSM
1813 OPENPTS_FSM_Transition *fsm_trans, // target Trans
1814 OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
1816 OPENPTS_FSM_Subvertex *prev_sub; // STRUCT LINK
1817 OPENPTS_FSM_Subvertex *new_sub;
1818 OPENPTS_FSM_Subvertex *dst_sub;
1819 OPENPTS_FSM_Transition *prev_trans; // STRUCT LINK
1820 OPENPTS_FSM_Transition *new_trans;
1821 TSS_PCR_EVENT *event;
1823 DEBUG_FSM("insertFsm - start\n");
1826 if (fsm_ctx == NULL) {
1827 LOG(LOG_ERR, "null input");
1830 if (fsm_trans == NULL) {
1831 LOG(LOG_ERR, "null input");
1834 if (eventWrapper == NULL) {
1835 LOG(LOG_ERR, "null input");
1838 event = eventWrapper->event;
1839 if (event == NULL) {
1840 LOG(LOG_ERR, "null input");
1844 if (fsm_trans->source_subvertex == NULL) {
1845 LOG(LOG_ERR, "ERROR fsm_trans->source_subvertex == NULL, %s -> %s\n",
1846 fsm_trans->source, fsm_trans->target);
1849 if (fsm_trans->target_subvertex == NULL) {
1850 LOG(LOG_ERR, "ERROR fsm_trans->target_subvertex == NULL\n");
1856 if (fsm_trans->source_subvertex == fsm_trans->target_subvertex) {
1857 /* OK, this is LOOP, */
1858 DEBUG_FSM("Loop (%s->%s) has %d events\n",
1859 fsm_trans->source, fsm_trans->target, fsm_trans->event_num);
1861 /* Base subvertex, B */
1862 dst_sub = fsm_trans->target_subvertex;
1864 /* Add new subvertex, BN (->B) */
1866 new_sub = (OPENPTS_FSM_Subvertex *)
1867 xmalloc(sizeof(OPENPTS_FSM_Subvertex));
1868 if (new_sub == NULL) {
1873 fsm_trans->source_subvertex,
1874 sizeof(OPENPTS_FSM_Subvertex));
1876 snprintf(new_sub->id, sizeof(new_sub->id),
1878 dst_sub->id, fsm_trans->copy_num);
1879 snprintf(new_sub->name, sizeof(new_sub->name),
1881 dst_sub->name, fsm_trans->copy_num);
1882 fsm_ctx->subvertex_num++;
1884 /* Update the subvetex chain, A-B => A-BN-B */
1887 prev_sub = dst_sub->prev;
1888 prev_sub->next = new_sub;
1889 new_sub->prev = prev_sub;
1892 new_sub->next = dst_sub;
1893 dst_sub->prev = new_sub;
1895 /* Any trans to B move to BN */
1896 // BN->B trans is open
1897 rc = changeTransTargetSubvertex(
1902 DEBUG_FSM("\tnew sub id = %s, name = %s added\n",
1903 new_sub->id, new_sub->name);
1905 /*Next Updatre the Transition */
1907 if (fsm_trans->event_num > 1) {
1908 /* Many loops, B-B -> BN-B-B, add new Trans between BN and B */
1911 new_trans = (OPENPTS_FSM_Transition*)
1912 xmalloc(sizeof(OPENPTS_FSM_Transition));
1913 if (new_trans == NULL) {
1919 sizeof(OPENPTS_FSM_Transition));
1921 /* update the transition struct chain */
1923 prev_trans = fsm_trans->prev;
1924 prev_trans->next = new_trans;
1925 new_trans->prev = prev_trans;
1927 new_trans->next = fsm_trans;
1928 fsm_trans->prev = new_trans;
1930 fsm_ctx->transition_num++;
1932 /* Update new Trans */
1933 new_trans->source_subvertex = new_sub;
1934 snprintf(new_trans->source, sizeof(new_trans->source),
1937 new_trans->target_subvertex = dst_sub;
1938 snprintf(new_trans->target, sizeof(new_trans->target),
1941 /* Update event link */
1943 new_trans->event = eventWrapper; // TSS_PCR_EVENT_WRAPPER
1944 new_trans->event_num = 1;
1946 eventWrapper->fsm_trans = new_trans;
1948 /* Update Original Trans */
1949 fsm_trans->event_num--;
1950 fsm_trans->copy_num++;
1952 /* Copy digest value to trans */
1953 if (0 == eventWrapper->transparent) {
1954 new_trans->digestFlag = DIGEST_FLAG_EQUAL;
1955 new_trans->digestSize = event->ulPcrValueLength;
1956 new_trans->digest = xmalloc(event->ulPcrValueLength);
1957 if (new_trans->digest == NULL) {
1960 memcpy(new_trans->digest, event->rgbPcrValue, event->ulPcrValueLength);
1962 DEBUG_FSM("Changing digestFlag == DIGEST_FLAG_TRANSPARENT\n");
1963 new_trans->digestFlag = DIGEST_FLAG_TRANSPARENT;
1966 DEBUG_FSM("new Trans BIN(%s -> %s)\n",
1967 new_trans->source, new_trans->target);
1968 DEBUG_FSM("orig Trans BIN(%s -> %s) share = %d\n",
1969 fsm_trans->source, fsm_trans->target, fsm_trans->event_num);
1971 } else if (fsm_trans->event_num == 1) {
1972 /* Last loop, B-B -> BN-B, just update the trans */
1974 /* Update new Trans */
1975 fsm_trans->source_subvertex = new_sub;
1976 snprintf(fsm_trans->source, sizeof(new_trans->source),
1979 /* Copy digest value to FSM */
1980 if (0 == eventWrapper->transparent) {
1981 fsm_trans->digestFlag = DIGEST_FLAG_EQUAL;
1982 fsm_trans->digestSize = event->ulPcrValueLength;
1983 fsm_trans->digest = xmalloc(event->ulPcrValueLength);
1984 if (fsm_trans->digest == NULL) {
1987 memcpy(fsm_trans->digest, event->rgbPcrValue, event->ulPcrValueLength);
1989 fsm_trans->digestFlag = DIGEST_FLAG_TRANSPARENT;
1992 // DEBUG_FSM("\tupdate Trans %p->%p->%p\n",
1993 // fsm_trans->prev, fsm_trans, fsm_trans->next);
1994 DEBUG_FSM("\tUpdate Trans BIN(%s -> %s)\n",
1995 fsm_trans->source, fsm_trans->target);
1997 LOG(LOG_ERR, "BAD LOOP");
2001 LOG(LOG_ERR, "Not a loop");
2005 DEBUG_FSM("insertFsm - done\n");
2011 * remove the trans from transition chain
2014 OPENPTS_FSM_CONTEXT *fsm_ctx,
2015 OPENPTS_FSM_Transition * trans) {
2017 OPENPTS_FSM_Transition * trans_prev;
2018 OPENPTS_FSM_Transition * trans_next;
2021 if (fsm_ctx == NULL) {
2022 LOG(LOG_ERR, "null input");
2025 if (trans == NULL) {
2026 LOG(LOG_ERR, "null input");
2031 trans_prev = trans->prev;
2032 trans_next = trans->next;
2035 if (trans_prev != NULL) {
2036 trans_prev->next = trans_next;
2037 } else { // 1st trans
2038 fsm_ctx->fsm_trans = trans_next;
2041 if (trans_next != NULL) {
2042 trans_next->prev = trans_prev;
2043 } else { // last trans
2052 * remove FSM subvertex
2055 OPENPTS_FSM_CONTEXT *fsm_ctx,
2056 OPENPTS_FSM_Subvertex * sub) {
2058 OPENPTS_FSM_Subvertex * sub_prev;
2059 OPENPTS_FSM_Subvertex * sub_next;
2062 if (fsm_ctx == NULL) {
2063 LOG(LOG_ERR, "null input");
2067 LOG(LOG_ERR, "null input");
2072 sub_prev = sub->prev;
2073 sub_next = sub->next;
2076 if (sub_prev != NULL) {
2077 sub_prev->next = sub_next;
2079 fsm_ctx->fsm_sub = sub_next;
2081 if (sub_next != NULL) {
2082 sub_next->prev = sub_prev;
2083 } else { // last sub
2087 // TODO(munetoh) Free
2094 * - delete unused BHV Transitions
2095 * - delete unused BHV Subvertex
2098 int cleanupFsm(OPENPTS_FSM_CONTEXT *fsm_ctx) {
2102 OPENPTS_FSM_Transition * trans;
2103 OPENPTS_FSM_Transition * trans_next;
2104 OPENPTS_FSM_Subvertex * sub;
2105 OPENPTS_FSM_Subvertex * sub_next;
2108 if (fsm_ctx == NULL) {
2109 LOG(LOG_ERR, "null input");
2113 DEBUG_FSM("cleanupFsm - start, PCR[%d]\n", fsm_ctx->pcrIndex);
2115 /* Delete BHV Transitions */
2117 trans = fsm_ctx->fsm_trans;
2119 if (trans == NULL) {
2120 LOG(LOG_ERR, "ERROR No FSM TRANS\n");
2125 while (trans != NULL) {
2126 trans_next = trans->next;
2127 if (trans->digestFlag == DIGEST_FLAG_IGNORE) {
2128 DEBUG_FSM("\tHIT %s->%s - removed\n",
2129 trans->source, trans->target);
2130 rc = removeFsmTrans(fsm_ctx, trans); // remove Trans
2132 LOG(LOG_ERR, "removeFsmTrans of %s -> %s was failed\n",
2133 trans->source, trans->target);
2138 // printf("MISS \n");
2143 DEBUG_FSM("cleanupFsm - %d trans was removed\n", count);
2144 fsm_ctx->transition_num -= count;
2146 /* Delete state which does not have incomming trans */
2147 sub = fsm_ctx->fsm_sub;
2149 LOG(LOG_ERR, "ERROR No FSM SUB\n");
2154 while (sub != NULL) {
2155 sub_next = sub->next;
2156 if (!strcmp(sub->id, "Start")) {
2158 } else if (!strcmp(sub->id, "Final")) {
2163 trans = fsm_ctx->fsm_trans;
2165 while (trans != NULL) {
2166 if (!strcmp(trans->target, sub->id)) {
2168 if (trans->target_subvertex == sub) {
2171 // EV_S_CRTM_VERSION is not detected. BAD link:-(
2174 // printf("ERROR BAD LINK\n");
2175 // printf("SUB id=%s name=%s \n",
2176 // sub->id,sub->name);
2177 // printf("TRANS %s -> %s \n",
2178 // trans->source,trans->target);
2181 trans = trans->next;
2185 DEBUG_FSM("\tSub %p id=%s name=%s not used\n",
2186 sub, sub->id, sub->name);
2188 removeFsmSub(fsm_ctx, sub);
2195 DEBUG_FSM("cleanupFsm - %d trans was removed\n", count);
2196 fsm_ctx->subvertex_num -= count;
2199 /* Again, Delete trans which does not have source target */
2201 trans = fsm_ctx->fsm_trans;
2203 if (trans == NULL) {
2204 LOG(LOG_ERR, "No FSM TRANS\n");
2209 while (trans != NULL) {
2210 trans_next = trans->next;
2212 sub = getSubvertex(fsm_ctx, trans->source);
2214 DEBUG_FSM("\tMISSING SOURCE %s->%s\n",
2215 trans->source, trans->target);
2216 removeFsmTrans(fsm_ctx, trans);
2225 DEBUG_FSM("cleanupFsm - %d trans was removed - missing source\n", count);
2226 fsm_ctx->transition_num -= count;
2229 DEBUG_FSM("cleanupFsm - done\n");
2234 * write DOT State Diagram for Graphviz
2235 * dot -Tpng tests/bios_pcr0.dot -o tests/bios_pcr0.png; eog tests/bios_pcr0.png
2236 * @param ctx FSM_CONTEXT
2237 * @param filename dot filename to write
2242 * PTS_INTERNAL_ERROR
2244 int writeDotModel(OPENPTS_FSM_CONTEXT *ctx, char * filename) {
2245 int rc = PTS_SUCCESS;
2248 OPENPTS_FSM_Subvertex *sptr;
2249 OPENPTS_FSM_Transition *ptr;
2251 DEBUG("writeDotModel - start %s\n", filename);
2255 LOG(LOG_ERR, "null input");
2259 if (filename == NULL) {
2262 if ((fp = fopen(filename, "w")) == NULL) {
2263 LOG(LOG_ERR, "fopen fail %s\n", filename);
2264 return PTS_OS_ERROR;
2268 DEBUG_FSM("Subvertex num= %d \n", ctx->subvertex_num);
2269 DEBUG_FSM("Transition num= %d \n", ctx->transition_num);
2271 fprintf(fp, "digraph G {\n");
2276 while (sptr != NULL) {
2277 if (!strcmp(sptr->id, "Start")) {
2278 fprintf(fp, "\t%s [label =\"\", fillcolor=black];\n", sptr->id);
2279 // TODO(munetoh) fillcolor not work
2280 } else if (!strcmp(sptr->id, "Final")) {
2281 fprintf(fp, "\t%s [label =\"\", peripheries = 2];\n", sptr->id);
2282 } else if (strlen(sptr->action) > 0) {
2283 fprintf(fp, "\t%s [label=\"%s\\naction=%s\"];\n",
2288 fprintf(fp, "\t%s [label=\"%s\"];\n",
2296 ptr = ctx->fsm_trans;
2298 while (ptr != NULL) {
2299 DEBUG_FSM("\tTransition = (%s->%s)\n", ptr->source, ptr->target);
2301 if (ptr->digestFlag == DIGEST_FLAG_EQUAL) { // BIN
2302 fprintf(fp, "\t%s -> %s [label=\"",
2306 if (ptr->eventTypeFlag == EVENTTYPE_FLAG_EQUAL) {
2307 fprintf(fp, "eventtype == 0x%x, ", ptr->eventType);
2308 } else if (ptr->eventTypeFlag == EVENTTYPE_FLAG_NOT_EQUAL) {
2309 fprintf(fp, "eventtype != 0x%x, ", ptr->eventType);
2312 fprintf(fp, "\\nhexdigest == ");
2313 for (j = 0; j < ptr->digestSize; j++) {
2314 fprintf(fp, "%02x", ptr->digest[j]);
2315 // TODO(munetoh) Hex, also supports Base64
2317 fprintf(fp, "\"];\n");
2319 fprintf(fp, "\t%s -> %s [label=\"%s\"];\n",
2331 DEBUG("writeDotModel - done\n");
2337 * write CSV file, RFC 4180 style
2339 * @param ctx FSM_CONTEXT
2340 * @param filename csv filename to write
2342 int writeCsvTable(OPENPTS_FSM_CONTEXT *ctx, char * filename) {
2346 OPENPTS_FSM_Transition *ptr;
2350 LOG(LOG_ERR, "null input");
2353 if (filename == NULL) {
2354 LOG(LOG_ERR, "writeCsvTable - filename is NULL\n");
2359 if ((fp = fopen(filename, "w")) == NULL) {
2364 "current state,condition type(hex), condition digest,next state\n");
2366 ptr = ctx->fsm_trans;
2367 for (i = 0; i < ctx->transition_num; i++) {
2368 fprintf(fp, "%s, ", getSubvertexName(ctx, ptr->source));
2370 if (ptr->eventTypeFlag == 1) {
2371 fprintf(fp, "type==0x%x,", ptr->eventType);
2372 } else if (ptr->eventTypeFlag == 1) {
2373 fprintf(fp, "type!=0x%x,", ptr->eventType);
2379 if (ptr->digestFlag == DIGEST_FLAG_EQUAL) {
2380 fprintf(fp, "digest==0x");
2381 // for (i=0;i<DIGEST_SIZE;i++) fprintf(fp,"%02x",ptr->digest[i]);
2383 } else if (ptr->digestFlag == DIGEST_FLAG_IGNORE) {
2384 fprintf(fp, "digest==base64!,");
2385 } else if (ptr->digestFlag == DIGEST_FLAG_TRANSPARENT) {
2386 fprintf(fp, "digest==transparent!,");
2390 fprintf(fp, "%s\n", getSubvertexName(ctx, ptr->target));
2402 * print FSM State Diagram
2404 * @param ctx FSM_CONTEXT
2406 int printFsmModel(OPENPTS_FSM_CONTEXT *ctx) {
2409 OPENPTS_FSM_Transition *ptr;
2413 LOG(LOG_ERR, "null input");
2417 OUTPUT(NLS(MS_OPENPTS, OPENPTS_PRINT_FSM_HEADER,
2418 "ctx->transition_num = %d\n"
2419 "trans\t\tcurrent state\t\t\tcondition\t\t\\ttnext state\n"
2420 " id \t\t\t\t\ttype(hex)\tdigest(hex)\n"), ctx->transition_num);
2421 OUTPUT("----------------------------------------------------------------------------------------------\n");
2424 ptr = ctx->fsm_trans;
2425 for (i = 0; i < ctx->transition_num; i++) {
2427 LOG(LOG_ERR, "PTR is NULL at %d\n", i);
2431 OUTPUT("%30s ", getSubvertexName(ctx, ptr->source));
2433 if (ptr->eventTypeFlag == 1) {
2434 OUTPUT(" 0x%08x ", ptr->eventType);
2435 } else if (ptr->eventTypeFlag == 1) {
2436 OUTPUT("!0x%08x ", ptr->eventType);
2441 if (ptr->digestFlag == DIGEST_FLAG_EQUAL) {
2443 for (j = 0; j < ptr->digestSize; j++) OUTPUT("%02x", ptr->digest[j]);
2445 } else if (ptr->digestFlag == DIGEST_FLAG_IGNORE) {
2446 OUTPUT(NLS(MS_OPENPTS, OPENPTS_PRINT_FSM_BASE64, "base64 "));
2447 } else if (ptr->digestFlag == DIGEST_FLAG_TRANSPARENT) {
2448 /* WORK NEEDED: say transparent here? */
2453 OUTPUT("%-30s\n", getSubvertexName(ctx, ptr->target));