blob: 33c7af791b84535212e134a9d1418b2535cdbf65 [file] [log] [blame]
Lawrence Tangb8fa2f72022-07-18 10:50:19 +01001/**
2 * A user-space application linking to the CPER-JSON conversion library which allows for easy
Ed Tanousfedd4572024-07-12 13:56:00 -07003 * conversion between CPER and CPER-JSON formats.
4 *
Lawrence Tangb8fa2f72022-07-18 10:50:19 +01005 * Author: Lawrence.Tang@arm.com
6 **/
7
8#include <stdio.h>
9#include <string.h>
10#include <libgen.h>
Andrew Adriance4482c482024-07-02 14:55:11 -070011#include <limits.h>
Lawrence Tang5202bbb2022-08-12 14:54:36 +010012#include <json.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000013#include <libcper/cper-parse.h>
14#include <libcper/json-schema.h>
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010015
Lawrence Tang617949e2022-08-08 14:21:42 +010016void cper_to_json(char *in_file, char *out_file, int is_single_section);
Ed Tanous4bdb2262025-03-10 21:13:46 -070017void json_to_cper(char *in_file, char *out_file);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010018void print_help(void);
19
Lawrence Tange407b4c2022-07-21 13:54:01 +010020int main(int argc, char *argv[])
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010021{
Lawrence Tang5f388a32022-08-08 10:49:02 +010022 //Print help if requested.
23 if (argc == 2 && strcmp(argv[1], "--help") == 0) {
24 print_help();
25 return 0;
26 }
27
28 //Ensure at least two arguments are present.
29 if (argc < 3) {
Lawrence Tange407b4c2022-07-21 13:54:01 +010030 printf("Invalid number of arguments. See 'cper-convert --help' for command information.\n");
31 return -1;
32 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010033
Lawrence Tang71c70a32022-08-08 09:16:06 +010034 //Parse the command line arguments.
Lawrence Tang5f388a32022-08-08 10:49:02 +010035 char *input_file = argv[2];
36 char *output_file = NULL;
37 char *specification_file = NULL;
38 int no_validate = 0;
39 int debug = 0;
40 for (int i = 3; i < argc; i++) {
41 if (strcmp(argv[i], "--out") == 0 && i < argc - 1) {
42 //Output file.
43 output_file = argv[i + 1];
44 i++;
45 } else if (strcmp(argv[i], "--specification") == 0 &&
46 i < argc - 1) {
47 //Specification file.
48 specification_file = argv[i + 1];
49 i++;
50 } else if (strcmp(argv[i], "--no-validate") == 0) {
51 //No validation to be used.
52 //Invalidates specification file.
53 specification_file = NULL;
54 no_validate = 1;
55 } else if (strcmp(argv[i], "--debug") == 0) {
56 //Debug output on.
57 debug = 1;
58 } else {
59 printf("Unrecognised argument '%s'. See 'cper-convert --help' for command information.\n",
60 argv[i]);
61 }
62 }
Lawrence Tang71c70a32022-08-08 09:16:06 +010063
Ed Tanous4bdb2262025-03-10 21:13:46 -070064 // Debug is not used at the moment. Leave for compatibility.
65 (void)debug;
66 (void)no_validate;
67 (void)specification_file;
Lawrence Tange407b4c2022-07-21 13:54:01 +010068 //Run the requested command.
Lawrence Tang617949e2022-08-08 14:21:42 +010069 if (strcmp(argv[1], "to-json") == 0) {
70 cper_to_json(input_file, output_file, 0);
71 } else if (strcmp(argv[1], "to-json-section") == 0) {
72 cper_to_json(input_file, output_file, 1);
73 } else if (strcmp(argv[1], "to-cper") == 0) {
Ed Tanous4bdb2262025-03-10 21:13:46 -070074 json_to_cper(input_file, output_file);
Lawrence Tang617949e2022-08-08 14:21:42 +010075 } else {
Lawrence Tange407b4c2022-07-21 13:54:01 +010076 printf("Unrecognised argument '%s'. See 'cper-convert --help' for command information.\n",
77 argv[1]);
78 return -1;
79 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010080
Lawrence Tange407b4c2022-07-21 13:54:01 +010081 return 0;
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010082}
83
Lawrence Tang617949e2022-08-08 14:21:42 +010084//Command for converting a provided CPER log file or CPER single section file into JSON.
85void cper_to_json(char *in_file, char *out_file, int is_single_section)
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010086{
Lawrence Tange407b4c2022-07-21 13:54:01 +010087 //Get a handle for the log file.
Lawrence Tang5f388a32022-08-08 10:49:02 +010088 FILE *cper_file = fopen(in_file, "r");
Lawrence Tange407b4c2022-07-21 13:54:01 +010089 if (cper_file == NULL) {
90 printf("Could not open provided CPER file '%s', file handle returned null.\n",
Lawrence Tang5f388a32022-08-08 10:49:02 +010091 in_file);
Lawrence Tange407b4c2022-07-21 13:54:01 +010092 return;
93 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +010094
Lawrence Tange407b4c2022-07-21 13:54:01 +010095 //Convert.
Lawrence Tang617949e2022-08-08 14:21:42 +010096 json_object *ir;
John Chungf8fc7052024-05-03 20:05:29 +080097 if (is_single_section) {
Lawrence Tang617949e2022-08-08 14:21:42 +010098 ir = cper_single_section_to_ir(cper_file);
John Chungf8fc7052024-05-03 20:05:29 +080099 } else {
Lawrence Tang617949e2022-08-08 14:21:42 +0100100 ir = cper_to_ir(cper_file);
John Chungf8fc7052024-05-03 20:05:29 +0800101 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100102 fclose(cper_file);
Lawrence Tang617949e2022-08-08 14:21:42 +0100103
104 //Output to string.
Lawrence Tange407b4c2022-07-21 13:54:01 +0100105 const char *json_output =
106 json_object_to_json_string_ext(ir, JSON_C_TO_STRING_PRETTY);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100107
Lawrence Tange407b4c2022-07-21 13:54:01 +0100108 //Check whether there is a "--out" argument, if there is, then output to file instead.
109 //Otherwise, just send to console.
Lawrence Tang5f388a32022-08-08 10:49:02 +0100110 if (out_file == NULL) {
Lawrence Tange407b4c2022-07-21 13:54:01 +0100111 printf("%s\n", json_output);
112 return;
113 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100114
Lawrence Tange407b4c2022-07-21 13:54:01 +0100115 //Try to open a file handle to the desired output file.
Lawrence Tang5f388a32022-08-08 10:49:02 +0100116 FILE *json_file = fopen(out_file, "w");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100117 if (json_file == NULL) {
118 printf("Could not get a handle for output file '%s', file handle returned null.\n",
Lawrence Tang5f388a32022-08-08 10:49:02 +0100119 out_file);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100120 return;
121 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100122
Lawrence Tange407b4c2022-07-21 13:54:01 +0100123 //Write out to file.
124 fwrite(json_output, strlen(json_output), 1, json_file);
125 fclose(json_file);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100126}
127
128//Command for converting a provided CPER-JSON JSON file to CPER binary.
Ed Tanous4bdb2262025-03-10 21:13:46 -0700129void json_to_cper(char *in_file, char *out_file)
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100130{
Lawrence Tang5f388a32022-08-08 10:49:02 +0100131 //Verify output file exists.
132 if (out_file == NULL) {
133 printf("No output file provided for 'to-cper'. See 'cper-convert --help' for command information.\n");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100134 return;
135 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100136
Lawrence Tange407b4c2022-07-21 13:54:01 +0100137 //Read JSON IR from file.
Lawrence Tang5f388a32022-08-08 10:49:02 +0100138 json_object *ir = json_object_from_file(in_file);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100139 if (ir == NULL) {
140 printf("Could not read JSON from file '%s', import returned null.\n",
Lawrence Tang5f388a32022-08-08 10:49:02 +0100141 in_file);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100142 return;
143 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100144
Lawrence Tange407b4c2022-07-21 13:54:01 +0100145 //Open a read for the output file.
Lawrence Tang5f388a32022-08-08 10:49:02 +0100146 FILE *cper_file = fopen(out_file, "w");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100147 if (cper_file == NULL) {
148 printf("Could not open output file '%s', file handle returned null.\n",
Lawrence Tang5f388a32022-08-08 10:49:02 +0100149 out_file);
Lawrence Tange407b4c2022-07-21 13:54:01 +0100150 return;
151 }
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100152
Lawrence Tang617949e2022-08-08 14:21:42 +0100153 //Detect the type of CPER (full log, single section) from the IR given.
154 //Run the converter accordingly.
John Chungf8fc7052024-05-03 20:05:29 +0800155 if (json_object_object_get(ir, "header") != NULL) {
Lawrence Tang617949e2022-08-08 14:21:42 +0100156 ir_to_cper(ir, cper_file);
John Chungf8fc7052024-05-03 20:05:29 +0800157 } else {
Lawrence Tang617949e2022-08-08 14:21:42 +0100158 ir_single_section_to_cper(ir, cper_file);
John Chungf8fc7052024-05-03 20:05:29 +0800159 }
Lawrence Tange407b4c2022-07-21 13:54:01 +0100160 fclose(cper_file);
John Chungf8fc7052024-05-03 20:05:29 +0800161 json_object_put(ir);
Lawrence Tangb8fa2f72022-07-18 10:50:19 +0100162}
163
164//Command for printing help information.
165void print_help(void)
166{
Lawrence Tange407b4c2022-07-21 13:54:01 +0100167 printf(":: to-json cper.file [--out file.name]\n");
Lawrence Tang5f388a32022-08-08 10:49:02 +0100168 printf("\tConverts the provided CPER log file into JSON, by default writing to stdout. If '--out' is specified,\n");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100169 printf("\tThe outputted JSON will be written to the provided file name instead.\n");
Lawrence Tang617949e2022-08-08 14:21:42 +0100170 printf("\n:: to-json-section cper.section.file [--out file.name]\n");
171 printf("\tConverts the provided single CPER section descriptor & section file into JSON, by default writing to stdout.\n");
172 printf("\tOtherwise behaves the same as 'to-json'.\n");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100173 printf("\n:: to-cper cper.json --out file.name [--no-validate] [--debug] [--specification some/spec/path.json]\n");
174 printf("\tConverts the provided CPER-JSON JSON file into CPER binary. An output file must be specified with '--out'.\n");
Lawrence Tang617949e2022-08-08 14:21:42 +0100175 printf("\tWill automatically detect whether the JSON passed is a single section, or a whole file,\n");
176 printf("\tand output binary accordingly.\n\n");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100177 printf("\tBy default, the provided JSON will try to be validated against a specification. If no specification file path\n");
178 printf("\tis provided with '--specification', then it will default to 'argv[0] + /specification/cper-json.json'.\n");
179 printf("\tIf the '--no-validate' argument is set, then the provided JSON will not be validated. Be warned, this may cause\n");
Lawrence Tang617949e2022-08-08 14:21:42 +0100180 printf("\tpremature exit/unexpected behaviour in CPER output.\n\n");
Lawrence Tang5f388a32022-08-08 10:49:02 +0100181 printf("\tIf '--debug' is set, then debug output for JSON specification parsing will be printed to stdout.\n");
Lawrence Tange407b4c2022-07-21 13:54:01 +0100182 printf("\n:: --help\n");
183 printf("\tDisplays help information to the console.\n");
John Chungf8fc7052024-05-03 20:05:29 +0800184}