OSDN Git Service

1f476332f65c5c9f063c0cba869789d9132a057f
[openpts/openpts.git] / src / fsm.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
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.
8  *
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)
12  * any later version.
13  *
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.
18  *
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.
22  */
23
24 /**
25  * \file src/fsm.c
26  * \brief Finite State Machine
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2010-04-01
29  * cleanup 2011-01-21 SM
30  * refactoring 2011-07-20 SM
31  * 
32  * Input
33  *   FSM Model
34  *   IML
35  *   PROPERTY
36  * Output
37  *   SNAPSHOT
38  *   PROPERTY
39  *
40  */
41
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45
46 #include <libxml/encoding.h>
47 #include <libxml/xmlwriter.h>
48 #include <libxml/parser.h>
49
50 #include <openpts.h>
51
52 /**
53  * create new FSM context
54  */
55 OPENPTS_FSM_CONTEXT *newFsmContext() {
56     OPENPTS_FSM_CONTEXT *ctx = NULL;
57
58     /* malloc */
59     ctx = (OPENPTS_FSM_CONTEXT *) xmalloc(sizeof(OPENPTS_FSM_CONTEXT));
60     if (ctx == NULL) {
61         return NULL;
62     }
63     /* init */
64     memset(ctx, 0 , sizeof(OPENPTS_FSM_CONTEXT));
65     ctx->fsm_sub = NULL;
66     ctx->fsm_trans = NULL;
67     ctx->uml_file = NULL;
68     ctx->state = 0;
69     ctx->subvertex_num = 0;
70     ctx->transition_num = 0;
71     return ctx;
72 }
73
74 /**
75  * Free OPENPTS_FSM_Transition chain
76  */
77 void freeFsmTransitionChain(OPENPTS_FSM_Transition *fsm_trans) {
78     if (fsm_trans->next != NULL) {
79         freeFsmTransitionChain(fsm_trans->next);
80     }
81
82     /* free */
83     if (fsm_trans->digest != NULL) {
84         xfree(fsm_trans->digest);
85     }
86
87     xfree(fsm_trans);
88 }
89
90 /**
91  * Free OPENPTS_FSM_Subvertex chain
92  */
93 void freeFsmSubvertexChain(OPENPTS_FSM_Subvertex *fsm_sub) {
94     if (fsm_sub->next != NULL) {
95         freeFsmSubvertexChain(fsm_sub->next);
96     }
97
98     xfree(fsm_sub);
99 }
100
101 /**
102  * free FSM context
103  */
104 int freeFsmContext(OPENPTS_FSM_CONTEXT *ctx) {
105     ASSERT(NULL != ctx, "ctx is NULL\n");
106
107     /* Transition */
108     if (ctx->fsm_trans != NULL) {
109         freeFsmTransitionChain(ctx->fsm_trans);
110         ctx->fsm_trans = NULL;
111     }
112
113
114     /* Subvertex */
115     if (ctx->fsm_sub != NULL) {
116         freeFsmSubvertexChain(ctx->fsm_sub);
117         ctx->fsm_sub = NULL;
118     }
119
120     /* UML filename */
121     if (ctx->uml_file != NULL) {
122         xfree(ctx->uml_file);
123         ctx->uml_file = NULL;
124     }
125
126     xfree(ctx);
127     return 0;
128 }
129
130
131 //// SUBVERTEX ////
132
133 /**
134  * reset FSM subvertex
135  */
136 void resetFsmSubvertex(OPENPTS_FSM_CONTEXT *ctx) {
137     // fsm_sub=NULL;
138     ctx->subvertex_num = 0;
139 }
140
141 /**
142  * reset FSM transition
143  */
144 void resetFsmTransition(OPENPTS_FSM_CONTEXT *ctx) {
145     // fsm_trans=NULL;
146     ctx->transition_num = 0;
147 }
148
149
150 /**
151  * add FMS subvertex to context
152  */ 
153 void addFsmSubvertex(
154         OPENPTS_FSM_CONTEXT *ctx,
155         char *type,
156         char *id,
157         char *name,
158         char *action) {
159     int i;
160     OPENPTS_FSM_Subvertex *ptr = NULL;
161     OPENPTS_FSM_Subvertex *ptr_pre = NULL;
162
163     DEBUG_CAL("addFsmSubvertex - %d \n", ctx->subvertex_num);
164
165     ptr = ctx->fsm_sub;
166     for (i = 0; i <= ctx->subvertex_num; i++) {
167         if (ptr == NULL) {
168             /* add new PENPTS_FSM_Subvertex */
169             DEBUG_FSM(" id=%s name=%s size=%d\n",
170                       id, name,
171                       (int)sizeof(OPENPTS_FSM_Subvertex));
172
173             /* malloc OPENPTS_FSM_Subvertex */
174             ptr = (OPENPTS_FSM_Subvertex *)
175                     xmalloc(sizeof(OPENPTS_FSM_Subvertex));
176             if (ptr == NULL) {
177                 return;
178             }
179
180             /* init */
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);
187
188             ptr->next = NULL;
189             ptr->num = ctx->subvertex_num;
190             ptr->incomming_num = 0;
191
192             if (ctx->subvertex_num == 0) {  // first event
193                 ctx->fsm_sub = ptr;
194                 ptr->prev = NULL;
195                 // NG must be Start event ctx->curr_state = ptr;
196             } else if (ptr_pre != NULL) {
197                 ptr_pre->next = ptr;  // else
198                 ptr->prev = ptr_pre;
199             } else {
200                 ERROR("\n");
201                 xfree(ptr);  // free last one
202                 return;
203             }
204
205             ctx->subvertex_num++;
206             return;
207         }
208         ptr_pre = ptr;
209         ptr = ptr->next;
210     }
211 }
212
213 /**
214  * get Subvertex ptr by ID
215  */
216 OPENPTS_FSM_Subvertex * getSubvertex(OPENPTS_FSM_CONTEXT *ctx, char * id) {
217     OPENPTS_FSM_Subvertex *ptr;
218
219     if (!strcmp(id, "Final")) return NULL;  // final state
220
221     ptr = ctx->fsm_sub;
222
223     while (ptr != NULL) {
224         if (!strcmp(id, ptr->id)) return ptr;
225         ptr = (OPENPTS_FSM_Subvertex *) ptr->next;
226     }
227     return NULL;
228 }
229
230 /**
231  * get Subvertex Name by ID
232  */
233 char * getSubvertexName(OPENPTS_FSM_CONTEXT *ctx, char * id) {
234     int i;
235     OPENPTS_FSM_Subvertex *ptr;
236
237     if (!strcmp(id, "Final")) return id;
238
239     ptr = ctx->fsm_sub;
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;
243     }
244
245     return NULL;
246 }
247
248 /**
249  * get Subvertex ID by Name
250  */
251 char * getSubvertexId(OPENPTS_FSM_CONTEXT *ctx, char * name) {
252     int i;
253     OPENPTS_FSM_Subvertex *ptr;
254
255     // if (!strcmp(id, "Final")) return id;
256
257     ptr = ctx->fsm_sub;
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;
261     }
262
263     return NULL;
264 }
265
266
267 /// TRANSITION ///
268
269 static char *skipWhiteSpace(char *str, int *len) {
270     char *cur = str, *end = str + *len;
271     /* skip space */
272     while (cur < end &&
273            '\0' != *cur &&
274            ' '  == *cur) {
275         cur++;
276     }
277     *len -= cur - str;
278     return cur;
279 }
280
281 static int isEndOfString(char *str) {
282     return '\0' == *str;
283 }
284
285 static char *skipParameter(char *str, int *len) {
286     char *cur = str, *end = str + *len;
287     /* skip space */
288     while (cur < end &&
289            '\0' != *cur &&
290            ' '  != *cur &&
291            ','  != *cur) {
292         cur++;
293     }
294     *len -= cur - str;
295     return cur;
296 }
297
298 /**
299  *   <body>eventtype == 0x01, digest == base64</body>
300  * -1: error
301  *  0: don't care
302  *   1: ==
303  *   2: !=
304  *
305  * Unit Test : check_fsm.c / test_getTypeFlag
306  *
307  */
308 int getTypeFlag(char * cond, UINT32 *eventtype) {
309     char * loc;
310     int len;
311     int rc = 0;
312     long int val;  // TODO uint64_t? but build fail on i386 platform
313
314     len = strlen(cond);
315
316     loc = strstr(cond, "eventtype");
317
318     if (loc == NULL) {  // miss
319         *eventtype = 0;
320         return 0;
321     } else {  // hit
322         /* skip eventtype*/
323         loc += 9;
324         len -= (loc - cond);
325
326         loc = skipWhiteSpace(loc, &len);
327         if (isEndOfString(loc)) {
328             return -1;
329         }
330
331         /* operation */
332         if (len < 2) {
333             ERROR("ERROR 001\n");
334             return -1;  // end
335         }
336         if ((loc[0] == '=') && (loc[1] == '=')) {  // ==
337             rc = 1;
338         } else if ((loc[0] == '!') && (loc[1] == '=')) {  // ==
339             rc = 2;
340         } else {
341             ERROR("ERROR 002 %c %c \n", loc[0], loc[1]);
342             return -1;  // unknown operand
343         }
344         loc += 2;
345         len -= 2;
346
347         loc = skipWhiteSpace(loc, &len);
348         if (isEndOfString(loc)) {
349             return -1;
350         }
351
352         /* value */
353         // 20110117 Ubuntu i386, 0x80000002 => 7FFFFFFF, => use strtoll
354         if (len > 2) {
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);
359                 return rc;
360             }
361         }
362         val = strtoll(loc, NULL, 10);
363         *eventtype = (UINT32)val;
364         // DEBUG("strtol [%s] => %X => %X\n", loc,val, *eventtype);
365
366         return rc;
367     }
368 }
369
370 /**
371  * Parse condition string and setup an internal digest condition structure
372  *
373  * Return
374  *   0: don't care
375  *   1: valid (=binary model),  return the digest => freed at freeFsmTransitionChain()
376  *   2: ignore now (=behavior model or ignored digests in binary model)
377  *  -1: Error?
378  *
379  * Unit Test : check_fsm.c / test_getDigestFlag
380  *
381  * TODO STA may complain the memory leak againt *digest.
382  */
383 int getDigestFlag(char * cond, BYTE **digest, int *digest_size) {
384     char * loc;   // loc at value
385     int len;
386     BYTE *buf;
387     int buf_len;
388
389     DEBUG_CAL("getDigestFlag -");
390
391     len = strlen(cond);
392
393     loc = strstr(cond, "digest");
394     if (loc == NULL) {  // miss
395         *digest_size = 0;
396         return DIGEST_FLAG_SKIP;
397     } else {  // hit
398         /* skip  digest */
399         loc += 6;
400         len -= (loc - cond);
401
402         loc = skipWhiteSpace(loc, &len);
403         if (isEndOfString(loc)) {
404             return -1;
405         }
406
407         /* operation, "==" only */
408         if (len < 2) {
409             ERROR("ERROR 001\n");
410             return -1;  // end
411         }
412         if ((loc[0] == '=') && (loc[1] == '=')) {  // ==
413             // operand is ==
414         } else {
415             ERROR("ERROR 002 [%c%c]  not  ==, (cond = %s)\n", loc[0], loc[1], cond);
416             return -1;  // unknown operand
417         }
418         loc +=2;
419         len -=2;
420
421         /* skip space */
422         loc = skipWhiteSpace(loc, &len);
423         if (isEndOfString(loc)) {
424             return -1;
425         }
426
427         /* digest == base64 (behavior model) */
428 #if 0
429         loc2 = strstr(loc, "base64");
430         if (loc2 != NULL) {  // HIT, temp
431             /* Behavior Model */
432             return 2;
433         } else {
434             /* Binary Model */
435             /* Base64 str -> BYTE[] */
436             buf = decodeBase64(
437                 (char *)loc,
438                 SHA1_BASE64_DIGEST_SIZE,
439                 &buf_len);
440             if (buf == NULL) {
441                 ERROR("decodeBase64 fail");
442                 *digest = NULL;
443                 *digest_size = 0;
444                 return -1;
445             }
446             *digest = buf;
447             // TODO buf_len >= SHA1_DIGEST_SIZE
448             *digest_size = SHA1_DIGEST_SIZE;
449             return 1;
450         }
451 #endif
452         if (NULL != strstr(loc, "base64!")) {  // HIT, temp
453             /* Behavior Model */
454             return DIGEST_FLAG_IGNORE;
455         } else if (NULL != strstr(loc, "base64")) {  // HIT, temp
456             /* Behavior Model */
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;
462         } else {
463             /* Binary Model */
464             /* Base64 str -> BYTE[] */
465             buf = decodeBase64(
466                 (char *)loc,
467                 SHA1_BASE64_DIGEST_SIZE,
468                 &buf_len);
469             if (buf == NULL) {
470                 ERROR("decodeBase64 fail");
471                 *digest = NULL;
472                 *digest_size = 0;
473                 return -1;
474             } else if (buf_len == SHA1_DIGEST_SIZE) {
475                 *digest = buf;
476                 *digest_size = SHA1_DIGEST_SIZE;
477                 return DIGEST_FLAG_EQUAL;  // 1
478             } else {
479                 ERROR("getDigestFlag() - decodeBase64() was failed \n");
480                 xfree(buf);
481                 *digest = NULL;
482                 *digest_size = 0;
483                 return -1;
484             }
485 #if 0
486             buf = (BYTE *) xmalloc(SHA1_DIGEST_SIZE + 1);
487             if (buf == NULL) {
488                 return -1;
489             }
490
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
496                 *digest = buf;
497                 *digest_size = rc;
498                 return DIGEST_FLAG_EQUAL;
499             } else {
500                 ERROR("getDigestFlag() - decodeBase64() was failed \n");
501                 xfree(buf);
502                 *digest = NULL;
503                 *digest_size = 0;
504                 return -1;
505             }
506 #endif
507         }
508     }
509 }
510
511 /**
512  * Parse condition string and setup an internal couter condition structure
513  *
514  *
515  * 
516  * Return
517  *   COUNTER_FLAG_SKIP 0: don't care
518  *   COUNTER_FLAG_LT   1:  < name
519  *   COUNTER_FLAG_GTE  2:  >= name 
520  *
521  * Unit Test : check_fsm.c / test_getCounterFlag
522  */
523 int getCounterFlag(char *cond, char *name, char **flag) {
524     char * loc;   // loc at value
525     char * loc2;  // loc at flag
526     int len;
527     int rc = COUNTER_FLAG_SKIP;
528
529     /* check */
530     if (cond == NULL) {
531         ERROR("Null condition found");
532         return 0;
533     }
534     if (name == NULL) {
535         ERROR("Null condition found");
536         return 0;
537     }
538
539     /* parse the flag */
540     len = strlen(cond);
541     loc = strstr(cond, name);
542
543     if (loc == NULL) {
544         /* miss */
545         return 0;
546     } else {
547         int param_len = 0;
548         /* hit */
549
550         /* skip  count */
551         loc += strlen(name);
552         len -= (loc - cond);
553
554         loc = skipWhiteSpace(loc, &len);
555         if (isEndOfString(loc)) {
556             goto error;  //return -1;
557         }
558
559         /* operation, "&lt;" ">=" only */
560         if ((len >= 2) && (loc[0] == 'l') && (loc[1] == 't')) {  // <, lt
561             rc = COUNTER_FLAG_LT;
562             loc +=2;
563             len -=2;
564         } else if ((len >= 2) && (loc[0] == 'l') && (loc[1] == 'e')) {  // <=, le
565             rc = COUNTER_FLAG_LE;
566             loc +=2;
567             len -=2;
568         } else if ((len >= 2) && (loc[0] == 'g') && (loc[1] == 't')) {  // >, gt
569             rc = COUNTER_FLAG_GT;
570             loc +=2;
571             len -=2;
572         } else if ((len >= 2) && (loc[0] == 'g') && (loc[1] == 'e')) {  // >, gt
573             rc = COUNTER_FLAG_GE;
574             loc +=2;
575             len -=2;
576         } else if ((len >= 2) && (loc[0] == '<') && (loc[1] == ' ')) {  // <, lt
577             rc = COUNTER_FLAG_LT;
578             loc +=2;
579             len -=2;
580         } else if ((len >= 2) && (loc[0] == '<') && (loc[1] == '=')) {  // <=, le
581             rc = COUNTER_FLAG_LE;
582             loc +=2;
583             len -=2;
584         } else if ((len >= 2) && (loc[0] == '>') && (loc[1] == ' ')) {  // >, gt
585             rc = COUNTER_FLAG_GT;
586             loc +=2;
587             len -=2;
588         } else if ((len >= 2) && (loc[0] == '>') && (loc[1] == '=')) {  // >=
589             rc = COUNTER_FLAG_GE;
590             loc +=2;
591             len -=2;
592         } else {
593             ERROR("unknown operand [%s]", &loc[0]);
594             goto error;  //return -1;
595         }
596
597         loc = skipWhiteSpace(loc, &len);
598         if (isEndOfString(loc)) {
599             goto error;  //return -1;
600         }
601
602         // TODO check the end, this code only support if counter is the last
603
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;
609         }
610
611         /* DEBUG_FSM("[%d][%s][%s]\n",len, loc, loc2); */
612
613         *flag = xmalloc(param_len + 1);
614         if (*flag == NULL) {
615             goto error;  //return -1;
616         }
617         memset(*flag, 0, param_len + 1);
618         memcpy(*flag, loc, param_len);
619     }
620
621     DEBUG_FSM("getCounterFlag  %s #=> %d %s\n", cond, rc, *flag);
622
623     return rc;
624
625   error:
626     ERROR("getCounterFlag(\"%s\",\"%s\") fail", cond, name);
627     return -1;
628 }
629
630
631
632 /**
633  * Parse condition string and setup an internal couter condition structure
634  *
635  *
636  * 
637  * Return
638  *                    -1: error
639  *   LAST_FLAG_SKIP 0: don't care
640  *   LAST_FLAG_EQ   1:  == last
641  *   LAST_FLAG_NEQ  2:  != last 
642  *
643  * Unit Test : check_fsm.c / test_getCounterFlag
644  */
645 int getLastFlag(char * cond) {
646     char * loc;   // loc at value
647     char * loc2;  // loc at name
648     int len;
649     int rc = LAST_FLAG_SKIP;
650
651     len = strlen(cond);
652     loc = strstr(cond, "last");
653
654     if (loc == NULL) {
655         /* miss */
656         return LAST_FLAG_SKIP;
657     } else {
658         /* hit */
659         // DEBUG("getLastFlag() - %s\n", cond);
660
661         /* skip  count */
662         loc += 5;
663         len -= (loc - cond);
664
665         loc = skipWhiteSpace(loc, &len);
666         if (isEndOfString(loc)) {
667             return -1;
668         }
669
670         /* operation, "&lt;" ">=" only */
671         if ((len >= 2) && (loc[0] == '=') && (loc[1] == '=')) {
672             /* >= */
673             rc = LAST_FLAG_EQ;
674             loc +=2;
675             len -=2;
676         } else if ((len >= 2) && (loc[0] == '!') && (loc[1] == '=')) {
677             /* >= */
678             rc = LAST_FLAG_NEQ;
679             loc +=2;
680             len -=2;
681         } else {
682             // ERROR("ERROR 002 [%s]  not  >= \n", &loc[0];
683             return -1;  // unknown operand
684         }
685
686         loc = skipWhiteSpace(loc, &len);
687         if (isEndOfString(loc)) {
688             return -1;
689         }
690
691         /* value */
692
693         loc2 = loc;
694         len = strlen(loc2);
695
696         // DEBUG("[%d][%s]\n",len, loc2);
697         if (!strncmp(loc2, "true", 4)) {
698             // DEBUG("true\n");
699             /* == true */
700             /* != true => false */
701         } else if (!strncmp(loc2, "false", 5)) {
702             // DEBUG("false %d\n",rc);
703             if (rc == LAST_FLAG_EQ) {
704                 rc = LAST_FLAG_NEQ;
705             } else {
706                 rc = LAST_FLAG_EQ;
707             }
708             // DEBUG("false %d\n",rc);
709         } else {
710             ERROR("unknown value, %s\n", loc2);
711         }
712     }
713
714     // DEBUG("getLastFlag  %s #=> %d\n",cond, rc);
715
716     return rc;
717 }
718
719
720
721
722 /**
723  * add FSM transition
724  *
725  * Return
726  *   PTS_SUCCESS
727  *   PTS_INTERNAL_ERROR
728  */
729 int addFsmTransition(
730         OPENPTS_FSM_CONTEXT *ctx,
731         char *source,
732         char *target,
733         char *cond) {
734     int i;
735     OPENPTS_FSM_Transition *ptr = NULL;
736     OPENPTS_FSM_Transition *ptr_pre = NULL;
737
738     DEBUG_CAL("addFsmTransition - start\n");
739
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));
746
747             /* malloc OPENPTS_FSM_Transition */
748             ptr = (OPENPTS_FSM_Transition *)
749                     xmalloc(sizeof(OPENPTS_FSM_Transition));
750             if (ptr == NULL) {
751                 return PTS_INTERNAL_ERROR;
752             }
753             /* init */
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;
758             if (cond == NULL) {
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);
765             } else {
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);
774                 }
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);
779                 }
780                 // 0:don't care 1: ==last 2: != last
781                 ptr->last_flag = getLastFlag(cond);
782                 memcpy(ptr->cond, cond, FSM_BUF_SIZE);
783             }
784             /* subvertex link (ptr) */
785             ptr->source_subvertex = getSubvertex(ctx, ptr->source);
786             ptr->target_subvertex = getSubvertex(ctx, ptr->target);
787
788             if (DIGEST_FLAG_TRANSPARENT == ptr->digestFlag) {
789                 DEBUG_FSM("Found transparent digest\n");
790                 ctx->numTransparencies++;
791             }
792
793             /* ptr */
794             ptr->next = NULL;
795             if (ctx->transition_num == 0) {
796                 ctx->fsm_trans = ptr;
797                 ptr->prev = NULL;  // first trans
798             } else if (ptr_pre != NULL) {
799                 ptr_pre->next = ptr;
800                 ptr->prev = ptr_pre;
801                 ptr->next = NULL;  // last trans
802             } else {
803                 ERROR("\n");
804                 xfree(ptr);  // free last one
805                 return PTS_INTERNAL_ERROR;
806             }
807             ctx->transition_num++;
808             /* added */
809             return PTS_SUCCESS;
810         }
811         /* next */
812         ptr_pre = ptr;
813         ptr = (OPENPTS_FSM_Transition *)ptr->next;
814     }
815
816     ERROR("missing?\n");
817     return PTS_INTERNAL_ERROR;
818 }
819
820 #if 0
821 /**
822  * get Event String (malloc) - obsolete function
823  */
824 char *getEventString(OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
825     // int len;
826     int size = FSM_BUF_SIZE;  // TODO fixed size
827     TSS_PCR_EVENT *event;
828     char *buf;
829
830     /* malloc */
831     buf = xmalloc(size);
832     if (buf == NULL) {
833         return NULL;
834     }
835
836     /* event */
837     event = eventWrapper->event;
838     if (event != NULL) {
839         // len = snprintf(buf, size, "PCR[%d],TYPE=%d", (int)event->ulPcrIndex, event->eventType);
840     } else {
841         ERROR("NULL event\n");  // TODO(munetoh)
842         xfree(buf);
843         return NULL;
844     }
845
846     return buf;
847 }
848 #endif
849
850 /**
851  * get counter(int) value from property
852  * property
853  *    name=num
854  *
855  * return
856  *   -1   : ERROR
857  *    1   : missing, invalid (e.g. minus)
858  *    num 
859  */
860 int getCountFromProperty(OPENPTS_CONTEXT *ctx, char * name) {
861     int count = 0;  // TODO get from prop
862     OPENPTS_PROPERTY *prop;
863
864     /* check */
865     if (ctx == NULL) {
866         ERROR("ctx == NULL");
867         return -1;
868     }
869     if (name == NULL) {
870         ERROR("name == NULL");
871         return -1;
872     }
873
874     /* lookup */
875     prop = getProperty(ctx, name);
876     if (prop != NULL) {
877         /* Hit use this properties */
878         count = atoi(prop->value);
879         DEBUG_FSM("getCountFromProperty - prop %s = %d\n", name, count);
880         if (count < 0) {
881             DEBUG("getCountFromProperty - prop %s is %d < 0. set count to 1\n", count, name);
882             count = 1;
883         }
884     } else {
885         /* Miss -> 1 */
886         // TODO
887         DEBUG("getCountFromProperty - prop %s is missing. set count to 1\n", name);
888         count = 1;  // TODO
889     }
890     return count;
891 }
892
893 /**
894  * Drive FSM Transition by Event
895  *
896  * @parm eventWrapper  NULL, push the FSM until Final state
897  *
898  * Return
899  *
900  *  OPENPTS_FSM_ERROR
901  *
902  *  OPENPTS_FSM_SUCCESS
903  *  OPENPTS_FSM_FLASH
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
907  *
908  * if eventWrapper is NULL, create and use dummy event 
909  */
910 int updateFsm(
911         OPENPTS_CONTEXT *ctx,
912         OPENPTS_FSM_CONTEXT *fsm,
913         OPENPTS_PCR_EVENT_WRAPPER *eventWrapper
914     ) {
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;
919     int type_check;
920     int digest_check;
921     int fatal_counter_check;
922     int last_check;
923     int dont_care;
924     int hit = 0;
925     char *hex;
926     OPENPTS_FSM_Transition *hit_trans = NULL;
927
928     DEBUG_CAL("updateFsm - start\n");
929
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");
934     }
935
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);
941
942         /* dummy wrapper */
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;
949
950         /*  push */
951         rc = updateFsm(ctx, fsm, eventWrapper);
952         if (rc == OPENPTS_FSM_ERROR) {
953             ERROR("updateFsm() - updateFsm push was fail\n");
954         }
955         if (rc == OPENPTS_FSM_ERROR_LOOP) {
956             // DEBUG("updateFsm -- updateFsm push - loop \n");
957         }
958
959         /* free dummy wrapper */
960         xfree(eventWrapper);
961         eventWrapper = NULL;
962         return rc;
963     } else if (eventWrapper->event == NULL) {
964         if (eventWrapper->event_type == OPENPTS_DUMMY_EVENT) {
965             // DUMMY
966             eventWrapper->push_count++;
967             event = NULL;
968
969             if (eventWrapper->push_count > 10) {
970                 /* LOOP */
971                 // TODO detect LOOP
972                 // DEBUG("LOOP?\n");
973                 return OPENPTS_FSM_ERROR_LOOP;
974             }
975         } else {
976            ERROR("missing event body\n");
977            return OPENPTS_FSM_ERROR;
978         }
979     } else {
980         /* FSM update by event */
981         event = eventWrapper->event;
982     }
983
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);
987
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);
993         xfree(hex);
994     }
995
996     if (eventWrapper->event_type == OPENPTS_DUMMY_EVENT) {
997         // DEBUG("flash FSM\n");
998         /* Flash the trans chain */
999         hit_trans = NULL;
1000         while (trans != NULL) {
1001             if (!strcmp(trans->source, curr_state->id)) {
1002                 /* ID HIT, this is the trans from current state */
1003
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;
1011                 }
1012
1013                 /* More stats */
1014                 hit_trans = trans;
1015
1016                 if (trans->last_flag == LAST_FLAG_EQ) {
1017                     DEBUG_FSM("check last == true\n");
1018                     if (eventWrapper->last == 1) {
1019                         /* Hit */
1020                         break;
1021                     }
1022                 } else if (trans->last_flag == LAST_FLAG_NEQ) {
1023                     DEBUG_FSM("check last != true\n");
1024                     if (eventWrapper->last == 0) {
1025                         /* Hit */
1026                         break;
1027                     }
1028                 } else {
1029                     // DEBUG_FSM("last - don't care\n");
1030                 }
1031             }  // hit
1032             trans = trans->next;
1033         }  // while
1034
1035
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);
1043
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");
1050
1051                     rc = updateFsm(ctx, fsm, NULL);
1052
1053                     if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1054                         rc = OPENPTS_FSM_FINISH;
1055                     } else {
1056                         ERROR("updateFsm - flash FSM was failed\n");
1057                         rc = OPENPTS_FSM_ERROR;
1058                     }
1059                 } else if (rc == OPENPTS_FSM_TRANSIT) {
1060                     /* transit FSM */
1061                     DEBUG_FSM("\t\tFlash FSM before transit \n");
1062
1063                     rc = updateFsm(ctx, fsm, NULL);  // flash FSM
1064
1065                     if  (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1066                         rc = OPENPTS_FSM_TRANSIT;
1067                     } else {
1068                         ERROR("updateFsm - FSM did not finish\n");
1069                         rc = OPENPTS_FSM_ERROR;
1070                     }
1071                 } else if (rc == OPENPTS_FSM_ERROR) {
1072                     ERROR("updateFsm - FSM doActivity False\n");
1073                     return rc;
1074                 } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1075                     TODO("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1076                     return rc;
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);
1082                 } else {
1083                     TODO("updateFsm() - rc = %d, call updateFsm() again\n", rc);
1084                     rc = updateFsm(ctx, fsm, eventWrapper);
1085                 }
1086             }  // curr state
1087         } else {  // hit
1088             TODO("no trans\n");
1089         }
1090     } else {
1091         /* check trans chain */
1092         // DEBUG("updateFsm - check trans\n");
1093         while (trans != NULL) {
1094             type_check = 0;
1095             digest_check = 0;
1096             dont_care = 0;
1097
1098             if (!strcmp(trans->source, curr_state->id)) {
1099                 /*  ID HIT, this is the trans from current state */
1100
1101                 /* check the last flag */
1102                 hit_trans = trans;
1103                 last_check = 3;
1104
1105                 if (trans->last_flag == LAST_FLAG_EQ) {
1106                     DEBUG_FSM("check last == true\n");
1107                     if (eventWrapper->last == 1) {
1108                         /* Hit */
1109                         last_check = 1;
1110                     } else {
1111                         last_check = -1;
1112                     }
1113                 } else if (trans->last_flag == LAST_FLAG_NEQ) {
1114                     DEBUG_FSM("check last != true\n");
1115                     if (eventWrapper->last == 0) {
1116                         /* Hit */
1117                         last_check = 1;
1118                     } else {
1119                         last_check = -1;
1120                     }
1121                 } else {
1122                     // DEBUG_FSM("last - don't care\n");
1123                 }
1124
1125                 if (last_check == 1) {
1126                     DEBUG_FSM("last event push the FSM\n");
1127                 } else {
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);
1131                 }
1132
1133
1134                 /* check the event type */
1135
1136                 if (trans->eventTypeFlag == EVENTTYPE_FLAG_EQUAL) {
1137                     // DEBUG_FSM("eventtype == %d - ", trans->eventType);
1138                     if (trans->eventType == event->eventType) {
1139                         /* TYPE MATCH */
1140                         // DEBUG_FSM("- valid\n");
1141                         type_check = 1;
1142                     } else {
1143                         // DEBUG_FSM("- invalid type %d(model) != %d(iml)\n", trans->eventType, event->eventType);
1144                         type_check = -1;
1145                     }
1146                 } else if (trans->eventTypeFlag == EVENTTYPE_FLAG_NOT_EQUAL) {
1147                     // DEBUG_FSM("eventtype != %d - ", trans->eventType);
1148                     if (trans->eventType != event->eventType) {
1149                         /* TYPE MATCH */
1150                         DEBUG_FSM("\t\t type %x(trans) != %x(event) \n", trans->eventType, event->eventType);
1151                         type_check = 2;
1152                     } else {
1153                         // DEBUG_FSM("- invalid type %d(model) == %d(iml)\n", trans->eventType, event->eventType);
1154                         type_check = -1;
1155                     }
1156                 } else {
1157                     // DEBUG_FSM("eventtype == %d - don't care\n", trans->eventType);
1158                     type_check = 3;
1159                     dont_care++;
1160                 }
1161
1162                 /* check the digest */
1163                 if (trans->digestFlag == DIGEST_FLAG_EQUAL) {
1164                     // DEBUG_FSM("digest -");
1165                     if (!memcmp(trans->digest,
1166                                 event->rgbPcrValue,
1167                                 event->ulPcrValueLength)) {
1168                         /* DIGEST MATCH */
1169                         digest_check = 1;
1170                         // DEBUG_FSM("- valid\n");
1171                     } else {
1172                         digest_check = -1;
1173                         // DEBUG_FSM("- invalid\n");
1174                     }
1175                 } else if (trans->digestFlag == DIGEST_FLAG_IGNORE ||
1176                            trans->digestFlag == DIGEST_FLAG_TRANSPARENT) {
1177                     /* Behavior Model */
1178                     // DEBUG_FSM("digest - ignore\n");
1179                     digest_check = 2;
1180                 } else {
1181                     // DEBUG_FSM("digest - don't care\n");
1182                     digest_check = 3;
1183                     dont_care++;
1184                 }
1185
1186                 /* check the counter */
1187                 fatal_counter_check = 3;
1188                 if (trans->fatal_counter_flag == COUNTER_FLAG_LT) {
1189                     /* count < name */
1190                     int fatal_count = getCountFromProperty(ctx, trans->fatal_counter_name);
1191
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
1197                     } else {
1198                         DEBUG_FSM("FATAL COUNTER %d < %d - MISS\n", ctx->count, fatal_count);
1199                         fatal_counter_check = -1;  // MISS
1200                     }
1201                 } else if (trans->fatal_counter_flag == COUNTER_FLAG_GE) {
1202                     /* count >= name */
1203                     int fatal_count = getCountFromProperty(ctx, trans->fatal_counter_name);
1204
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
1211                     } else {
1212                         DEBUG_FSM("FATAL COUNTER %d >= %d - MISS\n", ctx->count, fatal_count);
1213                         fatal_counter_check = -1;  // MISS
1214                     }
1215                 } else {
1216                     // DEBUG_FSM("counter - don't care\n");
1217                 }
1218
1219                 if (trans->counter_flag != COUNTER_FLAG_SKIP) {
1220                     int thisCount = 1 + trans->event_num;
1221                     int maxCount = getCountFromProperty(ctx, trans->counter_name);
1222                     if (maxCount < 0) {
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;
1234                     }
1235                 }
1236
1237                 /* Judge */
1238                 // if ((type_check == 1) && (digest_check == 1)) {
1239                 if ((type_check > 0) &&
1240                     (digest_check > 0) &&
1241                     (fatal_counter_check > 0) &&
1242                     (last_check > 0)) {
1243                     /* Hit this Trans */
1244                     /* If Final state, switch to next snapshot */
1245                     if (!strcmp(trans->target, UML2_SD_FINAL_STATE_STRING)) {
1246                         /* Final state */
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
1252                     }
1253
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);
1260                     hit = 1;
1261
1262                     /* next trans */
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);
1270
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");
1277
1278                                 rc = updateFsm(ctx, fsm, NULL);
1279
1280                                 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1281                                     rc = OPENPTS_FSM_FINISH;
1282                                 } else {
1283                                     ERROR("flash FSM was failed\n");
1284                                     rc = OPENPTS_FSM_ERROR;
1285                                 }
1286                             } else if (rc == OPENPTS_FSM_TRANSIT) {
1287                                 /* transit FSM */
1288                                 DEBUG_FSM("\t\tFlash FSM before transit \n");
1289
1290                                 rc = updateFsm(ctx, fsm, NULL);  // flash FSM
1291
1292                                 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1293                                     rc = OPENPTS_FSM_TRANSIT;
1294                                 } else {
1295                                     ERROR("updateFsm - FSM did not finish\n");
1296                                     rc = OPENPTS_FSM_ERROR;
1297                                 }
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);
1305                                 return rc;
1306                             } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1307                                 TODO("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1308                                 return rc;
1309                             } else if (rc == OPENPTS_FSM_SUCCESS) {
1310                                 rc = updateFsm(ctx, fsm, eventWrapper);
1311                             } else {
1312                                 TODO("rc = %d\n", rc);
1313                                 rc = updateFsm(ctx, fsm, eventWrapper);
1314                             }
1315                         }
1316                         break;
1317                     } else {
1318                         /* Trans */
1319                         DEBUG_FSM("[RM%02d-PCR%02d] %s -> %s - HIT (type=%d, digest=%d)\n",
1320                             fsm->level, fsm->pcr_index,
1321                             trans->source,
1322                             trans->target,
1323                             type_check, digest_check);
1324                         fsm->curr_state = getSubvertex(fsm, trans->target);
1325
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);
1333
1334                                 rc = updateFsm(ctx, fsm, NULL);
1335
1336                                 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1337                                     rc = OPENPTS_FSM_FINISH;
1338                                 } else {
1339                                     ERROR("updateFsm - flash FSM was failed, rc = %d\n", rc);
1340                                     rc = OPENPTS_FSM_ERROR;
1341                                 }
1342                             } else if (rc == OPENPTS_FSM_TRANSIT) {
1343                                 /* transit FSM */
1344                                 DEBUG_FSM("\t\tFlash FSM before transit \n");
1345
1346                                 rc = updateFsm(ctx, fsm, NULL);
1347
1348                                 if (rc == OPENPTS_FSM_FINISH_WO_HIT) {
1349                                     rc = OPENPTS_FSM_TRANSIT;
1350                                 } else {
1351                                     ERROR("updateFsm - FSM did not finish\n");
1352                                     rc = OPENPTS_FSM_ERROR;
1353                                 }
1354                             } else if (rc == OPENPTS_FSM_ERROR) {
1355                                 ERROR("updateFsm - FSM doActivity False, rc = %d\n", rc);
1356                                 return rc;
1357                             } else if (rc == OPENPTS_FSM_MIGRATE_EVENT) {
1358                                 // DEBUG("updateFsm - OPENPTS_FSM_MIGRATE_EVENT \n");
1359                                 return rc;
1360                             } else if (rc == OPENPTS_FSM_SUCCESS) {
1361                                 rc = OPENPTS_FSM_SUCCESS;
1362                             } else {
1363                                 /* */
1364                                 // DEBUG("rc = %d -> 0\n");  // fsm.c:1070 rc = 6 -> 0
1365                                 rc = OPENPTS_FSM_SUCCESS;
1366                             }
1367                         } else {
1368                             ERROR("curr_state is NULL, missing %s\n", trans->target);
1369                             rc = OPENPTS_FSM_ERROR;
1370                             return rc;
1371                         }
1372                         break;
1373                     }
1374                 } else {
1375                     // judge
1376                 }
1377             }  // if trans hit
1378             trans = trans->next;
1379         }  // while
1380     }  // DUMMY
1381
1382     /* MISS ALL? */
1383     if (hit == 0) {
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);
1387
1388         rc = OPENPTS_FSM_ERROR;
1389     }
1390
1391     /* success ? */
1392     return rc;
1393 }
1394
1395
1396 /**
1397  * Copy FSM
1398  *
1399  *   BHV->BIN
1400  *
1401  *   called from rm.c
1402  */
1403 OPENPTS_FSM_CONTEXT *copyFsm(OPENPTS_FSM_CONTEXT *src_fsm) {
1404     OPENPTS_FSM_CONTEXT * dst_fsm = NULL;
1405
1406     OPENPTS_FSM_Subvertex  *src_fsm_sub;
1407     OPENPTS_FSM_Subvertex  *dst_fsm_sub = NULL;
1408     OPENPTS_FSM_Subvertex  *dst_fsm_sub_prev = NULL;
1409
1410     OPENPTS_FSM_Transition *src_fsm_trans;
1411     OPENPTS_FSM_Transition *dst_fsm_trans = NULL;
1412     OPENPTS_FSM_Transition *dst_fsm_trans_prev = NULL;
1413
1414     int count;
1415
1416     DEBUG_FSM("copyFsm - start, PCR[%d]\n", src_fsm->pcrIndex);
1417
1418     if (src_fsm == NULL) {
1419         DEBUG("src_fsm == NULL, SKIP COPY\n");
1420         return NULL;
1421     }
1422
1423     /* New FSM */
1424     dst_fsm = (OPENPTS_FSM_CONTEXT *) xmalloc(sizeof(OPENPTS_FSM_CONTEXT));
1425     if (dst_fsm  == NULL) {
1426         return NULL;
1427     }
1428     memcpy((void *)dst_fsm, (void *)src_fsm, sizeof(OPENPTS_FSM_CONTEXT));
1429
1430     /* delete BHV-FSM smalloc link */
1431     dst_fsm->uml_file = NULL;
1432
1433     /* Copy Subvertexs */
1434     count = 0;
1435     src_fsm_sub = src_fsm->fsm_sub;
1436     if (src_fsm_sub == NULL) {
1437         ERROR("ERROR No FSM SUB\n");
1438         goto error;
1439     }
1440
1441     while (src_fsm_sub != NULL) {
1442         /* malloc new sub */
1443         dst_fsm_sub = (OPENPTS_FSM_Subvertex *)
1444             xmalloc_assert(sizeof(OPENPTS_FSM_Subvertex));
1445         /* copy */
1446         memcpy((void *)dst_fsm_sub,
1447                (void *)src_fsm_sub,
1448                sizeof(OPENPTS_FSM_Subvertex));
1449
1450         /* next ptr */
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;
1454         } else {  // 1st
1455             dst_fsm->fsm_sub = dst_fsm_sub;
1456         }
1457         dst_fsm_sub_prev = dst_fsm_sub;
1458
1459         /* BHV-BIN link */
1460         dst_fsm_sub->link = src_fsm_sub;
1461         src_fsm_sub->link = dst_fsm_sub;
1462
1463         /* go next */
1464         src_fsm_sub = src_fsm_sub->next;
1465         count++;
1466     }
1467
1468     DEBUG_FSM("%d Subvertex was copied\n", count);
1469
1470     /* Copy Transitions */
1471     count = 0;
1472     src_fsm_trans = src_fsm->fsm_trans;
1473
1474     if (src_fsm_trans == NULL) {
1475         ERROR("ERROR No FSM TRANS\n");
1476         goto error;
1477     }
1478
1479     while (src_fsm_trans != NULL) {
1480         /* malloc new sub */
1481         dst_fsm_trans = (OPENPTS_FSM_Transition *)
1482             xmalloc_assert(sizeof(OPENPTS_FSM_Transition));
1483         /* copy */
1484         memcpy((void *)dst_fsm_trans,
1485                (void *)src_fsm_trans,
1486                sizeof(OPENPTS_FSM_Transition));
1487
1488         /* ptr */
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;
1492         } else {  // 1st
1493             dst_fsm->fsm_trans = dst_fsm_trans;
1494         }
1495         dst_fsm_trans_prev = dst_fsm_trans;
1496
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;
1502         } else {
1503             ERROR("ERROR BHV trans %s source_subvertex is NULL\n",
1504                 src_fsm_trans->source);
1505         }
1506
1507         src_fsm_sub = src_fsm_trans->target_subvertex;
1508
1509         if (src_fsm_sub != NULL)
1510             dst_fsm_trans->target_subvertex = src_fsm_sub->link;
1511
1512         /* link between BIN and BHV FSM */
1513         dst_fsm_trans->link = src_fsm_trans;
1514         src_fsm_trans->link = dst_fsm_trans;
1515
1516         /* go next */
1517         src_fsm_trans = src_fsm_trans->next;
1518         count++;
1519     }
1520
1521     DEBUG_FSM("%d Transition was copied\n", count);
1522     DEBUG_FSM("copyFsm - done\n");
1523
1524     return dst_fsm;
1525
1526   error:
1527     if (dst_fsm != NULL) {
1528         xfree(dst_fsm);
1529     }
1530     return NULL;
1531 }
1532
1533 /**
1534
1535   S ----T--->Old_Sub
1536
1537   S ----T--->New_Sub(--->Old_Sub)
1538
1539           T(loop)
1540           |
1541   A---T---B---C
1542      
1543
1544           T(loop)
1545            |   A
1546            V   |
1547   A---T---BN   B--C    << NG
1548
1549
1550 */
1551 int changeTargetSubvertex(
1552         OPENPTS_FSM_CONTEXT *fsm_ctx,
1553         OPENPTS_FSM_Subvertex *old_sub,    // B
1554         OPENPTS_FSM_Subvertex *new_sub) {  // BN
1555     int rc = 0;
1556     OPENPTS_FSM_Transition *fsm_trans;
1557     int count = 0;
1558
1559     fsm_trans = fsm_ctx->fsm_trans;
1560
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),
1567                     "%s", new_sub->id);
1568         }
1569         fsm_trans = fsm_trans->next;
1570         count++;
1571     }
1572
1573     return rc;
1574 }
1575
1576 /**
1577
1578   S ----T--->Old_Sub
1579
1580   S ----T--->New_Sub(--->Old_Sub)
1581
1582           T(loop)
1583           |
1584   A---T---B---C
1585      
1586
1587                T(loop)
1588                |
1589   A---T---BN   B--C    << OK
1590
1591
1592 */
1593 int changeTransTargetSubvertex(
1594         OPENPTS_FSM_CONTEXT *fsm_ctx,
1595         OPENPTS_FSM_Subvertex *old_sub,    // B
1596         OPENPTS_FSM_Subvertex *new_sub) {  // BN
1597     int rc = 0;
1598     OPENPTS_FSM_Transition *fsm_trans;
1599     int count = 0;
1600
1601     fsm_trans = fsm_ctx->fsm_trans;
1602
1603     /* check all trans to B */
1604     while (fsm_trans != NULL) {
1605         if (fsm_trans->target_subvertex == old_sub) {
1606             /* HIT */
1607             if (fsm_trans->target_subvertex == fsm_trans->source_subvertex) {
1608                 // LOOP, belong to old sub
1609                 DEBUG_FSM("changeTransTargetSubvertex - keep loop '%s) \n",
1610                     fsm_trans->source);
1611             } else {
1612                 // move to new sub
1613                 fsm_trans->target_subvertex = new_sub;
1614                 snprintf(fsm_trans->target,
1615                          sizeof(fsm_trans->target),
1616                         "%s", new_sub->id);
1617                 DEBUG_FSM("changeTransTargetSubvertex - trans move to new sub (%s -> %s)\n",
1618                     fsm_trans->source, fsm_trans->target);
1619             }
1620         }
1621         fsm_trans = fsm_trans->next;
1622         count++;
1623     }
1624
1625     return rc;
1626 }
1627
1628
1629 /**
1630
1631 20100617 new alg
1632
1633 Behavior FSM
1634
1635                
1636 FSM   [A]---Ta---[B]---Tc---[C]
1637                   |
1638                  Tb(loop)
1639
1640
1641                   |<--loop-->|
1642 FSM   [A]---Ta---[B]---Tb---[B]---Tc---[C]
1643             |          |          |
1644 EW          e0       e1-e3        e4
1645                       (3)
1646
1647 Transfer Behavior to Binary FSM
1648
1649
1650                               |<--loop-->|
1651 FSM   [A]---Ta---[B0]---Tb0--[B]---Tb---[B]---Tc---[C]
1652             |           |           |         |
1653 EW          e0          e1         e2-e3      e4
1654                                    (2)
1655
1656                                           |<--loop-->|
1657 FSM   [A]---Ta---[B0]---Tb0--[B1]---tb1--[B]---Tb---[B]---Tc---[C]
1658             |           |           |          |          |
1659 EW          e0          e1          e2         e3         e4
1660                                                (1)
1661
1662
1663 FSM   [A]---Ta---[B0]---Tb0--[B1]---tb1--[B2]---Tb---[B]---Tc---[C]
1664             |           |           |           |          |
1665 EW          e0          e1          e2          e3         e4
1666                                                 (0)
1667
1668 */
1669
1670 int insertFsmNew(
1671         OPENPTS_FSM_CONTEXT *fsm_ctx,       // BIN-FSM
1672         OPENPTS_FSM_Transition *fsm_trans,  // target Trans
1673         OPENPTS_PCR_EVENT_WRAPPER *eventWrapper) {
1674     int rc =0;
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;
1681
1682     DEBUG_FSM("insertFsm - start\n");
1683
1684     /* check input */
1685     ASSERT(NULL != fsm_trans, "ERROR fsm_trans == NULL\n");
1686
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);
1690         return -1;
1691     }
1692     if (fsm_trans->target_subvertex == NULL) {
1693         ERROR("ERROR fsm_trans->target_subvertex == NULL\n");
1694         return -1;
1695     }
1696
1697     if (eventWrapper == NULL) {
1698         return -1;
1699     }
1700
1701     /* start */
1702
1703     event = eventWrapper->event;
1704
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);
1709
1710         /* Base subvertex, B */
1711         dst_sub = fsm_trans->target_subvertex;
1712
1713         /* Add new subvertex, BN (->B) */
1714
1715         new_sub = (OPENPTS_FSM_Subvertex *)
1716             xmalloc(sizeof(OPENPTS_FSM_Subvertex));
1717         if (new_sub == NULL) {
1718             return -1;
1719         }
1720         /* copy */
1721         memcpy(new_sub,
1722                fsm_trans->source_subvertex,
1723                sizeof(OPENPTS_FSM_Subvertex));
1724
1725         snprintf(new_sub->id,  sizeof(new_sub->id),
1726                  "%s_LOOP_%d",
1727                  dst_sub->id, fsm_trans->copy_num);
1728         snprintf(new_sub->name, sizeof(new_sub->name),
1729                  "%s_LOOP_%d",
1730                  dst_sub->name, fsm_trans->copy_num);
1731         fsm_ctx->subvertex_num++;
1732
1733         /* Update the subvetex chain, A-B => A-BN-B  */
1734
1735         /* A <-> BN */
1736         prev_sub       = dst_sub->prev;
1737         prev_sub->next  = new_sub;
1738         new_sub->prev  = prev_sub;
1739
1740         /* BN <-> B */
1741         new_sub->next  = dst_sub;
1742         dst_sub->prev  = new_sub;
1743
1744         /* Any trans to B move to BN */
1745         // BN->B trans is open
1746         rc = changeTransTargetSubvertex(
1747                 fsm_ctx,
1748                 dst_sub,   // B
1749                 new_sub);  // BN
1750
1751         DEBUG_FSM("\tnew sub id = %s, name = %s added\n",
1752             new_sub->id, new_sub->name);
1753
1754         /*Next Updatre the Transition */
1755
1756         if (fsm_trans->event_num > 1) {
1757             /* Many loops, B-B -> BN-B-B, add new Trans between BN and B */
1758
1759             /* malloc */
1760             new_trans = (OPENPTS_FSM_Transition*)
1761                 xmalloc(sizeof(OPENPTS_FSM_Transition));
1762             if (new_trans == NULL) {
1763                 return -1;
1764             }
1765             /* copy */
1766             memcpy(new_trans,
1767                    fsm_trans,
1768                    sizeof(OPENPTS_FSM_Transition));
1769
1770             /* update the transition struct chain */
1771
1772             prev_trans = fsm_trans->prev;
1773             prev_trans->next = new_trans;
1774             new_trans->prev  = prev_trans;
1775
1776             new_trans->next = fsm_trans;
1777             fsm_trans->prev = new_trans;
1778
1779             fsm_ctx->transition_num++;
1780
1781             /* Update new Trans  */
1782             new_trans->source_subvertex = new_sub;
1783             snprintf(new_trans->source, sizeof(new_trans->source),
1784                      "%s", new_sub->id);
1785
1786             new_trans->target_subvertex = dst_sub;
1787             snprintf(new_trans->target, sizeof(new_trans->target),
1788                      "%s", dst_sub->id);
1789
1790             /* Update event link */
1791             // trans -> event
1792             new_trans->event = eventWrapper;  // TSS_PCR_EVENT_WRAPPER
1793             new_trans->event_num = 1;
1794             // event -> trans
1795             eventWrapper->fsm_trans = new_trans;
1796
1797             /* Update Original Trans */
1798             fsm_trans->event_num--;
1799             fsm_trans->copy_num++;
1800
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) {
1807                     return -1;
1808                 }
1809                 memcpy(new_trans->digest, event->rgbPcrValue, event->ulPcrValueLength);
1810             } else {
1811                 DEBUG_FSM("Changing digestFlag == DIGEST_FLAG_TRANSPARENT\n");
1812                 new_trans->digestFlag = DIGEST_FLAG_TRANSPARENT;
1813             }
1814
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);
1819
1820         } else if (fsm_trans->event_num == 1) {
1821             /* Last loop, B-B -> BN-B, just update the trans */
1822
1823             /* Update new Trans  */
1824             fsm_trans->source_subvertex = new_sub;
1825             snprintf(fsm_trans->source, sizeof(new_trans->source),
1826                      "%s", new_sub->id);
1827
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) {
1834                     return -1;
1835                 }
1836                 memcpy(fsm_trans->digest, event->rgbPcrValue, event->ulPcrValueLength);
1837             } else {
1838                 fsm_trans->digestFlag = DIGEST_FLAG_TRANSPARENT;
1839             }
1840
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);
1845         } else {
1846             ASSERT(0, "BAD LOOP\n");
1847         }
1848     } else {
1849         ASSERT(0, "Not a loop");
1850     }
1851
1852     DEBUG_FSM("insertFsm - done\n");
1853     return rc;
1854 }
1855
1856
1857 /**
1858  *  remove the trans from transition chain
1859  */
1860 int removeFsmTrans(
1861         OPENPTS_FSM_CONTEXT *fsm_ctx,
1862         OPENPTS_FSM_Transition * trans) {
1863     int rc =0;
1864     OPENPTS_FSM_Transition * trans_prev;
1865     OPENPTS_FSM_Transition * trans_next;
1866
1867     trans_prev = trans->prev;
1868     trans_next = trans->next;
1869
1870     /* remove link */
1871     if (trans_prev != NULL) {
1872         trans_prev->next = trans_next;
1873     } else {  // 1st trans
1874         fsm_ctx->fsm_trans = trans_next;
1875     }
1876
1877     if (trans_next != NULL) {
1878         trans_next->prev = trans_prev;
1879     } else {  // last trans
1880         //
1881     }
1882
1883     // TODO(munetoh) Free
1884
1885     return rc;
1886 }
1887
1888
1889 /**
1890  * remove FSM subvertex
1891  */
1892 int removeFsmSub(
1893         OPENPTS_FSM_CONTEXT *fsm_ctx,
1894         OPENPTS_FSM_Subvertex * sub) {
1895     int rc =0;
1896
1897     OPENPTS_FSM_Subvertex * sub_prev;
1898     OPENPTS_FSM_Subvertex * sub_next;
1899
1900     sub_prev = sub->prev;
1901     sub_next = sub->next;
1902
1903     /* remove link */
1904     if (sub_prev != NULL) {
1905         sub_prev->next = sub_next;
1906     } else {  // 1st sub
1907         fsm_ctx->fsm_sub = sub_next;
1908     }
1909     if (sub_next != NULL) {
1910         sub_next->prev = sub_prev;
1911     } else {  // last sub
1912         //
1913     }
1914
1915     // TODO(munetoh) Free
1916
1917     return rc;
1918 }
1919
1920 /**
1921  *  clean up FSM
1922  *   - delete unused BHV Transitions
1923  *   - delete unused BHV Subvertex
1924  *
1925  */
1926 int cleanupFsm(OPENPTS_FSM_CONTEXT *fsm_ctx) {
1927     int rc = 0;
1928     int count = 0;
1929     int hit;
1930     OPENPTS_FSM_Transition * trans;
1931     OPENPTS_FSM_Transition * trans_next;
1932
1933     OPENPTS_FSM_Subvertex * sub;
1934     OPENPTS_FSM_Subvertex * sub_next;
1935
1936     ASSERT(NULL != fsm_ctx, "ERROR No FSM TRANS\n");
1937
1938     DEBUG_FSM("cleanupFsm - start, PCR[%d]\n", fsm_ctx->pcrIndex);
1939
1940     /* Delete BHV Transitions */
1941
1942     trans = fsm_ctx->fsm_trans;
1943
1944     if (trans == NULL) {
1945         ERROR("ERROR No FSM TRANS\n");
1946         return -1;
1947     }
1948
1949     count = 0;
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
1956             if (rc < 0) {
1957                 ERROR("removeFsmTrans of %s -> %s was failed\n",
1958                       trans->source, trans->target);
1959                 return -1;
1960             }
1961             count++;
1962         } else {
1963             // printf("MISS \n");
1964         }
1965         trans = trans_next;
1966     }
1967
1968     DEBUG_FSM("cleanupFsm - %d trans was removed\n", count);
1969     fsm_ctx->transition_num -= count;
1970
1971     /* Delete state which does not have incomming trans */
1972     sub = fsm_ctx->fsm_sub;
1973     if (sub == NULL) {
1974         ERROR("ERROR No FSM SUB\n");
1975         return -1;
1976     }
1977
1978     count = 0;
1979     while (sub != NULL) {
1980         sub_next = sub->next;
1981         if (!strcmp(sub->id, "Start")) {
1982             // START state
1983         } else if (!strcmp(sub->id, "Final")) {
1984             // FINAL state
1985         } else {
1986             // Other states
1987             /* check trans */
1988             trans = fsm_ctx->fsm_trans;
1989             hit = 0;
1990             while (trans != NULL) {
1991                 if (!strcmp(trans->target, sub->id)) {
1992                     hit++;
1993                     if (trans->target_subvertex == sub) {
1994                         // hit++;
1995                         // TODO(munetoh)
1996                         //   EV_S_CRTM_VERSION is not detected. BAD link:-(
1997                         // break;
1998                     } else {
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);
2004                     }
2005                 }
2006                 trans = trans->next;
2007             }
2008
2009             if (hit == 0) {
2010                 DEBUG_FSM("\tSub %p  id=%s name=%s not used\n",
2011                           sub, sub->id, sub->name);
2012                 /* remove sub */
2013                 removeFsmSub(fsm_ctx, sub);
2014             }
2015         }
2016
2017         sub = sub_next;
2018     }
2019
2020     DEBUG_FSM("cleanupFsm - %d trans was removed\n", count);
2021     fsm_ctx->subvertex_num -= count;
2022
2023
2024     /* Again, Delete trans which does not have source target */
2025
2026     trans = fsm_ctx->fsm_trans;
2027
2028     if (trans == NULL) {
2029         ERROR("No FSM TRANS\n");
2030         return -1;
2031     }
2032
2033     count = 0;
2034     while (trans != NULL) {
2035         trans_next = trans->next;
2036
2037         sub = getSubvertex(fsm_ctx, trans->source);
2038         if (sub == NULL) {
2039             DEBUG_FSM("\tMISSING SOURCE %s->%s\n",
2040                        trans->source, trans->target);
2041             removeFsmTrans(fsm_ctx, trans);
2042             count++;
2043         } else {
2044         }
2045
2046         trans = trans_next;
2047     }
2048
2049
2050     DEBUG_FSM("cleanupFsm - %d trans was removed - missing source\n", count);
2051     fsm_ctx->transition_num -= count;
2052
2053
2054     DEBUG_FSM("cleanupFsm - done\n");
2055     return rc;
2056 }
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068 /**
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
2073  *
2074  * Return
2075  *   PTS_SUCCESS
2076  *   PTS_OS_ERROR
2077  *   PTS_INTERNAL_ERROR
2078  */
2079 int writeDotModel(OPENPTS_FSM_CONTEXT *ctx, char * filename) {
2080     int rc = PTS_SUCCESS;
2081     FILE *fp;
2082     int j;
2083     OPENPTS_FSM_Subvertex *sptr;
2084     OPENPTS_FSM_Transition *ptr;
2085
2086     DEBUG("writeDotModel - start %s\n", filename);
2087
2088     /* check */
2089     ASSERT(NULL != ctx, "writeDotModel() - OPENPTS_FSM_CONTEXT is NULL\n");
2090
2091     if (filename == NULL) {
2092         fp = stdout;
2093     } else {
2094         if ((fp = fopen(filename, "w")) == NULL) {
2095             ERROR("fopen fail %s\n", filename);
2096             return PTS_OS_ERROR;
2097         }
2098     }
2099
2100     DEBUG_FSM("Subvertex  num= %d \n", ctx->subvertex_num);
2101     DEBUG_FSM("Transition num= %d \n", ctx->transition_num);
2102
2103     fprintf(fp, "digraph G {\n");
2104
2105     /* Subvertex */
2106     sptr =ctx->fsm_sub;
2107
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",
2116                     sptr->id,
2117                     sptr->name,
2118                     sptr->action);
2119         } else {
2120             fprintf(fp, "\t%s [label=\"%s\"];\n",
2121                     sptr->id,
2122                     sptr->name);
2123         }
2124         sptr = sptr->next;
2125     }
2126
2127     /* Transition */
2128     ptr = ctx->fsm_trans;
2129
2130     while (ptr != NULL) {
2131         DEBUG_FSM("\tTransition = (%s->%s)\n", ptr->source, ptr->target);
2132         /* cond */
2133         if (ptr->digestFlag == DIGEST_FLAG_EQUAL) {  // BIN
2134             fprintf(fp, "\t%s -> %s [label=\"",
2135                     ptr->source,
2136                     ptr->target);
2137             /* eventytpte */
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);
2142             }
2143             /* digest */
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
2148             }
2149             fprintf(fp, "\"];\n");
2150         } else {  // BHV
2151             fprintf(fp, "\t%s -> %s [label=\"%s\"];\n",
2152                     ptr->source,
2153                     ptr->target,
2154                     ptr->cond);
2155         }
2156         ptr = ptr->next;
2157     }
2158
2159     fprintf(fp, "}\n");
2160
2161     fclose(fp);
2162
2163     DEBUG("writeDotModel - done\n");
2164
2165     return rc;
2166 }
2167
2168 /**
2169  * write CSV file, RFC 4180 style
2170  *
2171  * @param ctx FSM_CONTEXT
2172  * @param filename csv filename to write
2173  */
2174 int writeCsvTable(OPENPTS_FSM_CONTEXT *ctx, char * filename) {
2175     int rc = 0;
2176     FILE *fp;
2177     int i;
2178     OPENPTS_FSM_Transition *ptr;
2179
2180     /* check */
2181     if (filename == NULL) {
2182         ERROR("writeCsvTable - filename is NULL\n");
2183         return -1;
2184     }
2185
2186     /* Open */
2187     if ((fp = fopen(filename, "w")) == NULL) {
2188         return -1;
2189     }
2190
2191     fprintf(fp,
2192         "current state,condition type(hex), condition digest,next state\n");
2193
2194     ptr = ctx->fsm_trans;
2195     for (i = 0; i < ctx->transition_num; i++) {
2196         fprintf(fp, "%s, ", getSubvertexName(ctx, ptr->source));
2197
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);
2202         } else {
2203             fprintf(fp, ",");
2204         }
2205
2206
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]);
2210             fprintf(fp, ",");
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!,");
2215         } else {
2216             fprintf(fp, ",");
2217         }
2218         fprintf(fp, "%s\n", getSubvertexName(ctx, ptr->target));
2219
2220         ptr = ptr->next;
2221     }
2222
2223     /* close */
2224     fclose(fp);
2225     return rc;
2226 }
2227
2228
2229 /**
2230  * print FSM State Diagram
2231  *
2232  * @param ctx FSM_CONTEXT
2233  */
2234 int printFsmModel(OPENPTS_FSM_CONTEXT *ctx) {
2235     int rc = 0;
2236     int i, j;
2237     OPENPTS_FSM_Transition *ptr;
2238
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");
2244
2245
2246     ptr = ctx->fsm_trans;
2247     for (i = 0; i < ctx->transition_num; i++) {
2248         if (ptr == NULL) {
2249             ERROR("PTR is NULL at %d\n", i);
2250             return -1;
2251         }
2252         OUTPUT("%5d ", i);
2253         OUTPUT("%30s ", getSubvertexName(ctx, ptr->source));
2254
2255         if (ptr->eventTypeFlag == 1) {
2256             OUTPUT(" 0x%08x  ", ptr->eventType);
2257         } else if (ptr->eventTypeFlag == 1) {
2258             OUTPUT("!0x%08x  ", ptr->eventType);
2259         } else {
2260             OUTPUT("             ");
2261         }
2262
2263         if (ptr->digestFlag == DIGEST_FLAG_EQUAL) {
2264             OUTPUT("0x");
2265             for (j = 0; j < ptr->digestSize; j++) OUTPUT("%02x", ptr->digest[j]);
2266             OUTPUT(" ");
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? */
2271             OUTPUT("                                           ");
2272         } else {
2273             OUTPUT("                                           ");
2274         }
2275         OUTPUT("%-30s\n", getSubvertexName(ctx, ptr->target));
2276
2277         ptr = ptr->next;
2278     }
2279
2280     return rc;
2281 }
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293