1 /**
2  * Functions for generating pseudo-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-section.h"
11 
12 //Generates a single pseudo-random generic DMAr error section, saving the resulting address to the given
13 //location. Returns the size of the newly created section.
generate_section_dmar_generic(void ** location)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 pseudo-random VT-d DMAr error section, saving the resulting address to the given
37 //location. Returns the size of the newly created section.
generate_section_dmar_vtd(void ** location)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 	}
48 	UINT8 *fault_record = bytes + 48;
49 	UINT32 *reserved = (UINT32 *)(fault_record);
50 	*reserved &= ~0xFFF;	     //First 12 bits of fault record.
51 	reserved = (UINT32 *)(fault_record + 8);
52 	*reserved &= ~0x1FFF0000;    //Bits 80-92 of fault record.
53 	*(fault_record + 15) &= 0x7; //Very last bit of fault record.
54 
55 	//Set return values, exit.
56 	*location = bytes;
57 	return size;
58 }
59 
60 //Generates a single pseudo-random IOMMU DMAr error section, saving the resulting address to the given
61 //location. Returns the size of the newly created section.
generate_section_dmar_iommu(void ** location)62 size_t generate_section_dmar_iommu(void **location)
63 {
64 	//Create random bytes.
65 	int size = 144;
66 	UINT8 *bytes = generate_random_bytes(size);
67 
68 	//Set reserved areas to zero.
69 	for (int i = 0; i < 7; i++) {
70 		*(bytes + 1 + i) = 0; //Reserved bytes 1 to 7.
71 	}
72 	UINT64 *reserved = (UINT64 *)(bytes + 24);
73 	*reserved = 0;		       //Reserved bytes 24-31.
74 	for (int i = 0; i < 16; i++) {
75 		*(bytes + 48 + i) = 0; //Reserved bytes 48-63.
76 	}
77 
78 	//Set return values, exit.
79 	*location = bytes;
80 	return size;
81 }
82