14795d4aeSLawrence Tang /**
24795d4aeSLawrence Tang  * Describes functions for converting generic DMAr CPER sections from binary and JSON format
34795d4aeSLawrence Tang  * into an intermediate format.
44795d4aeSLawrence Tang  *
54795d4aeSLawrence Tang  * Author: Lawrence.Tang@arm.com
64795d4aeSLawrence Tang  **/
74795d4aeSLawrence Tang #include <stdio.h>
84795d4aeSLawrence Tang #include "json.h"
94795d4aeSLawrence Tang #include "../edk/Cper.h"
104795d4aeSLawrence Tang #include "../cper-utils.h"
114795d4aeSLawrence Tang #include "cper-section-dmar-generic.h"
124795d4aeSLawrence Tang 
134795d4aeSLawrence Tang //Converts a single generic DMAr CPER section into JSON IR.
144795d4aeSLawrence Tang json_object* cper_section_dmar_generic_to_ir(void* section, EFI_ERROR_SECTION_DESCRIPTOR* descriptor)
154795d4aeSLawrence Tang {
164795d4aeSLawrence Tang     EFI_DMAR_GENERIC_ERROR_DATA* firmware_error = (EFI_DMAR_GENERIC_ERROR_DATA*)section;
174795d4aeSLawrence Tang     json_object* section_ir = json_object_new_object();
184795d4aeSLawrence Tang 
194795d4aeSLawrence Tang     //Requester ID, segment.
204795d4aeSLawrence Tang     json_object_object_add(section_ir, "requesterID", json_object_new_int(firmware_error->RequesterId));
214795d4aeSLawrence Tang     json_object_object_add(section_ir, "segmentNumber", json_object_new_int(firmware_error->SegmentNumber));
224795d4aeSLawrence Tang 
234795d4aeSLawrence Tang     //Fault reason.
244795d4aeSLawrence Tang     json_object* fault_reason = integer_to_readable_pair_with_desc(firmware_error->FaultReason, 11,
254795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_FAULT_REASON_TYPES_KEYS,
264795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_FAULT_REASON_TYPES_VALUES,
274795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_FAULT_REASON_TYPES_DESCRIPTIONS,
284795d4aeSLawrence Tang         "Unknown (Reserved)");
294795d4aeSLawrence Tang     json_object_object_add(section_ir, "faultReason", fault_reason);
304795d4aeSLawrence Tang 
314795d4aeSLawrence Tang     //Access type.
324795d4aeSLawrence Tang     json_object* access_type = integer_to_readable_pair(firmware_error->AccessType, 2,
334795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_ACCESS_TYPES_KEYS,
344795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_ACCESS_TYPES_VALUES,
354795d4aeSLawrence Tang         "Unknown (Reserved)");
364795d4aeSLawrence Tang     json_object_object_add(section_ir, "accessType", access_type);
374795d4aeSLawrence Tang 
384795d4aeSLawrence Tang     //Address type.
394795d4aeSLawrence Tang     json_object* address_type = integer_to_readable_pair(firmware_error->AddressType, 2,
404795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_ADDRESS_TYPES_KEYS,
414795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_ADDRESS_TYPES_VALUES,
424795d4aeSLawrence Tang         "Unknown (Reserved)");
434795d4aeSLawrence Tang     json_object_object_add(section_ir, "addressType", address_type);
444795d4aeSLawrence Tang 
454795d4aeSLawrence Tang     //Architecture type.
464795d4aeSLawrence Tang     json_object* arch_type = integer_to_readable_pair(firmware_error->ArchType, 2,
474795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_ARCH_TYPES_KEYS,
484795d4aeSLawrence Tang         DMAR_GENERIC_ERROR_ARCH_TYPES_VALUES,
494795d4aeSLawrence Tang         "Unknown (Reserved)");
504795d4aeSLawrence Tang     json_object_object_add(section_ir, "architectureType", arch_type);
514795d4aeSLawrence Tang 
524795d4aeSLawrence Tang     //Device address.
534795d4aeSLawrence Tang     json_object_object_add(section_ir, "deviceAddress", json_object_new_uint64(firmware_error->DeviceAddr));
544795d4aeSLawrence Tang 
554795d4aeSLawrence Tang     return section_ir;
564795d4aeSLawrence Tang }
57*205dd1d7SLawrence Tang 
58*205dd1d7SLawrence Tang //Converts a single generic DMAR CPER-JSON section into CPER binary, outputting to the given stream.
59*205dd1d7SLawrence Tang void ir_section_dmar_generic_to_cper(json_object* section, FILE* out)
60*205dd1d7SLawrence Tang {
61*205dd1d7SLawrence Tang     EFI_DMAR_GENERIC_ERROR_DATA* section_cper =
62*205dd1d7SLawrence Tang         (EFI_DMAR_GENERIC_ERROR_DATA*)calloc(1, sizeof(EFI_DMAR_GENERIC_ERROR_DATA));
63*205dd1d7SLawrence Tang 
64*205dd1d7SLawrence Tang     //Record fields.
65*205dd1d7SLawrence Tang     section_cper->RequesterId = (UINT16)json_object_get_int(json_object_object_get(section, "requesterID"));
66*205dd1d7SLawrence Tang     section_cper->SegmentNumber = (UINT16)json_object_get_int(json_object_object_get(section, "segmentNumber"));
67*205dd1d7SLawrence Tang     section_cper->FaultReason = (UINT8)readable_pair_to_integer(json_object_object_get(section, "faultReason"));
68*205dd1d7SLawrence Tang     section_cper->AccessType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "accessType"));
69*205dd1d7SLawrence Tang     section_cper->AddressType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "addressType"));
70*205dd1d7SLawrence Tang     section_cper->ArchType = (UINT8)readable_pair_to_integer(json_object_object_get(section, "archType"));
71*205dd1d7SLawrence Tang     section_cper->DeviceAddr = json_object_get_uint64(json_object_object_get(section, "deviceAddress"));
72*205dd1d7SLawrence Tang 
73*205dd1d7SLawrence Tang     //Write to stream, free resources.
74*205dd1d7SLawrence Tang     fwrite(&section_cper, sizeof(section_cper), 1, out);
75*205dd1d7SLawrence Tang     fflush(out);
76*205dd1d7SLawrence Tang     free(section_cper);
77*205dd1d7SLawrence Tang }