1 /**
2  * Functions for generating psuedo-random CPER DMAr error sections.
3  *
4  * Author: Lawrence.Tang@arm.com
5  **/
6 
7 #include <stdlib.h>
8 #include "../../edk/BaseTypes.h"
9 #include "../gen-utils.h"
10 #include "gen-sections.h"
11 
12 //Generates a single psuedo-random generic DMAr error section, saving the resulting address to the given
13 //location. Returns the size of the newly created section.
14 size_t generate_section_dmar_generic(void** location)
15 {
16     //Create random bytes.
17     int size = 32;
18     UINT8* bytes = generate_random_bytes(size);
19 
20     //Set reserved areas to zero.
21     UINT64* reserved = (UINT64*)(bytes + 16);
22     *reserved = 0;
23     *(reserved + 1) = 0;
24 
25     //Set expected values.
26     *(bytes + 4) = rand() % 0xC; //Fault reason.
27     *(bytes + 5) = rand() % 2; //Access type.
28     *(bytes + 6) = rand() % 2; //Address type.
29     *(bytes + 7) = rand() % 2 + 1; //Architecture type.
30 
31     //Set return values, exit.
32     *location = bytes;
33     return size;
34 }
35 
36 //Generates a single psuedo-random VT-d DMAr error section, saving the resulting address to the given
37 //location. Returns the size of the newly created section.
38 size_t generate_section_dmar_vtd(void** location)
39 {
40     //Create random bytes.
41     int size = 144;
42     UINT8* bytes = generate_random_bytes(size);
43 
44     //Set reserved areas to zero.
45     for (int i=0; i<12; i++)
46         *(bytes + 36 + i) = 0; //Reserved bytes 36-47.
47     UINT8* fault_record = bytes + 48;
48     UINT32* reserved = (UINT32*)(fault_record);
49     *reserved &= ~0xFFF; //First 12 bits of fault record.
50     reserved = (UINT32*)(fault_record + 10);
51     *reserved &= ~0x1FFF; //Bits 80-92 of fault record.
52     *(fault_record + 15) &= 0x7; //Very last bit of fault record.
53 
54     //Set return values, exit.
55     *location = bytes;
56     return size;
57 }
58 
59 //Generates a single psuedo-random IOMMU DMAr error section, saving the resulting address to the given
60 //location. Returns the size of the newly created section.
61 size_t generate_section_dmar_iommu(void** location)
62 {
63     //Create random bytes.
64     int size = 144;
65     UINT8* bytes = generate_random_bytes(size);
66 
67     //Set reserved areas to zero.
68     for (int i=0; i<7; i++)
69         *(bytes + 1 + i) = 0; //Reserved bytes 1 to 7.
70     UINT64* reserved = (UINT64*)(bytes + 24);
71     *reserved = 0; //Reserved bytes 24-31.
72     for (int i=0; i<16; i++)
73         *(bytes + 48 + i) = 0; //Reserved bytes 48-63.
74 
75     //Set return values, exit.
76     *location = bytes;
77     return size;
78 }