1#!/bin/sh 2# Copyright 2015 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6# Pull out basic typdefs. 7cat $1 | 8 # Mark types tables and section boundaries. 9 sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' | 10 sed 's/^Table [0-9]* . Definition of .*Types[^.]*$/_TYPES/' | 11 # Keep only table sections. 12 awk '/^_TYPES$/,/^_SECTION_BOUNDARY$/ { print $0; }' | 13 sed 's/^_TYPES$//' | 14 sed 's/^_SECTION_BOUNDARY$//' | 15 # Remove headers and footers. 16 sed 's/^.*Trusted Platform Module Library.*$//' | 17 sed 's/^.*Part 2: Structures.*$//' | 18 sed 's/^.*Family .2.0..*$//' | 19 sed 's/^.*Level 00 Revision.*$//' | 20 sed 's/^.*Published.*$//' | 21 sed 's/^.*Copyright.*$//' | 22 sed 's/^.*Page [0-9].*$//' | 23 sed 's/^.*October 31, 2013.*$//' | 24 # Remove table headers. 25 sed 's/^Type$//' | sed 's/^Name$//' | sed 's/^Description$//' | 26 # Remove leading spaces. 27 sed 's/^[ ][ ]*//' | 28 # Remove empty lines. 29 sed '/^$/d' | 30 # Mark begin and end and filter types. 31 awk ' 32 BEGIN { print "_BEGIN_TYPES"; state = 0; } 33 /^[^ ]*$/ { if (!state) { print "_OLD_TYPE " $0; state = 1; } 34 else { print "_NEW_TYPE " $0; state = 0; } } 35 END { print "_END"; } 36 ' | 37 # Sanity check. The format should now follow this grammar: 38 # Format:Begin||Typedef*||End 39 # Begin:_BEGIN_TYPES\n 40 # End:_END\n 41 # Typedef:OldType||NewType 42 # OldType:_OLD_TYPE <type>\n 43 # NewType:_NEW_TYPE <type>\n 44 awk ' 45 BEGIN { RS = ""; } 46 $0 !~ /_BEGIN_TYPES\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n)*_END/ { 47 print "_ERROR: Format check failed."; } 48 { print $0; } 49 ' 50 51# Pull out constant values. 52cat $1 | 53 # Mark constants tables and section boundaries. 54 sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' | 55 sed 's/^Table [0-9]* . Definition of \(.*\) Constants[^.]*$/_CONSTANTS \1/' | 56 # Keep only table sections. 57 awk '/^_CONSTANTS .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' | 58 sed 's/^_SECTION_BOUNDARY$//' | 59 # Remove headers and footers. 60 sed 's/^.*Trusted Platform Module Library.*$//' | 61 sed 's/^.*Part 2: Structures.*$//' | 62 sed 's/^.*Family .2.0..*$//' | 63 sed 's/^.*Level 00 Revision.*$//' | 64 sed 's/^.*Published.*$//' | 65 sed 's/^.*Copyright.*$//' | 66 sed 's/^.*Page [0-9].*$//' | 67 sed 's/^.*October 31, 2013.*$//' | 68 # Remove table headers. 69 sed 's/^Name$//' | sed 's/^Value$//' | sed 's/^Comments$//' | 70 # Remove leading spaces. 71 sed 's/^[ ][ ]*//' | 72 # Remove empty lines. 73 sed '/^$/d' | 74 # Mark begin and end. 75 awk ' 76 BEGIN { print "_BEGIN_CONSTANTS"; } 77 { print $0; } 78 END { print "_END"; } 79 ' | 80 # Mark type. 81 awk ' 82 BEGIN { FS = "[ ()]+"; } 83 { print $0; } 84 /^_CONSTANTS \(\w*\) .*$/ { print "_OLD_TYPE " $2; 85 print "_NEW_TYPE " $NF; } 86 ' | 87 # Mark names and error return type. 88 sed 's/^\(TPM_[_A-Z0-9a]*\)$/_NAME \1/' | 89 sed 's/^\(TPM_CC_[_A-Z0-9a-z]*\)$/_NAME \1/' | 90 sed 's/^\(RC_[_A-Z0-9]*\)$/_NAME \1/' | 91 sed 's/^\(PT_[_A-Z0-9]*\)$/_NAME \1/' | 92 sed 's/^\(HR_[_A-Z0-9]*\)$/_NAME \1/' | 93 sed 's/^\([_A-Z0-9]*FIRST\)$/_NAME \1/' | 94 sed 's/^\([_A-Z0-9]*LAST\)$/_NAME \1/' | 95 sed 's/^\(PLATFORM_PERSISTENT\)$/_NAME \1/' | 96 sed 's/^\(#TPM_RC[_A-Z0-9]*\)$/_RETURN \1/' | 97 # Keep only names and return types 98 awk ' 99 BEGIN { last_line_was_name = 0; 100 return_defined = 1; 101 FS = " |#"; } 102 /^_BEGIN_CONSTANTS$/ { print $0; } 103 /^_OLD_TYPE .*$/ { if (!return_defined) { print "_RETURN TPM_RC_VALUE"; } 104 return_defined = 0; 105 print $0 } 106 /^_NEW_TYPE .*$/ { print $0; } 107 /^_NAME .*$/ { if (last_line_was_name) { 108 last_line_was_name = 0; 109 if ($0 !~ /[A-Z_0-9x +]*/) { print "_ERROR: Invalid value"; } } 110 else { last_line_was_name = 1; print $0; } } 111 /^_RETURN .*$/ { print "_RETURN " $3; 112 return_defined = 1; } 113 /^[^_].*$/ { if (last_line_was_name) { 114 last_line_was_name = 0; 115 if ($0 !~ /[A-Z_0-9x +]*/) { print "_ERROR: Invalid value"; } } } 116 /^_END$/ { if (!return_defined) { print "_RETURN TPM_RC_VALUE"; } 117 print $0; } 118 ' | 119 # Sanity check. The format should now follow this grammar: 120 # Format:Begin||TableBlock*||End 121 # Begin:_BEGIN_CONSTANTS\n 122 # End:_END\n 123 # TableBlock:Typedef||Name*||Return 124 # Name:_NAME <name>\n 125 # Return:_RETURN <name>\n 126 # Typedef:OldType||NewType 127 # OldType:_OLD_TYPE <type>\n 128 # NewType:_NEW_TYPE <type>\n 129 awk ' 130 BEGIN { RS = ""; } 131 $0 !~ /_BEGIN_CONSTANTS\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n(_NAME[^\n]*\n)*_RETURN[^\n]*\n)*_END/ { 132 print "_ERROR: Format check failed."; } 133 { print $0; } 134 ' 135 136# Pull out attribute structs. 137cat $1 | 138 # Mark reserved bits. 139 sed 's/^\([0-9]\+:\?[0-9]* Reserved\)$/_RESERVED \1/' | 140 awk ' 141 BEGIN { print "_BEGIN_ATTRIBUTE_STRUCTS"; 142 FS = "[ ()]+|:"; 143 in_attribute = 0; } 144 /^Table [0-9]* . Definition of \([A-Z_0-9]*\) TPM[A-Z_]* Bits[^.]*$/ { 145 print "_OLD_TYPE " $6; 146 print "_NEW_TYPE " $7; 147 in_attribute = 1; } 148 /^_RESERVED .*$/ { if (in_attribute && NF == 4) { 149 print "_RESERVED " $3 "_" $2; } 150 else if (in_attribute) { 151 print "_RESERVED " $2; } } 152 END { print "_END"; } 153 ' | 154 # Sanity check. The format should now follow this grammar: 155 # Format:Begin||TableBlock*||End 156 # Begin:_BEGIN_ATTRIBUTE_STRUCTS\n 157 # End:_END\n 158 # TableBlock:Typedef||Reserved* 159 # Reserved:_RESERVED <value>(_<value>)?\n 160 # Typedef:OldType||NewType 161 # OldType:_OLD_TYPE <type>\n 162 # NewType:_NEW_TYPE <type>\n 163 awk ' 164 BEGIN { RS = ""; } 165 $0 !~ /_BEGIN_ATTRIBUTE_STRUCTS\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n(_RESERVED[^\n]*\n)*)*_END/ { 166 print "_ERROR: Format check failed."; } 167 { print $0; } 168 ' 169 170# Pull out interface types. 171cat $1 | 172 # Mark interface tables and section boundaries. 173 sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' | 174 sed 's/^Table [0-9]* . Definition of \(.*\) Type[^.s]*$/_INTERFACES \1/' | 175 # Keep only table sections. 176 awk '/^_INTERFACES .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' | 177 sed 's/^_SECTION_BOUNDARY$//' | 178 # Remove headers and footers. 179 sed 's/^.*Trusted Platform Module Library.*$//' | 180 sed 's/^.*Part 2: Structures.*$//' | 181 sed 's/^.*Family .2.0..*$//' | 182 sed 's/^.*Level 00 Revision.*$//' | 183 sed 's/^.*Published.*$//' | 184 sed 's/^.*Copyright.*$//' | 185 sed 's/^.*Page [0-9].*$//' | 186 sed 's/^.*October 31, 2013.*$//' | 187 # Remove table headers. 188 sed 's/^Type$//' | sed 's/^Name$//' | sed 's/^Description$//' | 189 # Remove leading spaces. 190 sed 's/^[ ][ ]*//' | 191 # Remove empty lines. 192 sed '/^$/d' | 193 # Mark begin and end. 194 awk ' 195 BEGIN { print "_BEGIN_INTERFACES"; } 196 { print $0; } 197 END { print "_END"; } 198 ' | 199 # Mark type. 200 awk ' 201 BEGIN { FS = "[ ()]+"; } 202 { print $0; } 203 /^_INTERFACES \(\w*\) .*$/ { print "_OLD_TYPE " $2; 204 print "_NEW_TYPE " $NF; } 205 /^_INTERFACES {[A-Z0-9]*} \(\w*\) .*$/ { print "_OLD_TYPE " $3; 206 print "_NEW_TYPE " $NF; } 207 ' | 208 # Mark names, bounds, conditional values, and return values. 209 sed 's/^\(TPM_[_A-Z0-9a]*\)$/_NAME \1/' | 210 sed 's/^\(TPM_CC_[_A-Z0-9a-z]*\)$/_NAME \1/' | 211 sed 's/^\(RC_[_A-Z0-9]*\)$/_NAME \1/' | 212 sed 's/^\(PT_[_A-Z0-9]*\)$/_NAME \1/' | 213 sed 's/^\(HR_[_A-Z0-9]*\)$/_NAME \1/' | 214 sed 's/^\([_A-Z0-9]*FIRST\)$/_NAME \1/' | 215 sed 's/^\([_A-Z0-9]*LAST\)$/_NAME \1/' | 216 sed 's/^\(PLATFORM_PERSISTENT\)$/_NAME \1/' | 217 sed 's/^\(NO\)$/_NAME \1/' | 218 sed 's/^\(YES\)$/_NAME \1/' | 219 sed 's/^\({[_A-Z0-9]*:[_A-Z0-9]*}\)$/_BOUND \1/' | 220 sed 's/^\(+[_A-Z0-9]*\)$/_CONDITIONAL \1/' | 221 sed 's/^\(#TPM_RC[_A-Z0-9]*\)$/_RETURN \1/' | 222 sed 's/^\(\$.*\)$/_SUBSTITUTE \1/' | 223 awk ' 224 BEGIN { print "_BEGIN_INTERFACES"; 225 FS = " |:|{|}|#|+"; 226 ret = 1; } 227 /^_OLD_TYPE .*$/ { if (!ret) { print "_RETURN TPM_RC_VALUE"; } 228 ret = 0; } 229 /^_.*_TYPE .*$/ { print $0; } 230 /^_NAME .*$/ { print $0; } 231 /^_SUBSTITUTE .*$/ { $2 = substr($2, 2, length($2)-1); 232 print $0; } 233 /^_BOUND .*$/ { print "_MIN " $3; 234 print "_MAX " $4; } 235 /^_CONDITIONAL .*$/ { print "_CONDITIONAL " $3; } 236 /^_RETURN .*$/ { print "_RETURN " $3; 237 ret = 1; } 238 END { print "_END"; } 239 ' | 240 # Sanity check. The format should now follow this grammar: 241 # Format:Begin||Tableblock*||End 242 # Begin:_BEGIN_INTERFACES\n 243 # End:_END\n 244 # Tableblock: Typedef||(Subval?|Name*)||Bound*||Conditional?||Return 245 # Name:_NAME <name>\n 246 # Subval:_SUBSTITUTE <name>\n 247 # Bound:Min||Max 248 # Min:_MIN <name>\n 249 # Max:_MAX <name>\n 250 # Conditional:_CONDITIONAL <name>\n 251 # Return:_RETURN <name>\n 252 # Typedef:OldType||NewType 253 # OldType:_OLD_TYPE <type>\n 254 # NewType:_NEW_TYPE <type>\n 255 awk ' 256 BEGIN { RS = ""; } 257 $0 !~ /_BEGIN_INTERFACES\n(_OLD_TYPE[^\n]*\n_NEW_TYPE[^\n]*\n(_NAME[^\n]*\n)*(_SUBSTITUTE[^\n]*\n)?(_MIN[^\n]*\n_MAX[^\n]*\n)*(_CONDITIONAL[^\n]*\n)?(_RETURN[^\n]*\n)?)*_END/ { 258 print "_ERROR: Format check failed."; } 259 { print $0; } 260 ' 261# Pull out structures. 262cat $1 | 263 # Mark tables and section boundaries. 264 sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' | 265 sed 's/^Table [0-9]* . Definition of \(.*\) Structure[^.]*$/_STRUCTURE \1/' | 266 # Keep only table sections. 267 awk '/^_STRUCTURE .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' | 268 sed 's/^_SECTION_BOUNDARY$//' | 269 # Remove headers and footers. 270 sed 's/^.*Trusted Platform Module Library.*$//' | 271 sed 's/^.*Part 2: Structures.*$//' | 272 sed 's/^.*Family .2.0..*$//' | 273 sed 's/^.*Level 00 Revision.*$//' | 274 sed 's/^.*Published.*$//' | 275 sed 's/^.*Copyright.*$//' | 276 sed 's/^.*Page [0-9].*$//' | 277 sed 's/^.*October 31, 2013.*$//' | 278 # Remove table headers. 279 sed 's/^Parameter$//' | sed 's/^Type$//' | sed 's/^Description$//' | 280 # Remove leading spaces. 281 sed 's/^[ ][ ]*//' | 282 # Remove empty lines. 283 sed '/^$/d' | 284 # Mark begin and end. 285 awk ' 286 BEGIN { print "_BEGIN_STRUCTURES"; } 287 { print $0; } 288 END { print "_END"; } 289 ' | 290 # Mark field types. 291 sed 's/^\(+*TPM[_A-Z0-9+]*\)$/_TYPE \1/' | 292 sed 's/^\(UINT[0-9]*\)$/_TYPE \1/' | 293 sed 's/^\(BYTE*\)$/_TYPE \1/' | 294 # Mark field names and associated decorations 295 awk ' 296 BEGIN { last_line = ""; 297 FS = ":| |{|}|+|#"; } 298 /^_.*$/ { if ($1 != "_TYPE") { print $0; } } 299 /^_TYPE \+[A-Z0-9_]*$/ { print $1 " " $3; 300 prefix = substr($3, 1, 4); 301 if (last_line != "" && prefix == "TPMI") { 302 print "_NAME " last_line " _PLUS"; 303 } else if (last_line != "") { 304 print "_NAME " last_line; 305 } else { print "_ERROR: Type with no name"; } 306 last_line = ""; } 307 /^_TYPE [A-Z0-9_]*\+$/ { print $1 " " $2; 308 prefix = substr($2, 1, 4); 309 if (last_line != "" && prefix == "TPMI") { 310 print "_NAME " last_line " _PLUS"; 311 } else if (last_line != "") { 312 print "_NAME " last_line; 313 } else { print "_ERROR: Type with no name"; } 314 last_line = ""; } 315 /^_TYPE [A-Z0-9_]*$/ { print $0; 316 if (last_line != "") { print "_NAME " last_line ; } 317 else { print "_ERROR: Type with no name"; } 318 if (extra_line != "") { print extra_line; } 319 last_line = ""; 320 extra_line = ""; } 321 /^[^_].*$/ { last_line = $0; } 322 /^\[[^]]*\].*$/ { $1 = substr($1, 2, length($1)-1); 323 sub(/\]/, " ", $0); 324 last_line = $2 " _UNION " $1; } 325 /^.*\[[^]]*\]$/ { $1 = substr($1, 1, length($1)-1); 326 sub(/\]/, " " , $0); 327 last_line = $1 " _ARRAY " $2; } 328 /^.*\{[A-Z0-9_]*:\}$/ { last_line = $1; 329 extra_line = "_MIN " $1 " " $3; } 330 /^.*\{:[A-Z0-9_]*\}$/ { last_line = $1; 331 extra_line = "_MAX " $1 " " $3; } 332 /^.*\[[^]]*\] \{:[a-zA-Z0-9_()\/]*\}$/ { $2 = substr($2, 2, length($2)-2); 333 last_line = $1 " _ARRAY " $2; 334 extra_line = "_MAX " $2 " " $5 ; } 335 /^tag \{[A-Z_]*(, [A-Z_]*)*\}$/ { last_line = "tag"; 336 extra_line = "_VALID " $3; 337 for (i = 4; i <= NF-1; i++) 338 extra_line = extra_line "\n_VALID " $i; 339 sub(/\,/, "", extra_line); } 340 /^size\=$/ { last_line = "size _CHECK" } 341 /^#.*$/ { print "_RETURN " $2; } 342 ' | 343 # Strip off structure modifiers 344 sed 's/^_STRUCTURE \((.*) \)*{.*} \(.*\)/_STRUCTURE \2/' | 345 # Sanity check. The format should now follow this grammar: 346 # Format:Begin||Tableblock*||End 347 # Begin:_BEGIN_STRUCTURES\n 348 # End:_END\n 349 # Tableblock: Structure||(Field|Min|Max)*||Return? 350 # Structure:_STRUCTURE <name>\n 351 # Min:_MIN <name> <value>\n 352 # Max:_Max <name> <value>\n 353 # Return:_RETURN <name>\n 354 # Field: Type||Name||Valid* 355 # Type:_TYPE <name>\n 356 # Valid:_VALID <value>\n 357 # Name:_NAME <name>((( _UNION | _ARRAY )<value>)| _PLUS)?\n 358 # No sanity check here. Format is checked during generator.py 359 awk ' 360 { print $0; } 361 ' 362 363# Pull out unions. 364cat $1 | 365 # Mark tables and section boundaries. 366 sed 's/^[0-9][0-9]*\([.][0-9][0-9]*\)\+.*$/_SECTION_BOUNDARY/' | 367 sed 's/^Table [0-9]* . Definition of \(.*\) Union[^.]*$/_UNION \1/' | 368 # Keep only table sections. 369 awk '/^_UNION .*$/,/^_SECTION_BOUNDARY$/ { print $0; }' | 370 sed 's/^_SECTION_BOUNDARY$//' | 371 # Remove headers and footers. 372 sed 's/^.*Trusted Platform Module Library.*$//' | 373 sed 's/^.*Part 2: Structures.*$//' | 374 sed 's/^.*Family .2.0..*$//' | 375 sed 's/^.*Level 00 Revision.*$//' | 376 sed 's/^.*Published.*$//' | 377 sed 's/^.*Copyright.*$//' | 378 sed 's/^.*Page [0-9].*$//' | 379 sed 's/^.*October 31, 2013.*$//' | 380 # Remove table headers. 381 sed 's/^Parameter$//' | sed 's/^Type$//' | sed 's/^Selector$//' | 382 sed 's/^Description$//' | 383 # Remove leading spaces. 384 sed 's/^[ ][ ]*//' | 385 # Remove empty lines. 386 sed '/^$/d' | 387 # Mark begin and end. 388 awk ' 389 BEGIN { print "_BEGIN_UNIONS"; } 390 { print $0; } 391 END { print "_END"; } 392 ' | 393 # Mark field types. 394 sed 's/^\(+*TPM[_A-Z0-9+a]*\)$/_TYPE \1/' | 395 sed 's/^\(UINT[0-9]*\)$/_TYPE \1/' | 396 sed 's/^\(BYTE*\)$/_TYPE \1/' | 397 # Mark field names and throw away everything else. 398 awk ' 399 BEGIN { last_line = ""; } 400 /^_.*$/ { if ($0 !~ /^_TYPE .*$/) { last_line = ""; print $0; } } 401 /^_TYPE .*$/ { if (last_line !~ /^_TYPE .*$/) { 402 if (last_line != "" && 403 last_line != "null" && 404 last_line != "NOTE") { 405 print $0; 406 print "_NAME " last_line; } 407 else if (last_line == "") { 408 print "_ERROR: Type with no name"; } 409 last_line = $0; } } 410 /^[^_].*$/ { last_line = $0; } 411 /^.* \[[^]]*\]$/ { $2 = substr($2, 2, length($2)-2); 412 last_line = $1 " _ARRAY " $2; } 413 ' | 414 # Sanity check. The format should now follow this grammar: 415 # Format:Begin||TableBlock*||End 416 # Begin:_BEGIN_UNIONS\n 417 # End:_END\n 418 # TableBlock:TableTag||Field* 419 # TableTag:_UNION <name>\n 420 # Field:Type||Name 421 # Type:_TYPE <type>\n 422 # Name:_NAME <name>\n 423 awk ' 424 BEGIN { RS = ""; } 425 $0 !~ /_BEGIN_UNIONS\n(_UNION[^\n]*\n(_TYPE[^\n]*\n_NAME[^\n]*\n)*)*_END/ { 426 print "_ERROR: Format check failed."; } 427 { print $0; } 428 ' 429 430exit 0 431