├── .beautysh-ignore ├── .black-ignore ├── .eslintignore ├── .flake8-ignore ├── .isort-ignore ├── .prettierignore ├── .markdownlint-ignore ├── .shellcheck-ignore ├── subprojects ├── CLI11.wrap └── nlohmann_json.wrap ├── README.md ├── meson.build ├── .gitignore ├── .clang-format ├── cper.h ├── LICENSE └── main.cpp /.beautysh-ignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.black-ignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.flake8-ignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.isort-ignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.markdownlint-ignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.shellcheck-ignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /subprojects/CLI11.wrap: -------------------------------------------------------------------------------- 1 | [wrap-git] 2 | url = https://github.com/CLIUtils/CLI11 3 | revision = HEAD 4 | 5 | [provide] 6 | CLI11 = CLI11_dep 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Getting Started 2 | 3 | The link below provides the latest changes and updates to this project. 4 | 5 | Link: 6 | https://confluence.nvidia.com/display/SPS/Grace+ARM+CPU+Common+Platform+Error+Record+Decoder 7 | 8 | The functions used and its description provided in the main.cpp file 9 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('cper-proj', 'cpp',default_options:['default_library=static']) 2 | nlohmann_json_dep = dependency('nlohmann_json', version: '>=3.11.2', include_type: 'system') 3 | CLI11_dep = dependency('CLI11') 4 | executable('cperparse', 'main.cpp', dependencies: [ nlohmann_json_dep, CLI11_dep ]) 5 | -------------------------------------------------------------------------------- /subprojects/nlohmann_json.wrap: -------------------------------------------------------------------------------- 1 | [wrap-file] 2 | directory = nlohmann_json-3.11.2 3 | lead_directory_missing = true 4 | source_url = https://github.com/nlohmann/json/releases/download/v3.11.2/include.zip 5 | source_filename = nlohmann_json-3.11.2.zip 6 | source_hash = e5c7a9f49a16814be27e4ed0ee900ecd0092bfb7dbfca65b5a421b774dccaaed 7 | wrapdb_version = 3.11.2-1 8 | 9 | [provide] 10 | nlohmann_json = nlohmann_json_dep 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/meson 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=meson 4 | 5 | ### Meson ### 6 | # subproject directories 7 | /subprojects/* 8 | !/subprojects/*.wrap 9 | 10 | # Meson Directories 11 | meson-logs 12 | meson-private 13 | 14 | # Meson Files 15 | meson_benchmark_setup.dat 16 | meson_test_setup.dat 17 | sanitycheckcpp.cc # C++ specific 18 | sanitycheckcpp.exe # C++ specific 19 | 20 | # Ninja 21 | build.ninja 22 | .ninja_deps 23 | .ninja_logs 24 | 25 | # Misc 26 | compile_commands.json 27 | 28 | # End of https://www.toptal.com/developers/gitignore/api/meson 29 | 30 | build/* -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: Align 10 | AlignTrailingComments: 11 | Kind: Always 12 | OverEmptyLines: 1 13 | AllowAllParametersOfDeclarationOnNextLine: true 14 | AllowShortBlocksOnASingleLine: Empty 15 | AllowShortCaseLabelsOnASingleLine: false 16 | AllowShortFunctionsOnASingleLine: Empty 17 | AllowShortIfStatementsOnASingleLine: Never 18 | AllowShortLambdasOnASingleLine: true 19 | AllowShortLoopsOnASingleLine: false 20 | AlwaysBreakAfterReturnType: None 21 | AlwaysBreakBeforeMultilineStrings: false 22 | AlwaysBreakTemplateDeclarations: Yes 23 | BinPackArguments: true 24 | BinPackParameters: true 25 | BitFieldColonSpacing: None 26 | BraceWrapping: 27 | AfterCaseLabel: true 28 | AfterClass: true 29 | AfterControlStatement: true 30 | AfterEnum: true 31 | AfterExternBlock: true 32 | AfterFunction: true 33 | AfterNamespace: true 34 | AfterObjCDeclaration: true 35 | AfterStruct: true 36 | AfterUnion: true 37 | BeforeCatch: true 38 | BeforeElse: true 39 | BeforeLambdaBody: false 40 | BeforeWhile: false 41 | IndentBraces: false 42 | SplitEmptyFunction: false 43 | SplitEmptyRecord: false 44 | SplitEmptyNamespace: false 45 | BreakAfterAttributes: Never 46 | BreakBeforeBinaryOperators: None 47 | BreakBeforeBraces: Custom 48 | BreakBeforeTernaryOperators: true 49 | BreakConstructorInitializers: AfterColon 50 | BreakInheritanceList: AfterColon 51 | BreakStringLiterals: false 52 | ColumnLimit: 80 53 | CommentPragmas: '^ IWYU pragma:' 54 | CompactNamespaces: false 55 | ConstructorInitializerIndentWidth: 4 56 | ContinuationIndentWidth: 4 57 | Cpp11BracedListStyle: true 58 | DerivePointerAlignment: false 59 | DisableFormat: false 60 | FixNamespaceComments: true 61 | ForEachMacros: 62 | - foreach 63 | - Q_FOREACH 64 | - BOOST_FOREACH 65 | IncludeBlocks: Regroup 66 | IncludeCategories: 67 | - Regex: '^[<"](gtest|gmock)' 68 | Priority: 7 69 | - Regex: '^"config.h"' 70 | Priority: -1 71 | - Regex: '^".*\.h"' 72 | Priority: 1 73 | - Regex: '^".*\.hpp"' 74 | Priority: 2 75 | - Regex: '^<.*\.h>' 76 | Priority: 3 77 | - Regex: '^<.*\.hpp>' 78 | Priority: 4 79 | - Regex: '^<.*' 80 | Priority: 5 81 | - Regex: '.*' 82 | Priority: 6 83 | IndentCaseLabels: true 84 | IndentExternBlock: NoIndent 85 | IndentRequiresClause: true 86 | IndentWidth: 4 87 | IndentWrappedFunctionNames: true 88 | InsertNewlineAtEOF: true 89 | KeepEmptyLinesAtTheStartOfBlocks: false 90 | LambdaBodyIndentation: OuterScope 91 | LineEnding: LF 92 | MacroBlockBegin: '' 93 | MacroBlockEnd: '' 94 | MaxEmptyLinesToKeep: 1 95 | NamespaceIndentation: None 96 | ObjCBlockIndentWidth: 2 97 | ObjCSpaceAfterProperty: false 98 | ObjCSpaceBeforeProtocolList: true 99 | PackConstructorInitializers: BinPack 100 | PenaltyBreakAssignment: 25 101 | PenaltyBreakBeforeFirstCallParameter: 19 102 | PenaltyBreakComment: 300 103 | PenaltyBreakFirstLessLess: 120 104 | PenaltyBreakString: 1000 105 | PenaltyExcessCharacter: 1000000 106 | PenaltyReturnTypeOnItsOwnLine: 60 107 | PenaltyIndentedWhitespace: 0 108 | PointerAlignment: Left 109 | QualifierAlignment: Left 110 | ReferenceAlignment: Left 111 | ReflowComments: true 112 | RequiresClausePosition: OwnLine 113 | RequiresExpressionIndentation: Keyword 114 | SortIncludes: CaseSensitive 115 | SortUsingDeclarations: true 116 | SpaceAfterCStyleCast: false 117 | SpaceAfterTemplateKeyword: true 118 | SpaceBeforeAssignmentOperators: true 119 | SpaceBeforeCpp11BracedList: false 120 | SpaceBeforeCtorInitializerColon: true 121 | SpaceBeforeInheritanceColon: true 122 | SpaceBeforeParens: ControlStatements 123 | SpaceBeforeRangeBasedForLoopColon: true 124 | SpaceInEmptyParentheses: false 125 | SpacesBeforeTrailingComments: 1 126 | SpacesInAngles: Never 127 | SpacesInContainerLiterals: true 128 | SpacesInCStyleCastParentheses: false 129 | SpacesInParentheses: false 130 | SpacesInSquareBrackets: false 131 | Standard: Latest 132 | TabWidth: 4 133 | UseTab: Never 134 | ... 135 | -------------------------------------------------------------------------------- /cper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & 3 | * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | // Constants and magic numbers 28 | const int recordHeaderLen = 0; 29 | const int sbmrOffset = 4; // 4 bytes of information present before header 30 | const int headerSize = 128; // Standard record header size 31 | const int secDescSize = 72; // Standard section descriptor size 32 | const int signatureEndMarker = 33 | 255; // Each byte of the signature end must be 0xFF which is 255 in int 34 | 35 | /** 36 | * Consists of strings to match each section type 37 | * @note: The section type (GUID) is in the order it is stored in memory in the 38 | *log file 39 | **/ 40 | const std::string 41 | nvda("f244526d1227ec11bea7cb3fdb95c786"); // NVIDIA CPER Section Type 42 | const std::string memErr( 43 | "1411bca5646fde4eb8633e83ed7c83b1"); // General Memory Error Section Type 44 | const std::string pciExpress( 45 | "54e995d9c1bb0f43ad91b44dcb3c6f35"); // PCI Express Error Section Type 46 | const std::string armProcErr( 47 | "163d9ee111bce4119caac2051d5d46b0"); // ARM Processor Error Section Type 48 | 49 | // structure to store the Record Header information as different fields (Refer 50 | // UEFI spec -> Appendix N) 51 | #pragma pack(1) 52 | struct header 53 | { 54 | unsigned char formatVersion[1]; 55 | unsigned char formatType[1]; 56 | unsigned char eventDataLength[2]; 57 | unsigned char signatureStart[4]; 58 | unsigned char Revision[2]; 59 | unsigned char SignatureEnd[4]; 60 | unsigned char SectionCount[2]; 61 | unsigned char ErrorSeverity[4]; 62 | unsigned char ValidationBits[4]; 63 | unsigned char RecordLength[4]; 64 | unsigned char Timestamp[8]; 65 | unsigned char PlatformID[16]; 66 | unsigned char PartitionID[16]; 67 | unsigned char CreatorID[16]; 68 | unsigned char NotificationType[16]; 69 | unsigned char RecordID[8]; 70 | unsigned char Flags[4]; 71 | unsigned char PersistenceInfo[8]; 72 | unsigned char Reserved[12]; 73 | }; 74 | 75 | // structure to store the content of 1 section descriptor as different fields 76 | #pragma pack(1) 77 | struct sectionDescriptor 78 | { 79 | unsigned char sectionOffset[4]; 80 | unsigned char sectionLength[4]; 81 | unsigned char revision[2]; 82 | unsigned char validationBits[1]; 83 | unsigned char reserved[1]; 84 | unsigned char flags[4]; 85 | unsigned char sectionType[16]; 86 | unsigned char fruID[16]; 87 | unsigned char sectionSeverity[4]; 88 | unsigned char fruText[20]; 89 | }; 90 | 91 | // structure to define common fields of the NVIDIA CPER section 92 | #pragma pack(1) 93 | struct section 94 | { 95 | unsigned char IPSignature[16]; 96 | unsigned char ErrorType[2]; 97 | unsigned char ErrorInstance[2]; 98 | unsigned char Severity[1]; 99 | unsigned char SocketNumber[1]; 100 | unsigned char RegDataPairs[1]; 101 | unsigned char Reserved[1]; 102 | unsigned char InstanceBase[8]; 103 | }; 104 | 105 | // structure to define the register and data pairs 106 | #pragma pack(1) 107 | struct registers 108 | { 109 | unsigned char address[8]; 110 | unsigned char value[8]; 111 | }; 112 | 113 | // structure to define the Memory Error Section 114 | #pragma pack(1) 115 | struct memErrorSection 116 | { 117 | unsigned char validationBits[8]; 118 | unsigned char errorStatus[8]; 119 | unsigned char physicalAddress[8]; 120 | unsigned char physicalAddressMask[8]; 121 | unsigned char node[2]; 122 | unsigned char card[2]; 123 | unsigned char module[2]; 124 | unsigned char bankGroup[1]; 125 | unsigned char bankAddress[1]; 126 | unsigned char device[2]; 127 | unsigned char row[2]; 128 | unsigned char column[2]; 129 | unsigned char bitPosition[2]; 130 | unsigned char requestorID[8]; 131 | unsigned char responderID[8]; 132 | unsigned char targetID[8]; 133 | unsigned char memErrType[1]; 134 | unsigned char extended[1]; 135 | unsigned char rankNumber[2]; 136 | unsigned char cardHandle[2]; 137 | unsigned char moduleHandle[2]; 138 | }; 139 | 140 | // structure to define the PCI Express Error Section 141 | #pragma pack(1) 142 | struct pcieSection 143 | { 144 | unsigned char validationBits[8]; 145 | unsigned char portType[4]; 146 | unsigned char version[4]; 147 | unsigned char pciCommandReg[2]; 148 | unsigned char pciStatusReg[2]; 149 | unsigned char reserved[4]; 150 | unsigned char vendorID[2]; 151 | unsigned char deviceID[2]; 152 | unsigned char classCode[3]; 153 | unsigned char functionNumber[1]; 154 | unsigned char deviceNumber[1]; 155 | unsigned char segmentNumber[2]; 156 | unsigned char deviceBusNumber[1]; 157 | unsigned char deviceSecondaryBusNumber[1]; 158 | unsigned char slotNumber[2]; 159 | unsigned char devReserved[1]; 160 | unsigned char lowerDeviceSerialNumber[4]; 161 | unsigned char upperDeviceSerialNumber[4]; 162 | unsigned char bridgeSecondaryStatusReg[2]; 163 | unsigned char bridgeControlReg[2]; 164 | unsigned char capabilityStructure[60]; 165 | unsigned char aerInfo[96]; 166 | }; 167 | 168 | // structure to define the ARM Processor Error Section 169 | #pragma pack(1) 170 | struct armSection 171 | { 172 | unsigned char validationBits[4]; 173 | unsigned char errInfoNum[2]; 174 | unsigned char contexInfoNum[2]; 175 | unsigned char armSecLength[4]; 176 | unsigned char errAffLvl[1]; 177 | unsigned char reserved[3]; 178 | unsigned char MPIDR[8]; 179 | unsigned char MIDR[8]; 180 | unsigned char runningState[4]; 181 | unsigned char psciState[4]; 182 | }; 183 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & 3 | * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | #include "cper.h" 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | using namespace std; 30 | using json = nlohmann::ordered_json; 31 | #define PHASE1 32 | string convertToHex(const unsigned char* input, int size); 33 | 34 | /* Modifying code to deploy Phase 1*/ 35 | 36 | // output object to write into the JSON file 37 | json j; 38 | 39 | /* ************ HELPER FUNCTIONS ************ */ 40 | 41 | /** 42 | * Signature End Validation 43 | * 44 | * This function validates if the Signature End which is a field as part of the 45 | * header has its value as 0xFFFFFFFF 46 | * 47 | * 48 | * @param input Pointer to the 4 bytes of signature end 49 | * @return TRUE if signature end is valid, FALSE otherwise 50 | */ 51 | 52 | bool SignatureEndValidation(const unsigned char* input) 53 | { 54 | for (int i = 0; i < 4; i++) 55 | { 56 | if (!((int)input[i] == signatureEndMarker)) 57 | { 58 | return false; 59 | } 60 | } 61 | return true; 62 | } 63 | 64 | /** 65 | * Convert to String 66 | * 67 | * This function takes a char array and its size as the input and returns a 68 | * string as its output 69 | * 70 | * @param input the input char array @param size Defines the size of the array 71 | * passed 72 | * @return temp which is the string output 73 | */ 74 | string convertToString(const unsigned char* input, int size) 75 | { 76 | string temp(input, input + size); 77 | return temp; 78 | } 79 | 80 | /** 81 | * Convert to ASCII formatted string 82 | * 83 | * This function takes a char array and its size as the input and returns a 84 | * string in its ASCII format as its output 85 | * 86 | * @param input the input char array @param size Defines the size of the array 87 | * passed 88 | * @return temp which is the string output 89 | */ 90 | string convertToStringAscii(const unsigned char* input, int size) 91 | { 92 | int i; 93 | for (i = 0; i < size; i++) 94 | { 95 | if ((int)input[i] == 0) 96 | break; 97 | } 98 | string temp(input, input + i); 99 | return temp; 100 | } 101 | 102 | /** 103 | * Convert from a string to integer 104 | * 105 | * This function takes a string as its input and returns an 106 | * integer as its output 107 | * 108 | * @param input in the form of a string 109 | * @return corresponding integer value 110 | */ 111 | int stringToInt(const string& input) 112 | { 113 | int result = 0; 114 | for (int i = 0; i < (int)input.size(); i++) 115 | { 116 | result += (int)input[i]; 117 | result *= 10; 118 | } 119 | return (int)result / 10; 120 | } 121 | 122 | /** 123 | * Reformatting the Timestamp field 124 | * 125 | * This function takes a pointer to the timestamp array and formats it into a 126 | * string of a specific format NOTE: To be changed based on Redfish format 127 | * @param temp input to the function which is a pointer to the timestamp char 128 | * array @param size Defines the size of the array passed 129 | * @return result which is the formatted string 130 | */ 131 | string timestampDecode(const unsigned char* temp, int size) 132 | { 133 | string time = convertToHex(temp, size); 134 | string result = "Format: MM-DD-YYYY HH:MM:SS "; 135 | 136 | // Extract year, month, and day from the timestamp string 137 | string year1 = time.substr(14, 2); 138 | string year2 = time.substr(12, 2); 139 | string month = time.substr(10, 2); 140 | string day = time.substr(8, 2); 141 | 142 | // Extract hour, minute, and second from the timestamp string 143 | string second = time.substr(0, 2); 144 | string minute = time.substr(2, 2); 145 | string hour = time.substr(4, 2); 146 | 147 | // Construct the formatted timestamp string 148 | result += month + "-" + day + "-" + year1 + year2 + " " + hour + ":" + 149 | minute + ":" + second; 150 | 151 | return result; 152 | } 153 | 154 | /** 155 | * Convert to HEX formatted string 156 | * 157 | * This function takes a char array and its size as the input and returns a 158 | * string in its HEX format as its output 159 | * 160 | * @param input the input char array @param size Defines the size of the array 161 | * passed 162 | * @return result which is the string output 163 | */ 164 | string convertToHex(const unsigned char* input, int size) 165 | { 166 | stringstream result; 167 | for (int k = 0; k < size; k++) 168 | { 169 | result << hex << std::setfill('0') << std::setw(2) << (int)input[k]; 170 | } 171 | return result.str(); 172 | } 173 | 174 | /** 175 | * Convert to HEX formatted string from an input of a char array in little 176 | * endian 177 | * 178 | * This function takes a char array and its size as the input and returns a 179 | * string in its HEX format as its output considering the input to be in little 180 | * endian 181 | * 182 | * @param input the input char array @param size Defines the size of the array 183 | * passed 184 | * @return result which is the string output 185 | */ 186 | string convertToHexLittleEndian(const unsigned char* input, int size) 187 | { 188 | stringstream result; 189 | for (int k = size - 1; k > -1; k--) 190 | { 191 | result << hex << std::setfill('0') << std::setw(2) << (int)input[k]; 192 | } 193 | return result.str(); 194 | } 195 | 196 | /** 197 | * Convert to integer from a char array stored in little endian 198 | * 199 | * This function takes a char array and its size as the input and returns an 200 | * integer as its output considering the input to be in little endian 201 | * 202 | * @param input the input char array @param size Defines the size of the array 203 | * passed 204 | * @return result which is the integer output 205 | */ 206 | long int charToIntLittleEndian(const unsigned char* input, int size) 207 | { 208 | long int result = 0; 209 | for (int i = size - 1; i >= 0; i--) 210 | { 211 | if (input[i] == 0x0A) 212 | { 213 | result += 10; 214 | } 215 | else 216 | { 217 | result += input[i]; 218 | } 219 | result = result << 8; 220 | } 221 | return (result >> 8); 222 | } 223 | 224 | /** 225 | * Reformatting the GUID field 226 | * 227 | * This function takes a string as its input and reformats it to a standard GUID 228 | * representation 229 | * 230 | * @param input to the function which is a string 231 | * @return result which is the formatted string 232 | */ 233 | string guidDecode(const string& input) 234 | { 235 | string result; 236 | for (int i = 6; i >= 0; i = i - 2) 237 | { 238 | result = result + input[i] + input[i + 1]; 239 | } 240 | result = result + '-'; 241 | for (int i = 10; i >= 8; i = i - 2) 242 | { 243 | result = result + input[i] + input[i + 1]; 244 | } 245 | result = result + '-'; 246 | for (int i = 14; i >= 12; i = i - 2) 247 | { 248 | result = result + input[i] + input[i + 1]; 249 | } 250 | result = result + '-'; 251 | for (int i = 16; i <= 19; i = i + 1) 252 | { 253 | result = result + input[i]; 254 | } 255 | result = result + '-'; 256 | for (int i = 20; i < 32; i++) 257 | { 258 | result = result + input[i]; 259 | } 260 | return result; 261 | } 262 | 263 | // Defining hashmaps for certain fields with multiple possibilities 264 | const map errorSev = { 265 | {0, "Recoverable"}, 266 | {1, "Fatal"}, 267 | {2, "Corrected"}, 268 | {3, "Informational"}, 269 | }; 270 | const map headerFlags = { 271 | {1, "HW_ERROR_FLAGS_RECOVERED"}, 272 | {2, "HW_ERROR_FLAGS_PREVERR"}, 273 | {4, "HW_ERROR_FLAGS_SIMULATED"}, 274 | }; 275 | const map memErrType = { 276 | {0, "Unknown"}, 277 | {1, "No Error"}, 278 | {2, "Sngle-bit ECC"}, 279 | {3, "Multi-bit ECC"}, 280 | {4, "Single-symbol ChipKill ECC"}, 281 | {5, "Multi-symbol ChipKill ECC"}, 282 | {6, "Master abort"}, 283 | {7, "Target abort"}, 284 | {8, "Parity Error"}, 285 | {9, "Watchdog timeout"}, 286 | {10, "Invalid address"}, 287 | {11, "Mirror Broken"}, 288 | {12, "Memory Sparing"}, 289 | {13, "Scrub corrected error"}, 290 | {14, "Scrub uncorrected error"}, 291 | {15, "Physical Memory Map-out event"}, 292 | }; 293 | 294 | /** 295 | * Function to check for validation bits in memory error section 296 | * 297 | * This function checks for different bits to be set and appropriately assigns a 298 | * valid or invalid result 299 | * 300 | * @param input is the pointer to the bytes of information to be used and i is 301 | * the section iterator 302 | * @return void 303 | */ 304 | void memErrValidationBitsDecode(const unsigned char* input, int i) 305 | { 306 | for (int k = 0; k < 8; k++) 307 | { 308 | switch (k) 309 | { 310 | case 0: 311 | j["Sections"][i]["Section"]["ValidationBits"] 312 | ["ErrorStatusValidity"] = 313 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 314 | : "Invalid"; 315 | break; 316 | case 1: 317 | j["Sections"][i]["Section"]["ValidationBits"] 318 | ["PhysicalAddressValidity"] = 319 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 320 | : "Invalid"; 321 | break; 322 | case 2: 323 | j["Sections"][i]["Section"]["ValidationBits"] 324 | ["PhysicalAddressMaskValidity"] = 325 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 326 | : "Invalid"; 327 | break; 328 | case 3: 329 | j["Sections"][i]["Section"]["ValidationBits"]["NodeValidity"] = 330 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 331 | : "Invalid"; 332 | break; 333 | case 4: 334 | j["Sections"][i]["Section"]["ValidationBits"]["CardValidity"] = 335 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 336 | : "Invalid"; 337 | break; 338 | case 5: 339 | j["Sections"][i]["Section"]["ValidationBits"] 340 | ["ModuleValidity"] = 341 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 342 | : "Invalid"; 343 | break; 344 | case 6: 345 | j["Sections"][i]["Section"]["ValidationBits"]["BankValidity"] = 346 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 347 | : "Invalid"; 348 | break; 349 | case 7: 350 | j["Sections"][i]["Section"]["ValidationBits"] 351 | ["DeviceValidity"] = 352 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 353 | : "Invalid"; 354 | break; 355 | } 356 | } 357 | for (int k = 0; k < 8; k++) 358 | { 359 | switch (k) 360 | { 361 | case 0: 362 | j["Sections"][i]["Section"]["ValidationBits"]["RowValidity"] = 363 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 364 | : "Invalid"; 365 | break; 366 | case 1: 367 | j["Sections"][i]["Section"]["ValidationBits"] 368 | ["ColumnValidity"] = 369 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 370 | : "Invalid"; 371 | break; 372 | case 2: 373 | j["Sections"][i]["Section"]["ValidationBits"] 374 | ["BitPositionValidity"] = 375 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 376 | : "Invalid"; 377 | break; 378 | case 3: 379 | j["Sections"][i]["Section"]["ValidationBits"] 380 | ["PlatformRequestorIDValidity"] = 381 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 382 | : "Invalid"; 383 | break; 384 | case 4: 385 | j["Sections"][i]["Section"]["ValidationBits"] 386 | ["PlatformResponderIDValidity"] = 387 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 388 | : "Invalid"; 389 | break; 390 | case 5: 391 | j["Sections"][i]["Section"]["ValidationBits"] 392 | ["MemoryPlatformTargetValidity"] = 393 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 394 | : "Invalid"; 395 | break; 396 | case 6: 397 | j["Sections"][i]["Section"]["ValidationBits"] 398 | ["MemoryErrorTypeValidity"] = 399 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 400 | : "Invalid"; 401 | break; 402 | case 7: 403 | j["Sections"][i]["Section"]["ValidationBits"] 404 | ["RankNumberValidity"] = 405 | (((int)input[6] & (0x01 << k)) == (0x01 << k)) ? "Valid" 406 | : "Invalid"; 407 | break; 408 | } 409 | } 410 | for (int k = 0; k < 6; k++) 411 | { 412 | switch (k) 413 | { 414 | case 0: 415 | j["Sections"][i]["Section"]["ValidationBits"] 416 | ["CardHandleValidity"] = 417 | (((int)input[5] & (0x01 << k)) == (0x01 << k)) ? "Valid" 418 | : "Invalid"; 419 | break; 420 | case 1: 421 | j["Sections"][i]["Section"]["ValidationBits"] 422 | ["ModuleHandleValidity"] = 423 | (((int)input[5] & (0x01 << k)) == (0x01 << k)) ? "Valid" 424 | : "Invalid"; 425 | break; 426 | case 2: 427 | j["Sections"][i]["Section"]["ValidationBits"] 428 | ["ExtendedRowValidity"] = 429 | (((int)input[5] & (0x01 << k)) == (0x01 << k)) ? "Valid" 430 | : "Invalid"; 431 | break; 432 | case 3: 433 | j["Sections"][i]["Section"]["ValidationBits"] 434 | ["BankGroupValidity"] = 435 | (((int)input[5] & (0x01 << k)) == (0x01 << k)) ? "Valid" 436 | : "Invalid"; 437 | break; 438 | case 4: 439 | j["Sections"][i]["Section"]["ValidationBits"] 440 | ["BankAddressValidity"] = 441 | (((int)input[5] & (0x01 << k)) == (0x01 << k)) ? "Valid" 442 | : "Invalid"; 443 | break; 444 | case 5: 445 | j["Sections"][i]["Section"]["ValidationBits"] 446 | ["ChipIdentificationValidity"] = 447 | (((int)input[5] & (0x01 << k)) == (0x01 << k)) ? "Valid" 448 | : "Invalid"; 449 | break; 450 | } 451 | } 452 | } 453 | 454 | /** 455 | * Function to check for validation bits in PCI Express error section 456 | * 457 | * This function checks for different bits to be set and appropriately assigns a 458 | * valid or invalid result 459 | * 460 | * @param input is the pointer to the bytes of information to be used and i is 461 | * the section iterator 462 | * @return void 463 | */ 464 | void pcieErrValidationBitsDecode(const unsigned char* input, int i) 465 | { 466 | for (int k = 0; k < 8; k++) 467 | { 468 | switch (k) 469 | { 470 | case 0: 471 | j["Sections"][i]["Section"]["ValidationBits"] 472 | ["PortTypeValidity"] = 473 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 474 | : "Invalid"; 475 | break; 476 | case 1: 477 | j["Sections"][i]["Section"]["ValidationBits"] 478 | ["VersionValidity"] = 479 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 480 | : "Invalid"; 481 | break; 482 | case 2: 483 | j["Sections"][i]["Section"]["ValidationBits"] 484 | ["CommandStatusValidity"] = 485 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 486 | : "Invalid"; 487 | break; 488 | case 3: 489 | j["Sections"][i]["Section"]["ValidationBits"] 490 | ["DeviceIDValidity"] = 491 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 492 | : "Invalid"; 493 | break; 494 | case 4: 495 | j["Sections"][i]["Section"]["ValidationBits"] 496 | ["DeviceSerialNumberValidity"] = 497 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 498 | : "Invalid"; 499 | break; 500 | case 5: 501 | j["Sections"][i]["Section"]["ValidationBits"] 502 | ["BridgeControlStatusValidity"] = 503 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 504 | : "Invalid"; 505 | break; 506 | case 6: 507 | j["Sections"][i]["Section"]["ValidationBits"] 508 | ["CapabilityStructureStatusValidity"] = 509 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 510 | : "Invalid"; 511 | break; 512 | case 7: 513 | j["Sections"][i]["Section"]["ValidationBits"] 514 | ["AERInfoValidity"] = 515 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 516 | : "Invalid"; 517 | break; 518 | } 519 | } 520 | } 521 | 522 | /** 523 | * Function to check for validation bits in ARM Processor error section 524 | * 525 | * This function checks for different bits to be set and appropriately assigns a 526 | * valid or invalid result 527 | * 528 | * @param input is the pointer to the bytes of information to be used and i is 529 | * the section iterator 530 | * @return void 531 | */ 532 | void armErrValidationBitsDecode(const unsigned char* input, int i) 533 | { 534 | for (int k = 0; k < 4; k++) 535 | { 536 | switch (k) 537 | { 538 | case 0: 539 | j["Sections"][i]["Section"]["ValidationBits"]["MPIDRValidity"] = 540 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 541 | : "Invalid"; 542 | break; 543 | case 1: 544 | j["Sections"][i]["Section"]["ValidationBits"] 545 | ["ErrorAffinityLevelValidity"] = 546 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 547 | : "Invalid"; 548 | break; 549 | case 2: 550 | j["Sections"][i]["Section"]["ValidationBits"] 551 | ["RunningStateValidity"] = 552 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 553 | : "Invalid"; 554 | break; 555 | case 3: 556 | j["Sections"][i]["Section"]["ValidationBits"] 557 | ["VendorSpecificInfoValidity"] = 558 | (((int)input[7] & (0x01 << k)) == (0x01 << k)) ? "Valid" 559 | : "Invalid"; 560 | break; 561 | } 562 | } 563 | } 564 | 565 | /** 566 | * Function to check for a particular Error Status Type (Memory Error Section) 567 | * 568 | * This function checks for different values of the error status type and 569 | * defines the type of errors for the same 570 | * 571 | * @param input is the value of the byte in the log file corresponding to error 572 | * type and i is the section iterator 573 | * @return void 574 | */ 575 | void memErrErrorStatusTypeDecode(int input, int i) 576 | { 577 | switch (input) 578 | { 579 | case 1: 580 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 581 | "ERR_INTERNAL"; 582 | break; 583 | case 16: 584 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = "ERR_BUS"; 585 | break; 586 | case 4: 587 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = "ERR_MEM"; 588 | break; 589 | case 5: 590 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = "ERR_TLB"; 591 | break; 592 | case 6: 593 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 594 | "ERR_CACHE"; 595 | break; 596 | case 7: 597 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 598 | "ERR_FUNCTION"; 599 | break; 600 | case 8: 601 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 602 | "ERR_SELFTEST"; 603 | break; 604 | case 9: 605 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 606 | "ERR_FLOW"; 607 | break; 608 | case 17: 609 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = "ERR_MAP"; 610 | break; 611 | case 18: 612 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 613 | "ERR_IMPROPER"; 614 | break; 615 | case 19: 616 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 617 | "ERR_UNIMPL"; 618 | break; 619 | case 20: 620 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = "ERR_LOL"; 621 | break; 622 | case 21: 623 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 624 | "ERR_RESPONSE"; 625 | break; 626 | case 22: 627 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 628 | "ERR_PARITY"; 629 | break; 630 | case 23: 631 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 632 | "ERR_PROTOCOL"; 633 | break; 634 | case 24: 635 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 636 | "ERR_ERROR"; 637 | break; 638 | case 25: 639 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 640 | "ERR_TIMEOUT"; 641 | break; 642 | case 26: 643 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 644 | "ERR_POISONED"; 645 | break; 646 | default: 647 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorType"] = 648 | "Reserved"; 649 | break; 650 | } 651 | } 652 | 653 | /** 654 | * Function to check for a particular Port Type (PCI Express Error Section) 655 | * 656 | * This function checks for different values of the port type and defines the 657 | * type of port for the same 658 | * 659 | * @param input is the value of the byte in the log file corresponding to port 660 | * type and i is the section iterator 661 | * @return void 662 | */ 663 | void pcieErrPortTypeDecode(int input, int i) 664 | { 665 | switch (input) 666 | { 667 | case 0: 668 | j["Sections"][i]["Section"]["PortType"] = "PCI Express End Point"; 669 | break; 670 | case 1: 671 | j["Sections"][i]["Section"]["PortType"] = 672 | "Legacy PCI End Point Device"; 673 | break; 674 | case 4: 675 | j["Sections"][i]["Section"]["PortType"] = "Root Port"; 676 | break; 677 | case 5: 678 | j["Sections"][i]["Section"]["PortType"] = "Upstream Switch Port"; 679 | break; 680 | case 6: 681 | j["Sections"][i]["Section"]["PortType"] = "Downstream Switch Port"; 682 | break; 683 | case 7: 684 | j["Sections"][i]["Section"]["PortType"] = 685 | "PCI Express to PCI/PCI-X Bridge"; 686 | break; 687 | case 8: 688 | j["Sections"][i]["Section"]["PortType"] = 689 | "PCI/PCI-X to PCI Express Bridge"; 690 | break; 691 | case 9: 692 | j["Sections"][i]["Section"]["PortType"] = 693 | "Root Complex Integrated Endpoint Device"; 694 | break; 695 | case 10: 696 | j["Sections"][i]["Section"]["PortType"] = 697 | "Root Complex Event Collector"; 698 | break; 699 | default: 700 | j["Sections"][i]["Section"]["PortType"] = "No port type defined"; 701 | break; 702 | } 703 | } 704 | /** 705 | * Helper function to append 0x to a string 706 | * 707 | * This function appends a 0x in order to represent a string as an address in 708 | * the hex notation 709 | * 710 | * @param input is the string which consisting of an address 711 | * @return string 712 | */ 713 | string addressRepresentation(const string& input) 714 | { 715 | string x("0x"); 716 | x.append(input); 717 | return x; 718 | } 719 | 720 | int main(int argc, char** argv) 721 | { 722 | CLI::App app{"CPER Decoder"}; // label the command line interface 723 | 724 | string inputFile; 725 | string outputFile; 726 | try 727 | { 728 | // input option for the binary blob path 729 | app.add_option("--redfish", inputFile, "Binary File Path"); 730 | // output option for the JSON file 731 | app.add_option("--json", outputFile, "JSON File Path"); 732 | } 733 | catch (CLI::Error& e) 734 | { 735 | return app.exit(e); 736 | } 737 | CLI11_PARSE(app, argc, argv); 738 | 739 | ifstream binFile; 740 | binFile.open(inputFile, ios::in | ios::binary); // open file in read mode 741 | if (!binFile.is_open()) 742 | return app.exit(CLI::FileError::Missing(inputFile)); 743 | 744 | ostringstream ostrm; 745 | ostrm << binFile.rdbuf(); // read the entire input binary file into an 746 | // output stringstream 747 | string line = ostrm.str(); // convert from type ostringstream to string 748 | 749 | // read the file into the header structure to 750 | // be able to segregate fields 751 | const header* p = reinterpret_cast(&line[0]); 752 | 753 | ofstream jsonFile(outputFile); 754 | if (!jsonFile.is_open()) 755 | return app.exit(CLI::FileError::Missing(outputFile)); 756 | 757 | // Write the header fields into the JSON file 758 | string revision = convertToString(p->Revision, sizeof(p->Revision)); 759 | string sectionCount = convertToString(p->SectionCount, 760 | sizeof(p->SectionCount)); 761 | #ifndef PHASE1 762 | j["Header"]["SignatureStart"] = convertToString(p->signatureStart, 763 | sizeof(p->signatureStart)); 764 | j["Header"]["MajorRevision"] = revision[1]; 765 | j["Header"]["MinorRevision"] = revision[0]; 766 | j["Header"]["SignatureEnd"] = 767 | SignatureEndValidation(p->SignatureEnd) ? "Valid" : "Invalid"; 768 | #endif 769 | reverse(sectionCount.begin(), sectionCount.end()); 770 | int secCount = stringToInt(sectionCount); 771 | 772 | j["Header"]["SectionCount"] = secCount; 773 | #ifndef PHASE1 774 | const auto& iterSev = errorSev.find((int)p->ErrorSeverity[0]); 775 | if (iterSev != errorSev.end()) 776 | { 777 | j["Header"]["ErrorSeverity"] = iterSev->second; 778 | } 779 | j["Header"]["PlatformIDValidation"] = 780 | ((int)p->ValidationBits[0] & 0x1) == 0x01 ? "Valid" : "Invalid"; 781 | j["Header"]["TimestampValidation"] = 782 | ((int)p->ValidationBits[0] & 0x2) == 0x02 ? "Valid" : "Invalid"; 783 | j["Header"]["PartitionIDValidation"] = 784 | ((int)p->ValidationBits[0] & 0x4) == 0x04 ? "Valid" : "Invalid"; 785 | j["Header"]["RecordLength"] = 786 | charToIntLittleEndian(p->RecordLength, sizeof(p->RecordLength)); 787 | string time = convertToHex(p->Timestamp, sizeof(p->Timestamp)); 788 | j["Header"]["Timestamp"] = timestampDecode(p->Timestamp, 789 | sizeof(p->Timestamp)); 790 | j["Header"]["PlatformID"] = 791 | guidDecode(convertToHex(p->PlatformID, sizeof(p->PlatformID))); 792 | j["Header"]["PartitionID"] = 793 | guidDecode(convertToHex(p->PartitionID, sizeof(p->PartitionID))); 794 | j["Header"]["CreatorID"] = 795 | guidDecode(convertToHex(p->CreatorID, sizeof(p->CreatorID))); 796 | #endif 797 | j["Header"]["NotificationType"] = guidDecode( 798 | convertToHex(p->NotificationType, sizeof(p->NotificationType))); 799 | #ifndef PHASE1 800 | j["Header"]["RecordID"] = convertToHex(p->RecordID, sizeof(p->RecordID)); 801 | const auto& iterFlags = headerFlags.find((int)p->Flags[0]); 802 | if (iterFlags != headerFlags.end()) 803 | { 804 | j["Header"]["Flags"] = iterFlags->second; 805 | } 806 | else 807 | { 808 | j["Header"]["Flags"] = "No Flags set"; 809 | } 810 | j["Header"]["PersistenceInformation"] = 811 | "Field defined by the creator. Out of scope of this specification"; 812 | #endif 813 | // Writing the Section Descriptors into the JSON file 814 | const char* lineC = line.c_str(); 815 | vector sections(secCount); 816 | vector secOffset(secCount); 817 | vector secLength(secCount); 818 | vector secTrack(secCount); 819 | vector secTrackString(secCount); 820 | for (int i = 0; i < secCount; i++) 821 | { 822 | memcpy(§ions[i], 823 | lineC + sbmrOffset + headerSize + (secDescSize * i), 72); 824 | } 825 | for (int i = 0; i < secCount; i++) 826 | { 827 | secOffset[i] = charToIntLittleEndian(sections[i].sectionOffset, 828 | sizeof(sections[i].sectionOffset)); 829 | secLength[i] = charToIntLittleEndian(sections[i].sectionLength, 830 | sizeof(sections[i].sectionLength)); 831 | (void)secLength[i]; 832 | #ifndef PHASE1 833 | j["Sections"][i]["SectionDescriptor"]["SectionOffset"] = secOffset[i]; 834 | j["Sections"][i]["SectionDescriptor"]["SectionLength"] = secLength[i]; 835 | string rev = (convertToString(sections[i].revision, 836 | sizeof(sections[i].revision))); 837 | j["Sections"][i]["SectionDescriptor"]["MajorRevision"] = rev[1]; 838 | j["Sections"][i]["SectionDescriptor"]["MinorRevision"] = rev[0]; 839 | j["Sections"][i]["SectionDescriptor"]["FRUIdValidity"] = 840 | ((((int)sections[i].validationBits[0]) & 0x01) == 0x01) 841 | ? "FRUId Valid" 842 | : "FRUId Invalid"; 843 | j["Sections"][i]["SectionDescriptor"]["FRUStringValidity"] = 844 | ((((int)sections[i].validationBits[0]) & 0x02) == 0x02) 845 | ? "FRUString Valid" 846 | : "FRUString Invalid"; 847 | 848 | string flagErrors[8] = {"Primary Error", 849 | "Containment Warning", 850 | "Reset", 851 | "Error threshold exceeded", 852 | "Resource not accessible", 853 | "Latent Error", 854 | "Propogated", 855 | "Overflow"}; 856 | int count = 0; 857 | for (int k = 0; k < 8; k++) 858 | { 859 | if (((int)sections[i].flags[0] & (0x01 << k)) == (0x01 << k)) 860 | { 861 | j["Sections"][i]["SectionDescriptor"]["Flags"][count] = 862 | flagErrors[k]; 863 | count = count + 1; 864 | } 865 | } 866 | if (count == 0) 867 | { 868 | j["Sections"][i]["SectionDescriptor"]["Flags"][count] = 869 | "No Flags Set"; 870 | } 871 | #endif 872 | string temp = convertToHex(sections[i].sectionType, 873 | sizeof(sections[i].sectionType)); 874 | if (temp.compare(nvda) == 0) 875 | { 876 | secTrack[i] = 1; 877 | secTrackString[i] = "NVIDIA CPER Error Section"; 878 | } 879 | else if (temp.compare(memErr) == 0) 880 | { 881 | secTrack[i] = 2; 882 | secTrackString[i] = "General Memory Error Section"; 883 | } 884 | else if (temp.compare(pciExpress) == 0) 885 | { 886 | secTrack[i] = 3; 887 | secTrackString[i] = "PCIe Error Section"; 888 | } 889 | else if (temp.compare(armProcErr) == 0) 890 | { 891 | secTrack[i] = 4; 892 | secTrackString[i] = "ARM Processor Error Section"; 893 | } 894 | 895 | // j["Sections"][i]["SectionDescriptor"]["SectionType"] = 896 | // guidDecode(temp); 897 | j["Sections"][i]["SectionDescriptor"]["SectionType"] = 898 | secTrackString[i]; 899 | j["Sections"][i]["SectionDescriptor"]["FRUId"] = guidDecode( 900 | convertToHex(sections[i].fruID, sizeof(sections[i].fruID))); 901 | const auto& iterSev = 902 | errorSev.find((int)sections[i].sectionSeverity[0]); 903 | if (iterSev != errorSev.end()) 904 | { 905 | j["Sections"][i]["SectionDescriptor"]["SectionSeverity"] = 906 | iterSev->second; 907 | } 908 | #ifndef PHASE1 909 | j["Sections"][i]["SectionDescriptor"]["FRUText"] = 910 | (convertToHex(sections[i].fruText, sizeof(sections[i].fruText))); 911 | #endif 912 | } 913 | 914 | // Writing NV CPER Sections into JSON file 915 | vector regDataPairs(secCount); 916 | vector
secDecode(secCount); 917 | vector decodeMemErr(secCount); 918 | vector decodePcieErr(secCount); 919 | vector decodeArmProcErr(secCount); 920 | for (int i = 0; i < secCount; i++) 921 | { 922 | if (secTrack[i] == 1) 923 | { // condition to check if it is an NV CPER 924 | memcpy(&secDecode[i], 925 | lineC + secOffset[i] + sbmrOffset + recordHeaderLen, 32); 926 | j["Sections"][i]["Section"]["IPSignature"] = (convertToStringAscii( 927 | secDecode[i].IPSignature, sizeof(secDecode[i].IPSignature))); 928 | #ifndef PHASE1 929 | j["Sections"][i]["Section"]["ErrorType"] = (charToIntLittleEndian( 930 | secDecode[i].ErrorType, sizeof(secDecode[i].ErrorType))); 931 | j["Sections"][i]["Section"]["ErrorInstance"] = 932 | (charToIntLittleEndian(secDecode[i].ErrorInstance, 933 | sizeof(secDecode[i].ErrorInstance))); 934 | #endif 935 | const auto& iterSev = errorSev.find((int)secDecode[i].Severity[0]); 936 | if (iterSev != errorSev.end()) 937 | { 938 | j["Sections"][i]["Section"]["Severity"] = iterSev->second; 939 | } 940 | j["Sections"][i]["Section"]["SocketNumber"] = 941 | (charToIntLittleEndian(secDecode[i].SocketNumber, 942 | sizeof(secDecode[i].SocketNumber))); 943 | #ifndef PHASE1 944 | regDataPairs[i] = (charToIntLittleEndian( 945 | secDecode[i].RegDataPairs, sizeof(secDecode[i].RegDataPairs))); 946 | j["Sections"][i]["Section"]["NumberOfRegisterDataPairs"] = 947 | regDataPairs[i]; 948 | j["Sections"][i]["Section"]["InstanceBase"] = addressRepresentation( 949 | convertToHexLittleEndian(secDecode[i].InstanceBase, 950 | sizeof(secDecode[i].InstanceBase))); 951 | #endif 952 | } 953 | 954 | // Writing Memory Error Section into JSON 955 | else if (secTrack[i] == 2) 956 | { // condition to check if it is a memory error section 957 | memcpy(&decodeMemErr[i], 958 | lineC + sbmrOffset + secOffset[i] + recordHeaderLen, 80); 959 | #ifndef PHASE1 960 | memErrValidationBitsDecode(decodeMemErr[i].validationBits, i); 961 | memErrErrorStatusTypeDecode((int)decodeMemErr[i].errorStatus[6], i); 962 | string errorStatusFields[7] = { 963 | "Address Error Detected", "Control Error Detected", 964 | "Data Error Detected", "Responder Error Detected", 965 | "Requester Error Detected", "First Error Detected", 966 | "Overflow Error Detected"}; 967 | int count = 0; 968 | for (int k = 0; k < 7; k++) 969 | { 970 | if (((int)decodeMemErr[i].errorStatus[5] & (0x01 << k)) == 971 | (0x01 << k)) 972 | { 973 | j["Sections"][i]["Section"]["ErrorStatus"] 974 | ["ErrorStatusField"][count] = errorStatusFields[k]; 975 | count = count + 1; 976 | } 977 | } 978 | if (count == 0) 979 | { 980 | j["Sections"][i]["Section"]["ErrorStatus"]["ErrorStatusField"] 981 | [count] = "No Error Status Fields Set"; 982 | } 983 | j["Sections"][i]["Section"]["PhysicalAddress"] = 984 | addressRepresentation(convertToHexLittleEndian( 985 | decodeMemErr[i].physicalAddress, 986 | sizeof(decodeMemErr[i].physicalAddress))); 987 | j["Sections"][i]["Section"]["PhysicalAddressMask"] = 988 | addressRepresentation(convertToHexLittleEndian( 989 | decodeMemErr[i].physicalAddressMask, 990 | sizeof(decodeMemErr[i].physicalAddressMask))); 991 | j["Sections"][i]["Section"]["Node"] = (charToIntLittleEndian( 992 | decodeMemErr[i].node, sizeof(decodeMemErr[i].node))); 993 | j["Sections"][i]["Section"]["Card"] = (charToIntLittleEndian( 994 | decodeMemErr[i].card, sizeof(decodeMemErr[i].card))); 995 | j["Sections"][i]["Section"]["Module"] = (charToIntLittleEndian( 996 | decodeMemErr[i].module, sizeof(decodeMemErr[i].module))); 997 | j["Sections"][i]["Section"]["BankAddress"] = 998 | (charToIntLittleEndian(decodeMemErr[i].bankAddress, 999 | sizeof(decodeMemErr[i].bankAddress))); 1000 | j["Sections"][i]["Section"]["BankGroup"] = (charToIntLittleEndian( 1001 | decodeMemErr[i].bankGroup, sizeof(decodeMemErr[i].bankGroup))); 1002 | j["Sections"][i]["Section"]["Device"] = (charToIntLittleEndian( 1003 | decodeMemErr[i].device, sizeof(decodeMemErr[i].device))); 1004 | j["Sections"][i]["Section"]["Row"] = (charToIntLittleEndian( 1005 | decodeMemErr[i].row, sizeof(decodeMemErr[i].row))); 1006 | j["Sections"][i]["Section"]["Column"] = (charToIntLittleEndian( 1007 | decodeMemErr[i].column, sizeof(decodeMemErr[i].column))); 1008 | j["Sections"][i]["Section"]["BitPosition"] = 1009 | (charToIntLittleEndian(decodeMemErr[i].bitPosition, 1010 | sizeof(decodeMemErr[i].bitPosition))); 1011 | j["Sections"][i]["Section"]["RequestorID"] = addressRepresentation( 1012 | convertToHexLittleEndian(decodeMemErr[i].requestorID, 1013 | sizeof(decodeMemErr[i].requestorID))); 1014 | j["Sections"][i]["Section"]["ResponderID"] = addressRepresentation( 1015 | convertToHexLittleEndian(decodeMemErr[i].responderID, 1016 | sizeof(decodeMemErr[i].responderID))); 1017 | j["Sections"][i]["Section"]["TargetID"] = addressRepresentation( 1018 | convertToHexLittleEndian(decodeMemErr[i].targetID, 1019 | sizeof(decodeMemErr[i].targetID))); 1020 | const auto& iterMem = 1021 | memErrType.find((int)decodeMemErr[i].memErrType[0]); 1022 | if (iterMem != memErrType.end()) 1023 | { 1024 | j["Sections"][i]["Section"]["MemoryErrorType"] = 1025 | iterMem->second; 1026 | } 1027 | else 1028 | { 1029 | j["Sections"][i]["Section"]["MemoryErrorType"] = "Reserved"; 1030 | } 1031 | j["Sections"][i]["Section"]["Extended"]["ChipIdentification"] = 1032 | (((int)decodeMemErr[i].extended[0]) >> 5) & 0x07; 1033 | j["Sections"][i]["Section"]["RankNumber"] = 1034 | (charToIntLittleEndian(decodeMemErr[i].rankNumber, 1035 | sizeof(decodeMemErr[i].rankNumber))); 1036 | j["Sections"][i]["Section"]["CardHandle"] = 1037 | (charToIntLittleEndian(decodeMemErr[i].cardHandle, 1038 | sizeof(decodeMemErr[i].cardHandle))); 1039 | j["Sections"][i]["Section"]["ModuleHandle"] = 1040 | (charToIntLittleEndian(decodeMemErr[i].moduleHandle, 1041 | sizeof(decodeMemErr[i].moduleHandle))); 1042 | #endif 1043 | } 1044 | 1045 | // Writing UEFI based PCI Express Error Section into JSON 1046 | // NOTE: THIS SECTION NEEDS TO BE RE REVIEWED FOR ENDIANNESS CHANGES AND 1047 | // BYTE ORDERING. HAS BEEN DEVELOPED WITH NO RELIABLE INPUT. EXPECT 1048 | // MINOR CHANGES. 1049 | else if (secTrack[i] == 3) 1050 | { 1051 | memcpy(&decodePcieErr[i], 1052 | lineC + sbmrOffset + secOffset[i] + recordHeaderLen, 208); 1053 | #ifndef PHASE1 1054 | pcieErrValidationBitsDecode(decodePcieErr[i].validationBits, i); 1055 | pcieErrPortTypeDecode((int)decodePcieErr[i].portType[3], i); 1056 | 1057 | j["Sections"][i]["Section"]["MajorVersion"] = 1058 | (int)decodePcieErr[i].version[2]; 1059 | j["Sections"][i]["Section"]["MinorVersion"] = 1060 | (int)decodePcieErr[i].version[3]; 1061 | 1062 | j["Sections"][i]["Section"]["CommandStatus"]["PCICommandRegister"] = 1063 | addressRepresentation(convertToHexLittleEndian( 1064 | decodePcieErr[i].pciCommandReg, 1065 | sizeof(decodePcieErr[i].pciCommandReg))); 1066 | j["Sections"][i]["Section"]["CommandStatus"]["PCIStatusRegister"] = 1067 | addressRepresentation(convertToHexLittleEndian( 1068 | decodePcieErr[i].pciStatusReg, 1069 | sizeof(decodePcieErr[i].pciStatusReg))); 1070 | #endif 1071 | j["Sections"][i]["Section"]["DeviceID"]["VendorID"] = 1072 | addressRepresentation(convertToHexLittleEndian( 1073 | decodePcieErr[i].vendorID, 1074 | sizeof(decodePcieErr[i].vendorID))); 1075 | j["Sections"][i]["Section"]["DeviceID"]["DeviceID"] = 1076 | addressRepresentation(convertToHexLittleEndian( 1077 | decodePcieErr[i].deviceID, 1078 | sizeof(decodePcieErr[i].deviceID))); 1079 | j["Sections"][i]["Section"]["DeviceID"]["ClassCode"] = 1080 | addressRepresentation(convertToHexLittleEndian( 1081 | decodePcieErr[i].classCode, 1082 | sizeof(decodePcieErr[i].classCode))); 1083 | j["Sections"][i]["Section"]["DeviceID"]["FunctionNumber"] = 1084 | addressRepresentation(convertToHexLittleEndian( 1085 | decodePcieErr[i].functionNumber, 1086 | sizeof(decodePcieErr[i].functionNumber))); 1087 | j["Sections"][i]["Section"]["DeviceID"]["DeviceNumber"] = 1088 | addressRepresentation(convertToHexLittleEndian( 1089 | decodePcieErr[i].deviceNumber, 1090 | sizeof(decodePcieErr[i].deviceNumber))); 1091 | j["Sections"][i]["Section"]["DeviceID"]["SegmentNumber"] = 1092 | addressRepresentation(convertToHexLittleEndian( 1093 | decodePcieErr[i].segmentNumber, 1094 | sizeof(decodePcieErr[i].segmentNumber))); 1095 | j["Sections"][i]["Section"]["DeviceID"]["DeviceBusNumber"] = 1096 | addressRepresentation(convertToHexLittleEndian( 1097 | decodePcieErr[i].deviceBusNumber, 1098 | sizeof(decodePcieErr[i].deviceBusNumber))); 1099 | j["Sections"][i]["Section"]["DeviceID"]["SecondaryBusNumber"] = 1100 | addressRepresentation(convertToHexLittleEndian( 1101 | decodePcieErr[i].deviceSecondaryBusNumber, 1102 | sizeof(decodePcieErr[i].deviceSecondaryBusNumber))); 1103 | j["Sections"][i]["Section"]["DeviceID"]["SlotNumber"] = 1104 | (charToIntLittleEndian(decodePcieErr[i].slotNumber, 1105 | sizeof(decodePcieErr[i].slotNumber))) & 1106 | (0xFFF8); 1107 | #ifndef PHASE1 1108 | j["Sections"][i]["Section"]["DeviceSerialNumber"]["LowerDW"] = 1109 | addressRepresentation(convertToHexLittleEndian( 1110 | decodePcieErr[i].lowerDeviceSerialNumber, 1111 | sizeof(decodePcieErr[i].lowerDeviceSerialNumber))); 1112 | j["Sections"][i]["Section"]["DeviceSerialNumber"]["UpperDW"] = 1113 | addressRepresentation(convertToHexLittleEndian( 1114 | decodePcieErr[i].upperDeviceSerialNumber, 1115 | sizeof(decodePcieErr[i].upperDeviceSerialNumber))); 1116 | j["Sections"][i]["Section"]["BridgeControlStatus"] 1117 | ["BridgeSecondaryStatusRegister"] = 1118 | addressRepresentation(convertToHexLittleEndian( 1119 | decodePcieErr[i].bridgeSecondaryStatusReg, 1120 | sizeof(decodePcieErr[i].bridgeSecondaryStatusReg))); 1121 | j["Sections"][i]["Section"]["BridgeControlStatus"] 1122 | ["BridgeControlRegister"] = 1123 | addressRepresentation(convertToHexLittleEndian( 1124 | decodePcieErr[i].bridgeControlReg, 1125 | sizeof(decodePcieErr[i].bridgeControlReg))); 1126 | j["Sections"][i]["Section"]["CapabilityStructure"] = 1127 | addressRepresentation(convertToHexLittleEndian( 1128 | decodePcieErr[i].capabilityStructure, 1129 | sizeof(decodePcieErr[i].capabilityStructure))); 1130 | j["Sections"][i]["Section"]["AERInfo"] = addressRepresentation( 1131 | convertToHexLittleEndian(decodePcieErr[i].aerInfo, 1132 | sizeof(decodePcieErr[i].aerInfo))); 1133 | #endif 1134 | } 1135 | else if (secTrack[i] == 4) 1136 | { 1137 | memcpy(&decodeArmProcErr[i], 1138 | lineC + sbmrOffset + secOffset[i] + recordHeaderLen, 40); 1139 | #ifndef PHASE1 1140 | armErrValidationBitsDecode(decodeArmProcErr[i].validationBits, i); 1141 | long int numErrInfo = 1142 | charToIntLittleEndian(decodeArmProcErr[i].errInfoNum, 1143 | sizeof(decodeArmProcErr[i].errInfoNum)); 1144 | long int numContextInfo = charToIntLittleEndian( 1145 | decodeArmProcErr[i].contexInfoNum, 1146 | sizeof(decodeArmProcErr[i].contexInfoNum)); 1147 | long int secLenArm = 1148 | charToIntLittleEndian(decodeArmProcErr[i].armSecLength, 1149 | sizeof(decodeArmProcErr[i].armSecLength)); 1150 | long int affLvl = 1151 | charToIntLittleEndian(decodeArmProcErr[i].errAffLvl, 1152 | sizeof(decodeArmProcErr[i].errAffLvl)); 1153 | j["Sections"][i]["Section"]["ErrorInfoNum"] = numErrInfo; 1154 | j["Sections"][i]["Section"]["ContextInfoNum"] = numContextInfo; 1155 | j["Sections"][i]["Section"]["SectionLength"] = secLenArm; 1156 | j["Sections"][i]["Section"]["ErrorAffinityLevel"] = affLvl; 1157 | #endif 1158 | j["Sections"][i]["Section"]["SocketNumber"] = 1159 | (int)decodeArmProcErr[i].MPIDR[4]; 1160 | } 1161 | } 1162 | 1163 | // Code fragment to decode the register/data pairs and write into a JSON 1164 | // object 1165 | #ifndef PHASE1 1166 | registers reg[1]; 1167 | for (int i = 0; i < secCount; i++) 1168 | { 1169 | if (secTrack[i] == 1) 1170 | { 1171 | for (int k = 0; k < regDataPairs[i]; k++) 1172 | { 1173 | memcpy(®[0], 1174 | lineC + sbmrOffset + secOffset[i] + recordHeaderLen + 1175 | 32 + (16 * k), 1176 | 16); 1177 | 1178 | j["Sections"][i]["Section"]["Registers"][k]["Address"] = 1179 | addressRepresentation(convertToHexLittleEndian( 1180 | reg[0].address, sizeof(reg[0].address))); 1181 | j["Sections"][i]["Section"]["Registers"][k]["Value"] = 1182 | addressRepresentation(convertToHexLittleEndian( 1183 | reg[0].value, sizeof(reg[0].value))); 1184 | } 1185 | } 1186 | } 1187 | #endif 1188 | 1189 | // writing all the json objects into the JSON file before closing the file 1190 | jsonFile << j; 1191 | jsonFile.close(); 1192 | return 0; 1193 | } 1194 | --------------------------------------------------------------------------------