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));
64 memset(ctx, 0 , sizeof(OPENPTS_FSM_CONTEXT));
66 ctx->fsm_trans = NULL;
69 ctx->subvertex_num = 0;
70 ctx->transition_num = 0;
75 * Free OPENPTS_FSM_Transition chain
77 void freeFsmTransitionChain(OPENPTS_FSM_Transition *fsm_trans) {
78 if (fsm_trans->next != NULL) {
79 freeFsmTransitionChain(fsm_trans->next);
83 if (fsm_trans->digest != NULL) {
84 xfree(fsm_trans->digest);
91 * Free OPENPTS_FSM_Subvertex chain
93 void freeFsmSubvertexChain(OPENPTS_FSM_Subvertex *fsm_sub) {
94 if (fsm_sub->next != NULL) {
95 freeFsmSubvertexChain(fsm_sub->next);
104 int freeFsmContext(OPENPTS_FSM_CONTEXT *ctx) {
105 ASSERT(NULL != ctx, "ctx is NULL\n");
108 if (ctx->fsm_trans != NULL) {
109 freeFsmTransitionChain(ctx->fsm_trans);
110 ctx->fsm_trans = NULL;
115 if (ctx->fsm_sub != NULL) {
116 freeFsmSubvertexChain(ctx->fsm_sub);
121 if (ctx->uml_file != NULL) {
122 xfree(ctx->uml_file);
123 ctx->uml_file = NULL;
134 * reset FSM subvertex
136 void resetFsmSubvertex(OPENPTS_FSM_CONTEXT *ctx) {
138 ctx->subvertex_num = 0;
142 * reset FSM transition
144 void resetFsmTransition(OPENPTS_FSM_CONTEXT *ctx) {
146 ctx->transition_num = 0;
151 * add FMS subvertex to context
153 void addFsmSubvertex(
154 OPENPTS_FSM_CONTEXT *ctx,
160 OPENPTS_FSM_Subvertex *ptr = NULL;
161 OPENPTS_FSM_Subvertex *ptr_pre = NULL;
163 DEBUG_CAL("addFsmSubvertex - %d \n", ctx->subvertex_num);
166 for (i = 0; i <= ctx->subvertex_num; i++) {
168 /* add new PENPTS_FSM_Subvertex */
169 DEBUG_FSM(" id=%s name=%s size=%d\n",
171 (int)sizeof(OPENPTS_FSM_Subvertex));
173 /* malloc OPENPTS_FSM_Subvertex */
174 ptr = (OPENPTS_FSM_Subvertex *)
175 xmalloc(sizeof(OPENPTS_FSM_Subvertex));
181 memset(ptr, 0, sizeof(OPENPTS_FSM_Subvertex));
182 /* setup new FSM_Subvertex */
183 memcpy(ptr->type, type, FSM_BUF_SIZE);
184 memcpy(ptr->id, id, FSM_BUF_SIZE);
185 memcpy(ptr->name, name, FSM_BUF_SIZE);
186 memcpy(ptr->action, action, FSM_BUF_SIZE);
189 ptr->num = ctx->subvertex_num;
190 ptr->incomming_num = 0;
192 if (ctx->subvertex_num == 0) { // first event
195 // NG must be Start event ctx->curr_state = ptr;
196 } else if (ptr_pre != NULL) {
197 ptr_pre->next = ptr; // else
201 xfree(ptr); // free last one
205 ctx->subvertex_num++;
214 * get Subvertex ptr by ID
216 OPENPTS_FSM_Subvertex * getSubvertex(OPENPTS_FSM_CONTEXT *ctx, char * id) {
217 OPENPTS_FSM_Subvertex *ptr;
219 if (!strcmp(id, "Final")) return NULL; // final state
223 while (ptr != NULL) {
224 if (!strcmp(id, ptr->id)) return ptr;
225 ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
231 * get Subvertex Name by ID
233 char * getSubvertexName(OPENPTS_FSM_CONTEXT *ctx, char * id) {
235 OPENPTS_FSM_Subvertex *ptr;
237 if (!strcmp(id, "Final")) return id;
240 for (i = 0;i <= ctx->subvertex_num; i++) {
241 if (!strcmp(id, ptr->id)) return ptr->name;
242 ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
249 * get Subvertex ID by Name
251 char * getSubvertexId(OPENPTS_FSM_CONTEXT *ctx, char * name) {
253 OPENPTS_FSM_Subvertex *ptr;
255 // if (!strcmp(id, "Final")) return id;
258 for (i = 0;i <= ctx->subvertex_num; i++) {
259 if (!strcmp(name, ptr->name)) return ptr->id;
260 ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
269 static char *skipWhiteSpace(char *str, int *len) {
270 char *cur = str, *end = str + *len;
281 static int isEndOfString(char *str) {
285 static char *skipParameter(char *str, int *len) {
286 char *cur = str, *end = str + *len;
299 * <body>eventtype == 0x01, digest == base64</body>
305 * Unit Test : check_fsm.c / test_getTypeFlag
308 int getTypeFlag(char * cond, UINT32 *eventtype) {
312 long int val; // TODO uint64_t? but build fail on i386 platform
316 loc = strstr(cond, "eventtype");
318 if (loc == NULL) { // miss
326 loc = skipWhiteSpace(loc, &len);
327 if (isEndOfString(loc)) {
333 ERROR("ERROR 001\n");
336 if ((loc[0] == '=') && (loc[1] == '=')) { // ==
338 } else if ((loc[0] == '!') && (loc[1] == '=')) { // ==
341 ERROR("ERROR 002 %c %c \n", loc[0], loc[1]);
342 return -1; // unknown operand
347 loc = skipWhiteSpace(loc, &len);
348 if (isEndOfString(loc)) {
353 // 20110117 Ubuntu i386, 0x80000002 => 7FFFFFFF, => use strtoll
355 if ((loc[0] == '0') && (loc[1] == 'x')) { // 0x HEX
356 val = strtoll(loc, NULL, 16);
357 *eventtype = (UINT32)val;
358 // DEBUG("strtol [%s] => %X => %X\n", loc,val,*eventtype);
362 val = strtoll(loc, NULL, 10);
363 *eventtype = (UINT32)val;
364 // DEBUG("strtol [%s] => %X => %X\n", loc,val, *eventtype);
371 * Parse condition string and setup an internal digest condition structure
375 * 1: valid (=binary model), return the digest => freed at freeFsmTransitionChain()
376 * 2: ignore now (=behavior model or ignored digests in binary model)
379 * Unit Test : check_fsm.c / test_getDigestFlag
381 * TODO STA may complain the memory leak againt *digest.
383 int getDigestFlag(char * cond, BYTE **digest, int *digest_size) {
384 char * loc; // loc at value
389 DEBUG_CAL("getDigestFlag -");
393 loc = strstr(cond, "digest");
394 if (loc == NULL) { // miss
396 return DIGEST_FLAG_SKIP;
402 loc = skipWhiteSpace(loc, &len);
403 if (isEndOfString(loc)) {
407 /* operation, "==" only */
409 ERROR("ERROR 001\n");
412 if ((loc[0] == '=') && (loc[1] == '=')) { // ==
415 ERROR("ERROR 002 [%c%c] not ==, (cond = %s)\n", loc[0], loc[1], cond);
416 return -1; // unknown operand
422 loc = skipWhiteSpace(loc, &len);
423 if (isEndOfString(loc)) {
427 /* digest == base64 (behavior model) */
429 loc2 = strstr(loc, "base64");
430 if (loc2 != NULL) { // HIT, temp
435 /* Base64 str -> BYTE[] */
438 SHA1_BASE64_DIGEST_SIZE,
441 ERROR("decodeBase64 fail");
447 // TODO buf_len >= SHA1_DIGEST_SIZE
448 *digest_size = SHA1_DIGEST_SIZE;
452 if (NULL != strstr(loc, "base64!")) { // HIT, temp
454 return DIGEST_FLAG_IGNORE;
455 } else if (NULL != strstr(loc, "base64")) { // HIT, temp
457 return DIGEST_FLAG_IGNORE;
458 } else if (NULL != strstr(loc, "transparent!")) {
459 /* we have been told to ignore this digest from the binary model */
460 /* and use the behaviour version instead */
461 return DIGEST_FLAG_TRANSPARENT;
464 /* Base64 str -> BYTE[] */
467 SHA1_BASE64_DIGEST_SIZE,
470 ERROR("decodeBase64 fail");
474 } else if (buf_len == SHA1_DIGEST_SIZE) {
476 *digest_size = SHA1_DIGEST_SIZE;
477 return DIGEST_FLAG_EQUAL; // 1
479 ERROR("getDigestFlag() - decodeBase64() was failed \n");
486 buf = (BYTE *) xmalloc(SHA1_DIGEST_SIZE + 1);
491 // TODO(munetoh) get len, "<"
492 rc = decodeBase64(buf, SHA1_DIGEST_SIZE + 1, (unsigned char *)loc, SHA1_BASE64_DIGEST_SIZE);
493 if (rc == SHA1_DIGEST_SIZE) {
494 // TODO(munetoh) digest size change by alg
495 // this code is SHA1 only
498 return DIGEST_FLAG_EQUAL;
500 ERROR("getDigestFlag() - decodeBase64() was failed \n");
512 * Parse condition string and setup an internal couter condition structure
517 * COUNTER_FLAG_SKIP 0: don't care
518 * COUNTER_FLAG_LT 1: < name
519 * COUNTER_FLAG_GTE 2: >= name
521 * Unit Test : check_fsm.c / test_getCounterFlag
523 int getCounterFlag(char *cond, char *name, char **flag) {
524 char * loc; // loc at value
525 char * loc2; // loc at flag
527 int rc = COUNTER_FLAG_SKIP;
531 ERROR("Null condition found");
535 ERROR("Null condition found");
541 loc = strstr(cond, name);
554 loc = skipWhiteSpace(loc, &len);
555 if (isEndOfString(loc)) {
556 goto error; //return -1;
559 /* operation, "<" ">=" only */
560 if ((len >= 2) && (loc[0] == 'l') && (loc[1] == 't')) { // <, lt
561 rc = COUNTER_FLAG_LT;
564 } else if ((len >= 2) && (loc[0] == 'l') && (loc[1] == 'e')) { // <=, le
565 rc = COUNTER_FLAG_LE;
568 } else if ((len >= 2) && (loc[0] == 'g') && (loc[1] == 't')) { // >, gt
569 rc = COUNTER_FLAG_GT;
572 } else if ((len >= 2) && (loc[0] == 'g') && (loc[1] == 'e')) { // >, gt
573 rc = COUNTER_FLAG_GE;
576 } else if ((len >= 2) && (loc[0] == '<') && (loc[1] == ' ')) { // <, lt
577 rc = COUNTER_FLAG_LT;
580 } else if ((len >= 2) && (loc[0] == '<') && (loc[1] == '=')) { // <=, le
581 rc = COUNTER_FLAG_LE;
584 } else if ((len >= 2) && (loc[0] == '>') && (loc[1] == ' ')) { // >, gt
585 rc = COUNTER_FLAG_GT;
588 } else if ((len >= 2) && (loc[0] == '>') && (loc[1] == '=')) { // >=
589 rc = COUNTER_FLAG_GE;
593 ERROR("unknown operand [%s]", &loc[0]);
594 goto error; //return -1;
597 loc = skipWhiteSpace(loc, &len);
598 if (isEndOfString(loc)) {
599 goto error; //return -1;
602 // TODO check the end, this code only support if counter is the last
604 loc2 = skipParameter(loc, &len);
605 param_len = loc2 - loc;
606 if (0 == param_len) {
607 /* we haven't moved along the string - no valid parameter found */
608 goto error; //return -1;
611 /* DEBUG_FSM("[%d][%s][%s]\n",len, loc, loc2); */
613 *flag = xmalloc(param_len + 1);
615 goto error; //return -1;
617 memset(*flag, 0, param_len + 1);
618 memcpy(*flag, loc, param_len);
621 DEBUG_FSM("getCounterFlag %s #=> %d %s\n", cond, rc, *flag);
626 ERROR("getCounterFlag(\"%s\",\"%s\") fail", cond, name);
633 * Parse condition string and setup an internal couter condition structure
639 * LAST_FLAG_SKIP 0: don't care
640 * LAST_FLAG_EQ 1: == last
641 * LAST_FLAG_NEQ 2: != last
643 * Unit Test : check_fsm.c / test_getCounterFlag
645 int getLastFlag(char * cond) {
646 char * loc; // loc at value
647 char * loc2; // loc at name
649 int rc = LAST_FLAG_SKIP;
652 loc = strstr(cond, "last");
656 return LAST_FLAG_SKIP;
659 // DEBUG("getLastFlag() - %s\n", cond);
665 loc = skipWhiteSpace(loc, &len);
666 if (isEndOfString(loc)) {
670 /* operation, "<" ">=" only */
671 if ((len >= 2) && (loc[0] == '=') && (loc[1] == '=')) {
676 } else if ((len >= 2) && (loc[0] == '!') && (loc[1] == '=')) {
682 // ERROR("ERROR 002 [%s] not >= \n", &loc[0];
683 return -1; // unknown operand
686 loc = skipWhiteSpace(loc, &len);
687 if (isEndOfString(loc)) {
696 // DEBUG("[%d][%s]\n",len, loc2);
697 if (!strncmp(loc2, "true", 4)) {
700 /* != true => false */
701 } else if (!strncmp(loc2, "false", 5)) {
702 // DEBUG("false %d\n",rc);
703 if (rc == LAST_FLAG_EQ) {
708 // DEBUG("false %d\n",rc);
710 ERROR("unknown value, %s\n", loc2);
714 // DEBUG("getLastFlag %s #=> %d\n",cond, rc);
729 int addFsmTransition(
730 OPENPTS_FSM_CONTEXT *ctx,
735 OPENPTS_FSM_Transition *ptr = NULL;
736 OPENPTS_FSM_Transition *ptr_pre = NULL;
738 DEBUG_CAL("addFsmTransition - start\n");
740 ptr = ctx->fsm_trans;
741 for (i = 0; i <= ctx->transition_num; i++) {
742 if (ptr == NULL) { // new
743 DEBUG_FSM(" src=%s -> dst=%s cond[%s] %d\n",
744 source, target, cond,
745 (int)sizeof(OPENPTS_FSM_Transition));
747 /* malloc OPENPTS_FSM_Transition */
748 ptr = (OPENPTS_FSM_Transition *)
749 xmalloc(sizeof(OPENPTS_FSM_Transition));
751 return PTS_INTERNAL_ERROR;
754 memset(ptr, 0, sizeof(OPENPTS_FSM_Transition));
755 memcpy(ptr->source, source, FSM_BUF_SIZE);
756 memcpy(ptr->target, target, FSM_BUF_SIZE);
757 ptr->num = ctx->transition_num;
759 ptr->eventTypeFlag = 0;
760 ptr->digestFlag = DIGEST_FLAG_SKIP;
761 } else if (cond[0] == 0) {
762 ptr->eventTypeFlag = 0;
763 ptr->digestFlag = DIGEST_FLAG_SKIP;
764 memcpy(ptr->cond, cond, FSM_BUF_SIZE);
766 // 0:don't care, 1:care
767 ptr->eventTypeFlag = getTypeFlag(cond, &ptr->eventType);
768 // 0:don't care, 1:care, 2:temp, 3:transparent
769 ptr->digestFlag = getDigestFlag(cond, &ptr->digest, &ptr->digestSize);
770 // 0:don't care, 1:<, 2:>=
771 ptr->counter_flag = getCounterFlag(cond, "digest_count", &ptr->counter_name);
772 if (ptr->counter_flag < 0) {
773 ERROR("getCounterFlag() fail (%s => %s [%s])", source, target, cond);
775 // 0:don't care, 1:<, 2:>=
776 ptr->fatal_counter_flag = getCounterFlag(cond, "fatal_count", &ptr->fatal_counter_name);
777 if (ptr->fatal_counter_flag < 0) {
778 ERROR("getCounterFlag() fail (%s => %s [%s])", source, target, cond);
780 // 0:don't care 1: ==last 2: != last
781 ptr->last_flag = getLastFlag(cond);
782 memcpy(ptr->cond, cond, FSM_BUF_SIZE);
784 /* subvertex link (ptr) */
785 ptr->source_subvertex = getSubvertex(ctx, ptr->source);
786 ptr->target_subvertex = getSubvertex(ctx, ptr->target);
788 if (DIGEST_FLAG_TRANSPARENT == ptr->digestFlag) {
789 DEBUG_FSM("Found transparent digest\n");
790 ctx->numTransparencies++;
795 if (ctx->transition_num == 0) {
796 ctx->fsm_trans = ptr;
797 ptr->prev = NULL; // first trans
798 } else if (ptr_pre != NULL) {
801 ptr->next = NULL; // last trans
804 xfree(ptr); // free last one
805 return PTS_INTERNAL_ERROR;
807 ctx->transition_num++;
813 ptr = (OPENPTS_FSM_Transition *)ptr->next;
817 return PTS_INTERNAL_ERROR;
822 * get Event String (malloc) - obsolete function
824 char *getEventString(OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
826 int size = FSM_BUF_SIZE; // TODO fixed size
827 TSS_PCR_EVENT *event;
837 event = eventWrapper->event;
839 // len = snprintf(buf, size, "PCR[%d],TYPE=%d", (int)event->ulPcrIndex, event->eventType);
841 ERROR("NULL event\n"); // TODO(munetoh)
851 * get counter(int) value from property
857 * 1 : missing, invalid (e.g. minus)
860 int getCountFromProperty(OPENPTS_CONTEXT *ctx, char * name) {
861 int count = 0; // TODO get from prop
862 OPENPTS_PROPERTY *prop;
866 ERROR("ctx == NULL");
870 ERROR("name == NULL");
875 prop = getProperty(ctx, name);
877 /* Hit use this properties */
878 count = atoi(prop->value);
879 DEBUG_FSM("getCountFromProperty - prop %s = %d\n", name, count);
881 DEBUG("getCountFromProperty - prop %s is %d < 0. set count to 1\n", count, name);
887 DEBUG("getCountFromProperty - prop %s is missing. set count to 1\n", name);
894 * Drive FSM Transition by Event
896 * @parm eventWrapper NULL, push the FSM until Final state
902 * OPENPTS_FSM_SUCCESS
904 * OPENPTS_FSM_FINISH reach Final State, move to the next snapshot(=model)
905 * OPENPTS_FSM_TRANSIT transit to next FSM
906 * OPENPTS_FSM_ERROR_LOOP
908 * if eventWrapper is NULL, create and use dummy event
911 OPENPTS_CONTEXT *ctx,
912 OPENPTS_FSM_CONTEXT *fsm,
913 OPENPTS_PCR_EVENT_WRAPPER *eventWrapper
915 int rc = OPENPTS_FSM_SUCCESS;
916 OPENPTS_FSM_Subvertex *curr_state = fsm->curr_state;
917 OPENPTS_FSM_Transition *trans = fsm->fsm_trans;
918 TSS_PCR_EVENT *event;
921 int fatal_counter_check;
926 OPENPTS_FSM_Transition *hit_trans = NULL;
928 DEBUG_CAL("updateFsm - start\n");
930 if (curr_state == NULL) {
931 DEBUG_FSM("[RM%02d-PCR%02d] updateFsm() - curr_state == NULL => set the FSM state to 'Start'\n",
932 fsm->level, fsm->pcr_index);
933 curr_state = getSubvertex(fsm, "Start");
936 /* Null event -> push FSM until Final state */
937 // TODO(munetoh) dummy event does not need event. just add flag to the wrapper
938 if (eventWrapper == NULL) {
939 DEBUG_FSM("[RM%02d-PCR%02d] create dummy event to flash the FSM\n",
940 fsm->level, fsm->pcr_index);
943 eventWrapper = (OPENPTS_PCR_EVENT_WRAPPER *)
944 xmalloc_assert(sizeof(OPENPTS_PCR_EVENT_WRAPPER));
945 memset(eventWrapper, 0, sizeof(OPENPTS_PCR_EVENT_WRAPPER));
946 eventWrapper->event_type = OPENPTS_DUMMY_EVENT;
947 eventWrapper->push_count = 0;
948 eventWrapper->last = 1;
951 rc = updateFsm(ctx, fsm, eventWrapper);
952 if (rc == OPENPTS_FSM_ERROR) {
953 ERROR("updateFsm() - updateFsm push was fail\n");
955 if (rc == OPENPTS_FSM_ERROR_LOOP) {
956 // DEBUG("updateFsm -- updateFsm push - loop \n");
959 /* free dummy wrapper */
963 } else if (eventWrapper->event == NULL) {
964 if (eventWrapper->event_type == OPENPTS_DUMMY_EVENT) {
966 eventWrapper->push_count++;
969 if (eventWrapper->push_count > 10) {
973 return OPENPTS_FSM_ERROR_LOOP;
976 ERROR("missing event body\n");
977 return OPENPTS_FSM_ERROR;
980 /* FSM update by event */
981 event = eventWrapper->event;
984 DEBUG_FSM("[RM%02d-PCR%02d] updateFsm() - State='%s', action='%s'\n",
985 fsm->level, fsm->pcr_index,
986 curr_state->name, curr_state->action);
988 if ((event != NULL) && isDebugFlagSet(DEBUG_FSM_FLAG)) {
989 hex = getHexString(event->rgbPcrValue, event->ulPcrValueLength);
990 DEBUG_FSM("[RM%02d-PCR%02d] eventtype=0x%x, digest=0x%s\n",
991 fsm->level, fsm->pcr_index,
992 event->eventType, hex);
996 if (eventWrapper->event_type == OPENPTS_DUMMY_EVENT) {
997 // DEBUG("flash FSM\n");
998 /* Flash the trans chain */
1000 while (trans != NULL) {
1001 if (!strcmp(trans->source, curr_state->id)) {
1002 /* ID HIT, this is the trans from current state */
1004 /* Is this Final (last)? */
1005 if (!strcmp(trans->target, UML2_SD_FINAL_STATE_STRING)) {
1006 /* Final state => PENPTS_FSM_FINISH_WO_HIT */
1007 DEBUG_FSM("[RM%02d-PCR%02d] Final state! move to the next snapshot\n",
1008 fsm->level, fsm->pcr_index);
1009 fsm->status = OPENPTS_FSM_FINISH;
1010 return OPENPTS_FSM_FINISH_WO_HIT;
1016 if (trans->last_flag == LAST_FLAG_EQ) {
1017 DEBUG_FSM("check last == true\n");
1018 if (eventWrapper->last == 1) {
1022 } else if (trans->last_flag == LAST_FLAG_NEQ) {
1023 DEBUG_FSM("check last != true\n");
1024 if (eventWrapper->last == 0) {
1029 // DEBUG_FSM("last - don't care\n");
1032 trans = trans->next;
1036 if (hit_trans != NULL) {
1037 // DEBUG("hit_trans\n");
1038 hit = 1; // SKIP with this trans
1039 DEBUG_FSM("[RM%02d-PCR%02d] '%s' -> '%s'\n",
1040 fsm->level, fsm->pcr_index,
1041 hit_trans->source, hit_trans->target);
1042 fsm->curr_state = getSubvertex(fsm, hit_trans->target);
1044 if (fsm->curr_state != NULL) {
1045 /* doActivity, update properties */
1046 rc = doActivity(ctx, (char *)fsm->curr_state->action, NULL); // action.c
1047 if (rc == OPENPTS_FSM_FLASH) {
1048 /* last event, Flash FSM */
1049 DEBUG_FSM("\t\tFlash FSM (don't care trans)\n");
1051 rc = updateFsm(ctx, fsm, NULL);
1053 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1054 rc = OPENPTS_FSM_FINISH;
1056 ERROR("updateFsm - flash FSM was failed\n");
1057 rc = OPENPTS_FSM_ERROR;
1059 } else if (rc == OPENPTS_FSM_TRANSIT) {
1061 DEBUG_FSM("\t\tFlash FSM before transit \n");
1063 rc = updateFsm(ctx, fsm, NULL); // flash FSM
1065 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1066 rc = OPENPTS_FSM_TRANSIT;
1068 ERROR("updateFsm - FSM did not finish\n");
1069 rc = OPENPTS_FSM_ERROR;
1071 } else if (rc == OPENPTS_FSM_ERROR) {
1072 ERROR("updateFsm - FSM doActivity False\n");
1074 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1075 TODO("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1077 } else if (rc == OPENPTS_FSM_SUCCESS) {
1078 rc = updateFsm(ctx, fsm, eventWrapper);
1079 } else if (rc == PTS_INTERNAL_ERROR) {
1080 // TODO << INFO:(TODO) action.c:97 addBIOSAction() - eventWrapper is NULL
1081 rc = updateFsm(ctx, fsm, eventWrapper);
1083 TODO("updateFsm() - rc = %d, call updateFsm() again\n", rc);
1084 rc = updateFsm(ctx, fsm, eventWrapper);
1091 /* check trans chain */
1092 // DEBUG("updateFsm - check trans\n");
1093 while (trans != NULL) {
1098 if (!strcmp(trans->source, curr_state->id)) {
1099 /* ID HIT, this is the trans from current state */
1101 /* check the last flag */
1105 if (trans->last_flag == LAST_FLAG_EQ) {
1106 DEBUG_FSM("check last == true\n");
1107 if (eventWrapper->last == 1) {
1113 } else if (trans->last_flag == LAST_FLAG_NEQ) {
1114 DEBUG_FSM("check last != true\n");
1115 if (eventWrapper->last == 0) {
1122 // DEBUG_FSM("last - don't care\n");
1125 if (last_check == 1) {
1126 DEBUG_FSM("last event push the FSM\n");
1128 // DEBUG("NOT last event??? last_check = %d\n", last_check);
1129 // DEBUG("NOT last event??? eventWrapper->last = %d\n", eventWrapper->last);
1130 // DEBUG("NOT last event??? trans->last_flag = %d\n", trans->last_flag);
1134 /* check the event type */
1136 if (trans->eventTypeFlag == EVENTTYPE_FLAG_EQUAL) {
1137 // DEBUG_FSM("eventtype == %d - ", trans->eventType);
1138 if (trans->eventType == event->eventType) {
1140 // DEBUG_FSM("- valid\n");
1143 // DEBUG_FSM("- invalid type %d(model) != %d(iml)\n", trans->eventType, event->eventType);
1146 } else if (trans->eventTypeFlag == EVENTTYPE_FLAG_NOT_EQUAL) {
1147 // DEBUG_FSM("eventtype != %d - ", trans->eventType);
1148 if (trans->eventType != event->eventType) {
1150 DEBUG_FSM("\t\t type %x(trans) != %x(event) \n", trans->eventType, event->eventType);
1153 // DEBUG_FSM("- invalid type %d(model) == %d(iml)\n", trans->eventType, event->eventType);
1157 // DEBUG_FSM("eventtype == %d - don't care\n", trans->eventType);
1162 /* check the digest */
1163 if (trans->digestFlag == DIGEST_FLAG_EQUAL) {
1164 // DEBUG_FSM("digest -");
1165 if (!memcmp(trans->digest,
1167 event->ulPcrValueLength)) {
1170 // DEBUG_FSM("- valid\n");
1173 // DEBUG_FSM("- invalid\n");
1175 } else if (trans->digestFlag == DIGEST_FLAG_IGNORE ||
1176 trans->digestFlag == DIGEST_FLAG_TRANSPARENT) {
1177 /* Behavior Model */
1178 // DEBUG_FSM("digest - ignore\n");
1181 // DEBUG_FSM("digest - don't care\n");
1186 /* check the counter */
1187 fatal_counter_check = 3;
1188 if (trans->fatal_counter_flag == COUNTER_FLAG_LT) {
1190 int fatal_count = getCountFromProperty(ctx, trans->fatal_counter_name);
1192 if (fatal_count < 0) {
1193 ERROR("getCountFromProperty() fail");
1194 } else if (ctx->count < fatal_count) {
1195 DEBUG_FSM("FATAL COUNTER %d < %d - HIT\n", ctx->count, fatal_count);
1196 fatal_counter_check = 1; // HIT
1198 DEBUG_FSM("FATAL COUNTER %d < %d - MISS\n", ctx->count, fatal_count);
1199 fatal_counter_check = -1; // MISS
1201 } else if (trans->fatal_counter_flag == COUNTER_FLAG_GE) {
1203 int fatal_count = getCountFromProperty(ctx, trans->fatal_counter_name);
1205 // TODO at this moment we ignore >= condition,
1206 if (fatal_count < 0) {
1207 ERROR("getCountFromProperty() fail");
1208 } else if (ctx->count >= fatal_count) {
1209 DEBUG_FSM("FATAL COUNTER %d >= %d - HIT\n", ctx->count, fatal_count);
1210 fatal_counter_check = 1; // HIT
1212 DEBUG_FSM("FATAL COUNTER %d >= %d - MISS\n", ctx->count, fatal_count);
1213 fatal_counter_check = -1; // MISS
1216 // DEBUG_FSM("counter - don't care\n");
1219 if (trans->counter_flag != COUNTER_FLAG_SKIP) {
1220 int thisCount = 1 + trans->event_num;
1221 int maxCount = getCountFromProperty(ctx, trans->counter_name);
1223 ERROR("getCountFromProperty() fail, trans->counter_flag=%d", trans->counter_flag);
1224 } else if (trans->counter_flag == COUNTER_FLAG_GE &&
1225 thisCount >= maxCount) {
1226 DEBUG_FSM("DIGEST COUNTER %d >= %d ('%s') - digest is transparent\n",
1227 thisCount, maxCount, trans->counter_name);
1228 eventWrapper->transparent = 1;
1229 } else if (trans->counter_flag == COUNTER_FLAG_LT &&
1230 thisCount < maxCount) {
1231 DEBUG_FSM("DIGEST COUNTER %d < %d ('%s') - digest is transparent\n",
1232 thisCount, maxCount, trans->counter_name);
1233 eventWrapper->transparent = 1;
1238 // if ((type_check == 1) && (digest_check == 1)) {
1239 if ((type_check > 0) &&
1240 (digest_check > 0) &&
1241 (fatal_counter_check > 0) &&
1243 /* Hit this Trans */
1244 /* If Final state, switch to next snapshot */
1245 if (!strcmp(trans->target, UML2_SD_FINAL_STATE_STRING)) {
1247 DEBUG_FSM("\tPCR[%d] level %d, Final state!! move to the next snapshot\n",
1248 fsm->pcr_index, fsm->level);
1249 // ERROR("PCR[%d] level %d, Final\n", fsm->pcr_index, fsm->level);
1250 fsm->status = OPENPTS_FSM_FINISH;
1251 return OPENPTS_FSM_FINISH_WO_HIT; // FINAL
1254 /* create FSM-IML link */
1255 eventWrapper->fsm_trans = trans;
1256 trans->event = (void *) event; // note) hold the last link of looped trans
1257 trans->event_num++; // # of shared trans > 1
1258 DEBUG_FSM("[RM%02d-PCR%02d] trans->event_num = %d\n",
1259 fsm->level, fsm->pcr_index, (int)trans->event_num);
1263 if (dont_care == 2) {
1264 // this transfer does not feed event,
1265 // just move to next state and check again
1266 DEBUG_FSM("[RM%02d-PCR%02d] '%s' -> '%s'\n",
1267 fsm->level, fsm->pcr_index,
1268 trans->source, trans->target);
1269 fsm->curr_state = getSubvertex(fsm, trans->target);
1271 if (fsm->curr_state != NULL) {
1272 /* doActivity, update properties */
1273 rc = doActivity(ctx, (char *)fsm->curr_state->action, NULL); // action.c
1274 if (rc == OPENPTS_FSM_FLASH) {
1275 /* last event, Flash FSM */
1276 DEBUG_FSM("\t\tFlash FSM (don't care trans)\n");
1278 rc = updateFsm(ctx, fsm, NULL);
1280 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1281 rc = OPENPTS_FSM_FINISH;
1283 ERROR("flash FSM was failed\n");
1284 rc = OPENPTS_FSM_ERROR;
1286 } else if (rc == OPENPTS_FSM_TRANSIT) {
1288 DEBUG_FSM("\t\tFlash FSM before transit \n");
1290 rc = updateFsm(ctx, fsm, NULL); // flash FSM
1292 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1293 rc = OPENPTS_FSM_TRANSIT;
1295 ERROR("updateFsm - FSM did not finish\n");
1296 rc = OPENPTS_FSM_ERROR;
1298 } else if (rc == OPENPTS_FSM_ERROR) {
1299 DEBUG("updateFsm - doActivity error\n");
1300 // INFO("FSM validation of doActivity() was failed.
1301 // (FSM state = %s)\n",fsm->curr_state->name);
1302 addReason(ctx, fsm->pcr_index, NLS(MS_OPENPTS, OPENPTS_FSM_ACTION_FAILED,
1303 "[PCR%02d-FSM] The action '%s' failed at state '%s'"),
1304 fsm->pcr_index, (char *)fsm->curr_state->action, fsm->curr_state->name);
1306 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1307 TODO("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1309 } else if (rc == OPENPTS_FSM_SUCCESS) {
1310 rc = updateFsm(ctx, fsm, eventWrapper);
1312 TODO("rc = %d\n", rc);
1313 rc = updateFsm(ctx, fsm, eventWrapper);
1319 DEBUG_FSM("[RM%02d-PCR%02d] %s -> %s - HIT (type=%d, digest=%d)\n",
1320 fsm->level, fsm->pcr_index,
1323 type_check, digest_check);
1324 fsm->curr_state = getSubvertex(fsm, trans->target);
1326 if (fsm->curr_state != NULL) {
1327 /* doActivity, update properties */
1328 rc = doActivity(ctx, (char *)fsm->curr_state->action, eventWrapper); // action.c
1329 if (rc == OPENPTS_FSM_FLASH) {
1330 /* last event, Flash FSM */
1331 DEBUG_FSM("[RM%02d-PCR%02d] Flash this FSM\n",
1332 fsm->level, fsm->pcr_index);
1334 rc = updateFsm(ctx, fsm, NULL);
1336 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1337 rc = OPENPTS_FSM_FINISH;
1339 ERROR("updateFsm - flash FSM was failed, rc = %d\n", rc);
1340 rc = OPENPTS_FSM_ERROR;
1342 } else if (rc == OPENPTS_FSM_TRANSIT) {
1344 DEBUG_FSM("\t\tFlash FSM before transit \n");
1346 rc = updateFsm(ctx, fsm, NULL);
1348 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1349 rc = OPENPTS_FSM_TRANSIT;
1351 ERROR("updateFsm - FSM did not finish\n");
1352 rc = OPENPTS_FSM_ERROR;
1354 } else if (rc == OPENPTS_FSM_ERROR) {
1355 ERROR("updateFsm - FSM doActivity False, rc = %d\n", rc);
1357 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1358 // DEBUG("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1360 } else if (rc == OPENPTS_FSM_SUCCESS) {
1361 rc = OPENPTS_FSM_SUCCESS;
1364 // DEBUG("rc = %d -> 0\n"); // fsm.c:1070 rc = 6 -> 0
1365 rc = OPENPTS_FSM_SUCCESS;
1368 ERROR("curr_state is NULL, missing %s\n", trans->target);
1369 rc = OPENPTS_FSM_ERROR;
1378 trans = trans->next;
1384 // 20101118 SM Reason generated at iml.c
1385 DEBUG_FSM("[RM%02d-PCR%02d] No transition => rc = OPENPTS_FSM_ERROR\n",
1386 fsm->level, fsm->pcr_index);
1388 rc = OPENPTS_FSM_ERROR;
1403 OPENPTS_FSM_CONTEXT *copyFsm(OPENPTS_FSM_CONTEXT *src_fsm) {
1404 OPENPTS_FSM_CONTEXT * dst_fsm = NULL;
1406 OPENPTS_FSM_Subvertex *src_fsm_sub;
1407 OPENPTS_FSM_Subvertex *dst_fsm_sub = NULL;
1408 OPENPTS_FSM_Subvertex *dst_fsm_sub_prev = NULL;
1410 OPENPTS_FSM_Transition *src_fsm_trans;
1411 OPENPTS_FSM_Transition *dst_fsm_trans = NULL;
1412 OPENPTS_FSM_Transition *dst_fsm_trans_prev = NULL;
1416 DEBUG_FSM("copyFsm - start, PCR[%d]\n", src_fsm->pcrIndex);
1418 if (src_fsm == NULL) {
1419 DEBUG("src_fsm == NULL, SKIP COPY\n");
1424 dst_fsm = (OPENPTS_FSM_CONTEXT *) xmalloc(sizeof(OPENPTS_FSM_CONTEXT));
1425 if (dst_fsm == NULL) {
1428 memcpy((void *)dst_fsm, (void *)src_fsm, sizeof(OPENPTS_FSM_CONTEXT));
1430 /* delete BHV-FSM smalloc link */
1431 dst_fsm->uml_file = NULL;
1433 /* Copy Subvertexs */
1435 src_fsm_sub = src_fsm->fsm_sub;
1436 if (src_fsm_sub == NULL) {
1437 ERROR("ERROR No FSM SUB\n");
1441 while (src_fsm_sub != NULL) {
1442 /* malloc new sub */
1443 dst_fsm_sub = (OPENPTS_FSM_Subvertex *)
1444 xmalloc_assert(sizeof(OPENPTS_FSM_Subvertex));
1446 memcpy((void *)dst_fsm_sub,
1447 (void *)src_fsm_sub,
1448 sizeof(OPENPTS_FSM_Subvertex));
1451 if (dst_fsm_sub_prev != NULL) { // 2nd-
1452 dst_fsm_sub_prev->next = dst_fsm_sub;
1453 dst_fsm_sub->prev = dst_fsm_sub_prev;
1455 dst_fsm->fsm_sub = dst_fsm_sub;
1457 dst_fsm_sub_prev = dst_fsm_sub;
1460 dst_fsm_sub->link = src_fsm_sub;
1461 src_fsm_sub->link = dst_fsm_sub;
1464 src_fsm_sub = src_fsm_sub->next;
1468 DEBUG_FSM("%d Subvertex was copied\n", count);
1470 /* Copy Transitions */
1472 src_fsm_trans = src_fsm->fsm_trans;
1474 if (src_fsm_trans == NULL) {
1475 ERROR("ERROR No FSM TRANS\n");
1479 while (src_fsm_trans != NULL) {
1480 /* malloc new sub */
1481 dst_fsm_trans = (OPENPTS_FSM_Transition *)
1482 xmalloc_assert(sizeof(OPENPTS_FSM_Transition));
1484 memcpy((void *)dst_fsm_trans,
1485 (void *)src_fsm_trans,
1486 sizeof(OPENPTS_FSM_Transition));
1489 if (dst_fsm_trans_prev != NULL) { // 2nd-
1490 dst_fsm_trans_prev->next = dst_fsm_trans;
1491 dst_fsm_trans->prev = dst_fsm_trans_prev;
1493 dst_fsm->fsm_trans = dst_fsm_trans;
1495 dst_fsm_trans_prev = dst_fsm_trans;
1497 /* links to sub, Start and Final */
1498 // TODO(munetoh) does NULL check need?
1499 src_fsm_sub = src_fsm_trans->source_subvertex;
1500 if (src_fsm_sub != NULL) {
1501 dst_fsm_trans->source_subvertex = src_fsm_sub->link;
1503 ERROR("ERROR BHV trans %s source_subvertex is NULL\n",
1504 src_fsm_trans->source);
1507 src_fsm_sub = src_fsm_trans->target_subvertex;
1509 if (src_fsm_sub != NULL)
1510 dst_fsm_trans->target_subvertex = src_fsm_sub->link;
1512 /* link between BIN and BHV FSM */
1513 dst_fsm_trans->link = src_fsm_trans;
1514 src_fsm_trans->link = dst_fsm_trans;
1517 src_fsm_trans = src_fsm_trans->next;
1521 DEBUG_FSM("%d Transition was copied\n", count);
1522 DEBUG_FSM("copyFsm - done\n");
1527 if (dst_fsm != NULL) {
1537 S ----T--->New_Sub(--->Old_Sub)
1547 A---T---BN B--C << NG
1551 int changeTargetSubvertex(
1552 OPENPTS_FSM_CONTEXT *fsm_ctx,
1553 OPENPTS_FSM_Subvertex *old_sub, // B
1554 OPENPTS_FSM_Subvertex *new_sub) { // BN
1556 OPENPTS_FSM_Transition *fsm_trans;
1559 fsm_trans = fsm_ctx->fsm_trans;
1561 /* check all trans to B */
1562 while (fsm_trans != NULL) {
1563 if (fsm_trans->target_subvertex == old_sub) {
1564 fsm_trans->target_subvertex = new_sub;
1565 snprintf(fsm_trans->target,
1566 sizeof(fsm_trans->target),
1569 fsm_trans = fsm_trans->next;
1580 S ----T--->New_Sub(--->Old_Sub)
1589 A---T---BN B--C << OK
1593 int changeTransTargetSubvertex(
1594 OPENPTS_FSM_CONTEXT *fsm_ctx,
1595 OPENPTS_FSM_Subvertex *old_sub, // B
1596 OPENPTS_FSM_Subvertex *new_sub) { // BN
1598 OPENPTS_FSM_Transition *fsm_trans;
1601 fsm_trans = fsm_ctx->fsm_trans;
1603 /* check all trans to B */
1604 while (fsm_trans != NULL) {
1605 if (fsm_trans->target_subvertex == old_sub) {
1607 if (fsm_trans->target_subvertex == fsm_trans->source_subvertex) {
1608 // LOOP, belong to old sub
1609 DEBUG_FSM("changeTransTargetSubvertex - keep loop '%s) \n",
1613 fsm_trans->target_subvertex = new_sub;
1614 snprintf(fsm_trans->target,
1615 sizeof(fsm_trans->target),
1617 DEBUG_FSM("changeTransTargetSubvertex - trans move to new sub (%s -> %s)\n",
1618 fsm_trans->source, fsm_trans->target);
1621 fsm_trans = fsm_trans->next;
1636 FSM [A]---Ta---[B]---Tc---[C]
1642 FSM [A]---Ta---[B]---Tb---[B]---Tc---[C]
1647 Transfer Behavior to Binary FSM
1651 FSM [A]---Ta---[B0]---Tb0--[B]---Tb---[B]---Tc---[C]
1657 FSM [A]---Ta---[B0]---Tb0--[B1]---tb1--[B]---Tb---[B]---Tc---[C]
1663 FSM [A]---Ta---[B0]---Tb0--[B1]---tb1--[B2]---Tb---[B]---Tc---[C]
1671 OPENPTS_FSM_CONTEXT *fsm_ctx, // BIN-FSM
1672 OPENPTS_FSM_Transition *fsm_trans, // target Trans
1673 OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
1675 OPENPTS_FSM_Subvertex *prev_sub; // STRUCT LINK
1676 OPENPTS_FSM_Subvertex *new_sub;
1677 OPENPTS_FSM_Subvertex *dst_sub;
1678 OPENPTS_FSM_Transition *prev_trans; // STRUCT LINK
1679 OPENPTS_FSM_Transition *new_trans;
1680 TSS_PCR_EVENT *event;
1682 DEBUG_FSM("insertFsm - start\n");
1685 ASSERT(NULL != fsm_trans, "ERROR fsm_trans == NULL\n");
1687 if (fsm_trans->source_subvertex == NULL) {
1688 ERROR("ERROR fsm_trans->source_subvertex == NULL, %s -> %s\n",
1689 fsm_trans->source, fsm_trans->target);
1692 if (fsm_trans->target_subvertex == NULL) {
1693 ERROR("ERROR fsm_trans->target_subvertex == NULL\n");
1697 if (eventWrapper == NULL) {
1703 event = eventWrapper->event;
1705 if (fsm_trans->source_subvertex == fsm_trans->target_subvertex) {
1706 /* OK, this is LOOP, */
1707 DEBUG_FSM("Loop (%s->%s) has %d events\n",
1708 fsm_trans->source, fsm_trans->target, fsm_trans->event_num);
1710 /* Base subvertex, B */
1711 dst_sub = fsm_trans->target_subvertex;
1713 /* Add new subvertex, BN (->B) */
1715 new_sub = (OPENPTS_FSM_Subvertex *)
1716 xmalloc(sizeof(OPENPTS_FSM_Subvertex));
1717 if (new_sub == NULL) {
1722 fsm_trans->source_subvertex,
1723 sizeof(OPENPTS_FSM_Subvertex));
1725 snprintf(new_sub->id, sizeof(new_sub->id),
1727 dst_sub->id, fsm_trans->copy_num);
1728 snprintf(new_sub->name, sizeof(new_sub->name),
1730 dst_sub->name, fsm_trans->copy_num);
1731 fsm_ctx->subvertex_num++;
1733 /* Update the subvetex chain, A-B => A-BN-B */
1736 prev_sub = dst_sub->prev;
1737 prev_sub->next = new_sub;
1738 new_sub->prev = prev_sub;
1741 new_sub->next = dst_sub;
1742 dst_sub->prev = new_sub;
1744 /* Any trans to B move to BN */
1745 // BN->B trans is open
1746 rc = changeTransTargetSubvertex(
1751 DEBUG_FSM("\tnew sub id = %s, name = %s added\n",
1752 new_sub->id, new_sub->name);
1754 /*Next Updatre the Transition */
1756 if (fsm_trans->event_num > 1) {
1757 /* Many loops, B-B -> BN-B-B, add new Trans between BN and B */
1760 new_trans = (OPENPTS_FSM_Transition*)
1761 xmalloc(sizeof(OPENPTS_FSM_Transition));
1762 if (new_trans == NULL) {
1768 sizeof(OPENPTS_FSM_Transition));
1770 /* update the transition struct chain */
1772 prev_trans = fsm_trans->prev;
1773 prev_trans->next = new_trans;
1774 new_trans->prev = prev_trans;
1776 new_trans->next = fsm_trans;
1777 fsm_trans->prev = new_trans;
1779 fsm_ctx->transition_num++;
1781 /* Update new Trans */
1782 new_trans->source_subvertex = new_sub;
1783 snprintf(new_trans->source, sizeof(new_trans->source),
1786 new_trans->target_subvertex = dst_sub;
1787 snprintf(new_trans->target, sizeof(new_trans->target),
1790 /* Update event link */
1792 new_trans->event = eventWrapper; // TSS_PCR_EVENT_WRAPPER
1793 new_trans->event_num = 1;
1795 eventWrapper->fsm_trans = new_trans;
1797 /* Update Original Trans */
1798 fsm_trans->event_num--;
1799 fsm_trans->copy_num++;
1801 /* Copy digest value to trans */
1802 if (0 == eventWrapper->transparent) {
1803 new_trans->digestFlag = DIGEST_FLAG_EQUAL;
1804 new_trans->digestSize = event->ulPcrValueLength;
1805 new_trans->digest = xmalloc(event->ulPcrValueLength);
1806 if (new_trans->digest == NULL) {
1809 memcpy(new_trans->digest, event->rgbPcrValue, event->ulPcrValueLength);
1811 DEBUG_FSM("Changing digestFlag == DIGEST_FLAG_TRANSPARENT\n");
1812 new_trans->digestFlag = DIGEST_FLAG_TRANSPARENT;
1815 DEBUG_FSM("new Trans BIN(%s -> %s)\n",
1816 new_trans->source, new_trans->target);
1817 DEBUG_FSM("orig Trans BIN(%s -> %s) share = %d\n",
1818 fsm_trans->source, fsm_trans->target, fsm_trans->event_num);
1820 } else if (fsm_trans->event_num == 1) {
1821 /* Last loop, B-B -> BN-B, just update the trans */
1823 /* Update new Trans */
1824 fsm_trans->source_subvertex = new_sub;
1825 snprintf(fsm_trans->source, sizeof(new_trans->source),
1828 /* Copy digest value to FSM */
1829 if (0 == eventWrapper->transparent) {
1830 fsm_trans->digestFlag = DIGEST_FLAG_EQUAL;
1831 fsm_trans->digestSize = event->ulPcrValueLength;
1832 fsm_trans->digest = xmalloc(event->ulPcrValueLength);
1833 if (fsm_trans->digest == NULL) {
1836 memcpy(fsm_trans->digest, event->rgbPcrValue, event->ulPcrValueLength);
1838 fsm_trans->digestFlag = DIGEST_FLAG_TRANSPARENT;
1841 // DEBUG_FSM("\tupdate Trans %p->%p->%p\n",
1842 // fsm_trans->prev, fsm_trans, fsm_trans->next);
1843 DEBUG_FSM("\tUpdate Trans BIN(%s -> %s)\n",
1844 fsm_trans->source, fsm_trans->target);
1846 ASSERT(0, "BAD LOOP\n");
1849 ASSERT(0, "Not a loop");
1852 DEBUG_FSM("insertFsm - done\n");
1858 * remove the trans from transition chain
1861 OPENPTS_FSM_CONTEXT *fsm_ctx,
1862 OPENPTS_FSM_Transition * trans) {
1864 OPENPTS_FSM_Transition * trans_prev;
1865 OPENPTS_FSM_Transition * trans_next;
1867 trans_prev = trans->prev;
1868 trans_next = trans->next;
1871 if (trans_prev != NULL) {
1872 trans_prev->next = trans_next;
1873 } else { // 1st trans
1874 fsm_ctx->fsm_trans = trans_next;
1877 if (trans_next != NULL) {
1878 trans_next->prev = trans_prev;
1879 } else { // last trans
1883 // TODO(munetoh) Free
1890 * remove FSM subvertex
1893 OPENPTS_FSM_CONTEXT *fsm_ctx,
1894 OPENPTS_FSM_Subvertex * sub) {
1897 OPENPTS_FSM_Subvertex * sub_prev;
1898 OPENPTS_FSM_Subvertex * sub_next;
1900 sub_prev = sub->prev;
1901 sub_next = sub->next;
1904 if (sub_prev != NULL) {
1905 sub_prev->next = sub_next;
1907 fsm_ctx->fsm_sub = sub_next;
1909 if (sub_next != NULL) {
1910 sub_next->prev = sub_prev;
1911 } else { // last sub
1915 // TODO(munetoh) Free
1922 * - delete unused BHV Transitions
1923 * - delete unused BHV Subvertex
1926 int cleanupFsm(OPENPTS_FSM_CONTEXT *fsm_ctx) {
1930 OPENPTS_FSM_Transition * trans;
1931 OPENPTS_FSM_Transition * trans_next;
1933 OPENPTS_FSM_Subvertex * sub;
1934 OPENPTS_FSM_Subvertex * sub_next;
1936 ASSERT(NULL != fsm_ctx, "ERROR No FSM TRANS\n");
1938 DEBUG_FSM("cleanupFsm - start, PCR[%d]\n", fsm_ctx->pcrIndex);
1940 /* Delete BHV Transitions */
1942 trans = fsm_ctx->fsm_trans;
1944 if (trans == NULL) {
1945 ERROR("ERROR No FSM TRANS\n");
1950 while (trans != NULL) {
1951 trans_next = trans->next;
1952 if (trans->digestFlag == DIGEST_FLAG_IGNORE) {
1953 DEBUG_FSM("\tHIT %s->%s - removed\n",
1954 trans->source, trans->target);
1955 rc = removeFsmTrans(fsm_ctx, trans); // remove Trans
1957 ERROR("removeFsmTrans of %s -> %s was failed\n",
1958 trans->source, trans->target);
1963 // printf("MISS \n");
1968 DEBUG_FSM("cleanupFsm - %d trans was removed\n", count);
1969 fsm_ctx->transition_num -= count;
1971 /* Delete state which does not have incomming trans */
1972 sub = fsm_ctx->fsm_sub;
1974 ERROR("ERROR No FSM SUB\n");
1979 while (sub != NULL) {
1980 sub_next = sub->next;
1981 if (!strcmp(sub->id, "Start")) {
1983 } else if (!strcmp(sub->id, "Final")) {
1988 trans = fsm_ctx->fsm_trans;
1990 while (trans != NULL) {
1991 if (!strcmp(trans->target, sub->id)) {
1993 if (trans->target_subvertex == sub) {
1996 // EV_S_CRTM_VERSION is not detected. BAD link:-(
1999 // printf("ERROR BAD LINK\n");
2000 // printf("SUB id=%s name=%s \n",
2001 // sub->id,sub->name);
2002 // printf("TRANS %s -> %s \n",
2003 // trans->source,trans->target);
2006 trans = trans->next;
2010 DEBUG_FSM("\tSub %p id=%s name=%s not used\n",
2011 sub, sub->id, sub->name);
2013 removeFsmSub(fsm_ctx, sub);
2020 DEBUG_FSM("cleanupFsm - %d trans was removed\n", count);
2021 fsm_ctx->subvertex_num -= count;
2024 /* Again, Delete trans which does not have source target */
2026 trans = fsm_ctx->fsm_trans;
2028 if (trans == NULL) {
2029 ERROR("No FSM TRANS\n");
2034 while (trans != NULL) {
2035 trans_next = trans->next;
2037 sub = getSubvertex(fsm_ctx, trans->source);
2039 DEBUG_FSM("\tMISSING SOURCE %s->%s\n",
2040 trans->source, trans->target);
2041 removeFsmTrans(fsm_ctx, trans);
2050 DEBUG_FSM("cleanupFsm - %d trans was removed - missing source\n", count);
2051 fsm_ctx->transition_num -= count;
2054 DEBUG_FSM("cleanupFsm - done\n");
2069 * write DOT State Diagram for Graphviz
2070 * dot -Tpng tests/bios_pcr0.dot -o tests/bios_pcr0.png; eog tests/bios_pcr0.png
2071 * @param ctx FSM_CONTEXT
2072 * @param filename dot filename to write
2077 * PTS_INTERNAL_ERROR
2079 int writeDotModel(OPENPTS_FSM_CONTEXT *ctx, char * filename) {
2080 int rc = PTS_SUCCESS;
2083 OPENPTS_FSM_Subvertex *sptr;
2084 OPENPTS_FSM_Transition *ptr;
2086 DEBUG("writeDotModel - start %s\n", filename);
2089 ASSERT(NULL != ctx, "writeDotModel() - OPENPTS_FSM_CONTEXT is NULL\n");
2091 if (filename == NULL) {
2094 if ((fp = fopen(filename, "w")) == NULL) {
2095 ERROR("fopen fail %s\n", filename);
2096 return PTS_OS_ERROR;
2100 DEBUG_FSM("Subvertex num= %d \n", ctx->subvertex_num);
2101 DEBUG_FSM("Transition num= %d \n", ctx->transition_num);
2103 fprintf(fp, "digraph G {\n");
2108 while (sptr != NULL) {
2109 if (!strcmp(sptr->id, "Start")) {
2110 fprintf(fp, "\t%s [label =\"\", fillcolor=black];\n", sptr->id);
2111 // TODO(munetoh) fillcolor not work
2112 } else if (!strcmp(sptr->id, "Final")) {
2113 fprintf(fp, "\t%s [label =\"\", peripheries = 2];\n", sptr->id);
2114 } else if (strlen(sptr->action) > 0) {
2115 fprintf(fp, "\t%s [label=\"%s\\naction=%s\"];\n",
2120 fprintf(fp, "\t%s [label=\"%s\"];\n",
2128 ptr = ctx->fsm_trans;
2130 while (ptr != NULL) {
2131 DEBUG_FSM("\tTransition = (%s->%s)\n", ptr->source, ptr->target);
2133 if (ptr->digestFlag == DIGEST_FLAG_EQUAL) { // BIN
2134 fprintf(fp, "\t%s -> %s [label=\"",
2138 if (ptr->eventTypeFlag == EVENTTYPE_FLAG_EQUAL) {
2139 fprintf(fp, "eventtype == 0x%x, ", ptr->eventType);
2140 } else if (ptr->eventTypeFlag == EVENTTYPE_FLAG_NOT_EQUAL) {
2141 fprintf(fp, "eventtype != 0x%x, ", ptr->eventType);
2144 fprintf(fp, "\\nhexdigest == ");
2145 for (j = 0; j < ptr->digestSize; j++) {
2146 fprintf(fp, "%02x", ptr->digest[j]);
2147 // TODO(munetoh) Hex, also supports Base64
2149 fprintf(fp, "\"];\n");
2151 fprintf(fp, "\t%s -> %s [label=\"%s\"];\n",
2163 DEBUG("writeDotModel - done\n");
2169 * write CSV file, RFC 4180 style
2171 * @param ctx FSM_CONTEXT
2172 * @param filename csv filename to write
2174 int writeCsvTable(OPENPTS_FSM_CONTEXT *ctx, char * filename) {
2178 OPENPTS_FSM_Transition *ptr;
2181 if (filename == NULL) {
2182 ERROR("writeCsvTable - filename is NULL\n");
2187 if ((fp = fopen(filename, "w")) == NULL) {
2192 "current state,condition type(hex), condition digest,next state\n");
2194 ptr = ctx->fsm_trans;
2195 for (i = 0; i < ctx->transition_num; i++) {
2196 fprintf(fp, "%s, ", getSubvertexName(ctx, ptr->source));
2198 if (ptr->eventTypeFlag == 1) {
2199 fprintf(fp, "type==0x%x,", ptr->eventType);
2200 } else if (ptr->eventTypeFlag == 1) {
2201 fprintf(fp, "type!=0x%x,", ptr->eventType);
2207 if (ptr->digestFlag == DIGEST_FLAG_EQUAL) {
2208 fprintf(fp, "digest==0x");
2209 // for (i=0;i<DIGEST_SIZE;i++) fprintf(fp,"%02x",ptr->digest[i]);
2211 } else if (ptr->digestFlag == DIGEST_FLAG_IGNORE) {
2212 fprintf(fp, "digest==base64!,");
2213 } else if (ptr->digestFlag == DIGEST_FLAG_TRANSPARENT) {
2214 fprintf(fp, "digest==transparent!,");
2218 fprintf(fp, "%s\n", getSubvertexName(ctx, ptr->target));
2230 * print FSM State Diagram
2232 * @param ctx FSM_CONTEXT
2234 int printFsmModel(OPENPTS_FSM_CONTEXT *ctx) {
2237 OPENPTS_FSM_Transition *ptr;
2239 OUTPUT(NLS(MS_OPENPTS, OPENPTS_PRINT_FSM_HEADER,
2240 "ctx->transition_num = %d\n"
2241 "trans\t\tcurrent state\t\t\tcondition\t\t\\ttnext state\n"
2242 " id \t\t\t\t\ttype(hex)\tdigest(hex)\n"), ctx->transition_num);
2243 OUTPUT("----------------------------------------------------------------------------------------------\n");
2246 ptr = ctx->fsm_trans;
2247 for (i = 0; i < ctx->transition_num; i++) {
2249 ERROR("PTR is NULL at %d\n", i);
2253 OUTPUT("%30s ", getSubvertexName(ctx, ptr->source));
2255 if (ptr->eventTypeFlag == 1) {
2256 OUTPUT(" 0x%08x ", ptr->eventType);
2257 } else if (ptr->eventTypeFlag == 1) {
2258 OUTPUT("!0x%08x ", ptr->eventType);
2263 if (ptr->digestFlag == DIGEST_FLAG_EQUAL) {
2265 for (j = 0; j < ptr->digestSize; j++) OUTPUT("%02x", ptr->digest[j]);
2267 } else if (ptr->digestFlag == DIGEST_FLAG_IGNORE) {
2268 OUTPUT(NLS(MS_OPENPTS, OPENPTS_PRINT_FSM_BASE64, "base64 "));
2269 } else if (ptr->digestFlag == DIGEST_FLAG_TRANSPARENT) {
2270 /* WORK NEEDED: say transparent here? */
2275 OUTPUT("%-30s\n", getSubvertexName(ctx, ptr->target));