1 /** 2 * Describes functions for converting memory error CPER sections from binary and JSON format 3 * into an intermediate format. 4 * 5 * Author: Lawrence.Tang@arm.com 6 **/ 7 #include <stdio.h> 8 #include <json.h> 9 #include <libcper/Cper.h> 10 #include <libcper/cper-utils.h> 11 #include <libcper/sections/cper-section-memory.h> 12 #include <libcper/log.h> 13 14 //Converts a single memory error CPER section into JSON IR. 15 json_object *cper_section_platform_memory_to_ir(const UINT8 *section, 16 UINT32 size) 17 { 18 if (size < sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)) { 19 return NULL; 20 } 21 22 EFI_PLATFORM_MEMORY_ERROR_DATA *memory_error = 23 (EFI_PLATFORM_MEMORY_ERROR_DATA *)section; 24 json_object *section_ir = json_object_new_object(); 25 26 ValidationTypes ui64Type = { UINT_64T, 27 .value.ui64 = memory_error->ValidFields }; 28 29 //Error status. 30 if (isvalid_prop_to_ir(&ui64Type, 0)) { 31 json_object *error_status = cper_generic_error_status_to_ir( 32 &memory_error->ErrorStatus); 33 json_object_object_add(section_ir, "errorStatus", error_status); 34 } 35 36 //Bank 37 json_object *bank = json_object_new_object(); 38 if (isvalid_prop_to_ir(&ui64Type, 6)) { 39 //Entire bank address mode. 40 json_object_object_add( 41 bank, "value", 42 json_object_new_uint64(memory_error->Bank)); 43 } else { 44 //Address/group address mode. 45 json_object_object_add( 46 bank, "address", 47 json_object_new_uint64(memory_error->Bank & 0xFF)); 48 json_object_object_add( 49 bank, "group", 50 json_object_new_uint64(memory_error->Bank >> 8)); 51 } 52 json_object_object_add(section_ir, "bank", bank); 53 54 //Memory error type. 55 if (isvalid_prop_to_ir(&ui64Type, 14)) { 56 json_object *memory_error_type = integer_to_readable_pair( 57 memory_error->ErrorType, 16, MEMORY_ERROR_TYPES_KEYS, 58 MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)"); 59 json_object_object_add(section_ir, "memoryErrorType", 60 memory_error_type); 61 } 62 63 //"Extended" row/column indication field + misc. 64 // Review this 65 if (isvalid_prop_to_ir(&ui64Type, 18)) { 66 json_object *extended = json_object_new_object(); 67 json_object_object_add( 68 extended, "rowBit16", 69 json_object_new_boolean(memory_error->Extended & 0x1)); 70 json_object_object_add( 71 extended, "rowBit17", 72 json_object_new_boolean((memory_error->Extended >> 1) & 73 0x1)); 74 if (isvalid_prop_to_ir(&ui64Type, 21)) { 75 json_object_object_add( 76 extended, "chipIdentification", 77 json_object_new_int(memory_error->Extended >> 78 5)); 79 } 80 json_object_object_add(section_ir, "extended", extended); 81 82 //bit 16 and 17 are valid only if extended is valid 83 if (isvalid_prop_to_ir(&ui64Type, 16)) { 84 json_object_object_add( 85 section_ir, "cardSmbiosHandle", 86 json_object_new_uint64( 87 memory_error->CardHandle)); 88 } 89 if (isvalid_prop_to_ir(&ui64Type, 17)) { 90 json_object_object_add( 91 section_ir, "moduleSmbiosHandle", 92 json_object_new_uint64( 93 memory_error->ModuleHandle)); 94 } 95 } 96 97 //Miscellaneous numeric fields. 98 if (isvalid_prop_to_ir(&ui64Type, 1)) { 99 json_object_object_add( 100 section_ir, "physicalAddress", 101 json_object_new_uint64(memory_error->PhysicalAddress)); 102 103 char hexstring_buf[EFI_UINT64_HEX_STRING_LEN]; 104 snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX", 105 memory_error->PhysicalAddress); 106 json_object_object_add(section_ir, "physicalAddressHex", 107 json_object_new_string(hexstring_buf)); 108 } 109 if (isvalid_prop_to_ir(&ui64Type, 2)) { 110 json_object_object_add( 111 section_ir, "physicalAddressMask", 112 json_object_new_uint64( 113 memory_error->PhysicalAddressMask)); 114 } 115 if (isvalid_prop_to_ir(&ui64Type, 3)) { 116 json_object_object_add( 117 section_ir, "node", 118 json_object_new_uint64(memory_error->Node)); 119 } 120 if (isvalid_prop_to_ir(&ui64Type, 4)) { 121 json_object_object_add( 122 section_ir, "card", 123 json_object_new_uint64(memory_error->Card)); 124 } 125 if (isvalid_prop_to_ir(&ui64Type, 5)) { 126 json_object_object_add( 127 section_ir, "moduleRank", 128 json_object_new_uint64(memory_error->ModuleRank)); 129 } 130 if (isvalid_prop_to_ir(&ui64Type, 7)) { 131 json_object_object_add( 132 section_ir, "device", 133 json_object_new_uint64(memory_error->Device)); 134 } 135 if (isvalid_prop_to_ir(&ui64Type, 8)) { 136 json_object_object_add( 137 section_ir, "row", 138 json_object_new_uint64(memory_error->Row)); 139 } 140 if (isvalid_prop_to_ir(&ui64Type, 9)) { 141 json_object_object_add( 142 section_ir, "column", 143 json_object_new_uint64(memory_error->Column)); 144 } 145 if (isvalid_prop_to_ir(&ui64Type, 10)) { 146 json_object_object_add( 147 section_ir, "bitPosition", 148 json_object_new_uint64(memory_error->BitPosition)); 149 } 150 if (isvalid_prop_to_ir(&ui64Type, 11)) { 151 json_object_object_add( 152 section_ir, "requestorID", 153 json_object_new_uint64(memory_error->RequestorId)); 154 } 155 if (isvalid_prop_to_ir(&ui64Type, 12)) { 156 json_object_object_add( 157 section_ir, "responderID", 158 json_object_new_uint64(memory_error->ResponderId)); 159 } 160 if (isvalid_prop_to_ir(&ui64Type, 13)) { 161 json_object_object_add( 162 section_ir, "targetID", 163 json_object_new_uint64(memory_error->TargetId)); 164 } 165 if (isvalid_prop_to_ir(&ui64Type, 15)) { 166 json_object_object_add( 167 section_ir, "rankNumber", 168 json_object_new_uint64(memory_error->RankNum)); 169 } 170 171 return section_ir; 172 } 173 174 //Converts a single memory error 2 CPER section into JSON IR. 175 json_object *cper_section_platform_memory2_to_ir(const UINT8 *section, 176 UINT32 size) 177 { 178 if (size < sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA)) { 179 return NULL; 180 } 181 182 EFI_PLATFORM_MEMORY2_ERROR_DATA *memory_error = 183 (EFI_PLATFORM_MEMORY2_ERROR_DATA *)section; 184 json_object *section_ir = json_object_new_object(); 185 186 ValidationTypes ui64Type = { UINT_64T, 187 .value.ui64 = memory_error->ValidFields }; 188 189 //Error status. 190 if (isvalid_prop_to_ir(&ui64Type, 0)) { 191 json_object *error_status = cper_generic_error_status_to_ir( 192 &memory_error->ErrorStatus); 193 json_object_object_add(section_ir, "errorStatus", error_status); 194 } 195 196 //Bank. 197 json_object *bank = json_object_new_object(); 198 if (isvalid_prop_to_ir(&ui64Type, 6)) { 199 //Entire bank address mode. 200 json_object_object_add( 201 bank, "value", 202 json_object_new_uint64(memory_error->Bank)); 203 } else { 204 //Address/group address mode. 205 json_object_object_add( 206 bank, "address", 207 json_object_new_uint64(memory_error->Bank & 0xFF)); 208 json_object_object_add( 209 bank, "group", 210 json_object_new_uint64(memory_error->Bank >> 8)); 211 } 212 json_object_object_add(section_ir, "bank", bank); 213 214 //Memory error type. 215 if (isvalid_prop_to_ir(&ui64Type, 13)) { 216 json_object *memory_error_type = integer_to_readable_pair( 217 memory_error->MemErrorType, 16, MEMORY_ERROR_TYPES_KEYS, 218 MEMORY_ERROR_TYPES_VALUES, "Unknown (Reserved)"); 219 json_object_object_add(section_ir, "memoryErrorType", 220 memory_error_type); 221 } 222 223 //Status. 224 if (isvalid_prop_to_ir(&ui64Type, 14)) { 225 json_object *status = json_object_new_object(); 226 json_object_object_add( 227 status, "value", 228 json_object_new_int(memory_error->Status)); 229 json_object_object_add( 230 status, "state", 231 json_object_new_string((memory_error->Status & 0x1) == 232 0 ? 233 "Corrected" : 234 "Uncorrected")); 235 json_object_object_add(section_ir, "status", status); 236 } 237 238 //Miscellaneous numeric fields. 239 if (isvalid_prop_to_ir(&ui64Type, 0)) { 240 json_object_object_add( 241 section_ir, "physicalAddress", 242 json_object_new_uint64(memory_error->PhysicalAddress)); 243 } 244 245 char hexstring_buf[EFI_UINT64_HEX_STRING_LEN]; 246 snprintf(hexstring_buf, EFI_UINT64_HEX_STRING_LEN, "0x%016llX", 247 memory_error->PhysicalAddress); 248 json_object_object_add(section_ir, "physicalAddressHex", 249 json_object_new_string(hexstring_buf)); 250 251 if (isvalid_prop_to_ir(&ui64Type, 2)) { 252 json_object_object_add( 253 section_ir, "physicalAddressMask", 254 json_object_new_uint64( 255 memory_error->PhysicalAddressMask)); 256 } 257 if (isvalid_prop_to_ir(&ui64Type, 3)) { 258 json_object_object_add( 259 section_ir, "node", 260 json_object_new_uint64(memory_error->Node)); 261 } 262 if (isvalid_prop_to_ir(&ui64Type, 4)) { 263 json_object_object_add( 264 section_ir, "card", 265 json_object_new_uint64(memory_error->Card)); 266 } 267 if (isvalid_prop_to_ir(&ui64Type, 5)) { 268 json_object_object_add( 269 section_ir, "module", 270 json_object_new_uint64(memory_error->Module)); 271 } 272 if (isvalid_prop_to_ir(&ui64Type, 7)) { 273 json_object_object_add( 274 section_ir, "device", 275 json_object_new_uint64(memory_error->Device)); 276 } 277 if (isvalid_prop_to_ir(&ui64Type, 8)) { 278 json_object_object_add( 279 section_ir, "row", 280 json_object_new_uint64(memory_error->Row)); 281 } 282 if (isvalid_prop_to_ir(&ui64Type, 9)) { 283 json_object_object_add( 284 section_ir, "column", 285 json_object_new_uint64(memory_error->Column)); 286 } 287 if (isvalid_prop_to_ir(&ui64Type, 10)) { 288 json_object_object_add( 289 section_ir, "rank", 290 json_object_new_uint64(memory_error->Rank)); 291 } 292 if (isvalid_prop_to_ir(&ui64Type, 11)) { 293 json_object_object_add( 294 section_ir, "bitPosition", 295 json_object_new_uint64(memory_error->BitPosition)); 296 } 297 if (isvalid_prop_to_ir(&ui64Type, 12)) { 298 json_object_object_add( 299 section_ir, "chipID", 300 json_object_new_uint64(memory_error->ChipId)); 301 } 302 if (isvalid_prop_to_ir(&ui64Type, 15)) { 303 json_object_object_add( 304 section_ir, "requestorID", 305 json_object_new_uint64(memory_error->RequestorId)); 306 } 307 if (isvalid_prop_to_ir(&ui64Type, 16)) { 308 json_object_object_add( 309 section_ir, "responderID", 310 json_object_new_uint64(memory_error->ResponderId)); 311 } 312 if (isvalid_prop_to_ir(&ui64Type, 17)) { 313 json_object_object_add( 314 section_ir, "targetID", 315 json_object_new_uint64(memory_error->TargetId)); 316 } 317 if (isvalid_prop_to_ir(&ui64Type, 18)) { 318 json_object_object_add( 319 section_ir, "cardSmbiosHandle", 320 json_object_new_uint64(memory_error->CardHandle)); 321 } 322 if (isvalid_prop_to_ir(&ui64Type, 19)) { 323 json_object_object_add( 324 section_ir, "moduleSmbiosHandle", 325 json_object_new_uint64(memory_error->ModuleHandle)); 326 } 327 328 return section_ir; 329 } 330 331 //Converts a single Memory Error IR section into CPER binary, outputting to the provided stream. 332 void ir_section_memory_to_cper(json_object *section, FILE *out) 333 { 334 EFI_PLATFORM_MEMORY_ERROR_DATA *section_cper = 335 (EFI_PLATFORM_MEMORY_ERROR_DATA *)calloc( 336 1, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA)); 337 338 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; 339 struct json_object *obj = NULL; 340 341 //Error status. 342 if (json_object_object_get_ex(section, "errorStatus", &obj)) { 343 ir_generic_error_status_to_cper(obj, 344 §ion_cper->ErrorStatus); 345 add_to_valid_bitfield(&ui64Type, 0); 346 } 347 348 //Bank. 349 if (json_object_object_get_ex(section, "bank", &obj)) { 350 json_object *bank = obj; 351 if (json_object_object_get_ex(bank, "value", &obj)) { 352 //Bank just uses simple address. 353 section_cper->Bank = 354 (UINT16)json_object_get_uint64(obj); 355 add_to_valid_bitfield(&ui64Type, 6); 356 } else { 357 //Bank uses address/group style address. 358 UINT16 address = (UINT8)json_object_get_uint64( 359 json_object_object_get(bank, "address")); 360 UINT16 group = (UINT8)json_object_get_uint64( 361 json_object_object_get(bank, "group")); 362 section_cper->Bank = address + (group << 8); 363 add_to_valid_bitfield(&ui64Type, 19); 364 add_to_valid_bitfield(&ui64Type, 20); 365 } 366 } 367 368 //"Extended" field. 369 if (json_object_object_get_ex(section, "extended", &obj)) { 370 json_object *extended = obj; 371 section_cper->Extended = 0; 372 section_cper->Extended |= json_object_get_boolean( 373 json_object_object_get(extended, "rowBit16")); 374 section_cper->Extended |= 375 json_object_get_boolean( 376 json_object_object_get(extended, "rowBit17")) 377 << 1; 378 if (json_object_object_get_ex(extended, "chipIdentification", 379 &obj)) { 380 section_cper->Extended |= json_object_get_int(obj) << 5; 381 add_to_valid_bitfield(&ui64Type, 21); 382 } 383 add_to_valid_bitfield(&ui64Type, 18); 384 } 385 386 //Miscellaneous value fields. 387 if (json_object_object_get_ex(section, "memoryErrorType", &obj)) { 388 section_cper->ErrorType = (UINT8)readable_pair_to_integer(obj); 389 add_to_valid_bitfield(&ui64Type, 14); 390 } 391 if (json_object_object_get_ex(section, "physicalAddress", &obj)) { 392 section_cper->PhysicalAddress = json_object_get_uint64(obj); 393 add_to_valid_bitfield(&ui64Type, 1); 394 } 395 if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) { 396 section_cper->PhysicalAddressMask = json_object_get_uint64(obj); 397 add_to_valid_bitfield(&ui64Type, 2); 398 } 399 if (json_object_object_get_ex(section, "node", &obj)) { 400 section_cper->Node = (UINT16)json_object_get_uint64(obj); 401 add_to_valid_bitfield(&ui64Type, 3); 402 } 403 if (json_object_object_get_ex(section, "card", &obj)) { 404 section_cper->Card = (UINT16)json_object_get_uint64(obj); 405 add_to_valid_bitfield(&ui64Type, 4); 406 } 407 if (json_object_object_get_ex(section, "moduleRank", &obj)) { 408 section_cper->ModuleRank = (UINT16)json_object_get_uint64(obj); 409 add_to_valid_bitfield(&ui64Type, 5); 410 } 411 if (json_object_object_get_ex(section, "device", &obj)) { 412 section_cper->Device = (UINT16)json_object_get_uint64(obj); 413 add_to_valid_bitfield(&ui64Type, 7); 414 } 415 if (json_object_object_get_ex(section, "row", &obj)) { 416 section_cper->Row = (UINT16)json_object_get_uint64(obj); 417 add_to_valid_bitfield(&ui64Type, 8); 418 } 419 if (json_object_object_get_ex(section, "column", &obj)) { 420 section_cper->Column = (UINT16)json_object_get_uint64(obj); 421 add_to_valid_bitfield(&ui64Type, 9); 422 } 423 if (json_object_object_get_ex(section, "bitPosition", &obj)) { 424 section_cper->BitPosition = (UINT16)json_object_get_uint64(obj); 425 add_to_valid_bitfield(&ui64Type, 10); 426 } 427 if (json_object_object_get_ex(section, "requestorID", &obj)) { 428 section_cper->RequestorId = json_object_get_uint64(obj); 429 add_to_valid_bitfield(&ui64Type, 11); 430 } 431 if (json_object_object_get_ex(section, "responderID", &obj)) { 432 section_cper->ResponderId = json_object_get_uint64(obj); 433 add_to_valid_bitfield(&ui64Type, 12); 434 } 435 if (json_object_object_get_ex(section, "targetID", &obj)) { 436 section_cper->TargetId = json_object_get_uint64(obj); 437 add_to_valid_bitfield(&ui64Type, 13); 438 } 439 if (json_object_object_get_ex(section, "rankNumber", &obj)) { 440 section_cper->RankNum = (UINT16)json_object_get_uint64( 441 json_object_object_get(section, "rankNumber")); 442 add_to_valid_bitfield(&ui64Type, 15); 443 } 444 if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) { 445 section_cper->CardHandle = (UINT16)json_object_get_uint64(obj); 446 add_to_valid_bitfield(&ui64Type, 16); 447 } 448 if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) { 449 section_cper->ModuleHandle = 450 (UINT16)json_object_get_uint64(obj); 451 add_to_valid_bitfield(&ui64Type, 17); 452 } 453 section_cper->ValidFields = ui64Type.value.ui64; 454 455 //Write to stream, free up resources. 456 fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY_ERROR_DATA), 1, out); 457 fflush(out); 458 free(section_cper); 459 } 460 461 //Converts a single Memory Error 2 IR section into CPER binary, outputting to the provided stream. 462 void ir_section_memory2_to_cper(json_object *section, FILE *out) 463 { 464 EFI_PLATFORM_MEMORY2_ERROR_DATA *section_cper = 465 (EFI_PLATFORM_MEMORY2_ERROR_DATA *)calloc( 466 1, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA)); 467 468 //Validation bits. 469 ValidationTypes ui64Type = { UINT_64T, .value.ui64 = 0 }; 470 struct json_object *obj = NULL; 471 472 //Error status. 473 if (json_object_object_get_ex(section, "errorStatus", &obj)) { 474 ir_generic_error_status_to_cper(obj, 475 §ion_cper->ErrorStatus); 476 add_to_valid_bitfield(&ui64Type, 0); 477 } 478 479 //Bank. 480 json_object *bank = json_object_object_get(section, "bank"); 481 if (json_object_object_get_ex(bank, "value", &obj)) { 482 //Bank just uses simple address. 483 section_cper->Bank = (UINT16)json_object_get_uint64(obj); 484 add_to_valid_bitfield(&ui64Type, 6); 485 } else { 486 //Bank uses address/group style address. 487 UINT16 address = (UINT8)json_object_get_uint64( 488 json_object_object_get(bank, "address")); 489 UINT16 group = (UINT8)json_object_get_uint64( 490 json_object_object_get(bank, "group")); 491 section_cper->Bank = address + (group << 8); 492 add_to_valid_bitfield(&ui64Type, 20); 493 add_to_valid_bitfield(&ui64Type, 21); 494 } 495 496 //Miscellaneous value fields. 497 if (json_object_object_get_ex(section, "memoryErrorType", &obj)) { 498 section_cper->MemErrorType = readable_pair_to_integer(obj); 499 add_to_valid_bitfield(&ui64Type, 13); 500 } 501 if (json_object_object_get_ex(section, "status", &obj)) { 502 section_cper->Status = (UINT8)readable_pair_to_integer(obj); 503 add_to_valid_bitfield(&ui64Type, 14); 504 } 505 if (json_object_object_get_ex(section, "physicalAddress", &obj)) { 506 section_cper->PhysicalAddress = json_object_get_uint64(obj); 507 add_to_valid_bitfield(&ui64Type, 1); 508 } 509 if (json_object_object_get_ex(section, "physicalAddressMask", &obj)) { 510 section_cper->PhysicalAddressMask = json_object_get_uint64(obj); 511 add_to_valid_bitfield(&ui64Type, 2); 512 } 513 if (json_object_object_get_ex(section, "node", &obj)) { 514 section_cper->Node = (UINT16)json_object_get_uint64(obj); 515 add_to_valid_bitfield(&ui64Type, 3); 516 } 517 if (json_object_object_get_ex(section, "card", &obj)) { 518 section_cper->Card = (UINT16)json_object_get_uint64(obj); 519 add_to_valid_bitfield(&ui64Type, 4); 520 } 521 if (json_object_object_get_ex(section, "module", &obj)) { 522 section_cper->Module = (UINT32)json_object_get_uint64(obj); 523 add_to_valid_bitfield(&ui64Type, 5); 524 } 525 if (json_object_object_get_ex(section, "device", &obj)) { 526 section_cper->Device = (UINT32)json_object_get_uint64(obj); 527 add_to_valid_bitfield(&ui64Type, 7); 528 } 529 if (json_object_object_get_ex(section, "row", &obj)) { 530 section_cper->Row = (UINT32)json_object_get_uint64(obj); 531 add_to_valid_bitfield(&ui64Type, 8); 532 } 533 if (json_object_object_get_ex(section, "column", &obj)) { 534 section_cper->Column = (UINT32)json_object_get_uint64(obj); 535 add_to_valid_bitfield(&ui64Type, 9); 536 } 537 if (json_object_object_get_ex(section, "rank", &obj)) { 538 section_cper->Rank = (UINT32)json_object_get_uint64(obj); 539 add_to_valid_bitfield(&ui64Type, 10); 540 } 541 if (json_object_object_get_ex(section, "bitPosition", &obj)) { 542 section_cper->BitPosition = (UINT32)json_object_get_uint64(obj); 543 add_to_valid_bitfield(&ui64Type, 11); 544 } 545 if (json_object_object_get_ex(section, "chipID", &obj)) { 546 section_cper->ChipId = (UINT8)json_object_get_uint64(obj); 547 add_to_valid_bitfield(&ui64Type, 12); 548 } 549 if (json_object_object_get_ex(section, "requestorID", &obj)) { 550 section_cper->RequestorId = json_object_get_uint64(obj); 551 add_to_valid_bitfield(&ui64Type, 15); 552 } 553 if (json_object_object_get_ex(section, "responderID", &obj)) { 554 section_cper->ResponderId = json_object_get_uint64(obj); 555 add_to_valid_bitfield(&ui64Type, 16); 556 } 557 if (json_object_object_get_ex(section, "targetID", &obj)) { 558 section_cper->TargetId = json_object_get_uint64(obj); 559 add_to_valid_bitfield(&ui64Type, 17); 560 } 561 if (json_object_object_get_ex(section, "cardSmbiosHandle", &obj)) { 562 section_cper->CardHandle = (UINT32)json_object_get_uint64(obj); 563 add_to_valid_bitfield(&ui64Type, 18); 564 } 565 if (json_object_object_get_ex(section, "moduleSmbiosHandle", &obj)) { 566 section_cper->ModuleHandle = 567 (UINT32)json_object_get_uint64(obj); 568 add_to_valid_bitfield(&ui64Type, 19); 569 } 570 571 section_cper->ValidFields = ui64Type.value.ui64; 572 573 //Write to stream, free up resources. 574 fwrite(section_cper, sizeof(EFI_PLATFORM_MEMORY2_ERROR_DATA), 1, out); 575 fflush(out); 576 free(section_cper); 577 } 578