blob: 53fb24c0ed9130d36bd7c4bfb31b14768b158a96 [file] [log] [blame]
Lawrence Tang67cbed62022-07-18 16:44:51 +01001/**
2 * Functions for generating psuedo-random CPER ARM processor sections.
3 *
4 * Author: Lawrence.Tang@arm.com
5 **/
6
7#include <stdlib.h>
8#include <string.h>
9#include "../../edk/BaseTypes.h"
10#include "../gen-utils.h"
11#include "gen-sections.h"
12#define ARM_ERROR_INFO_SIZE 32
13
14void* generate_arm_error_info();
15size_t generate_arm_context_info(void** location);
16
17//Generates a single psuedo-random ARM processor section, saving the resulting address to the given
18//location. Returns the size of the newly created section.
19size_t generate_section_arm(void** location)
20{
21 //Set up for generation of error/context structures.
22 UINT16 error_structure_num = rand() % 4 + 1; //Must be at least 1.
23 UINT16 context_structure_num = rand() % 3;
24 void* error_structures[error_structure_num];
25 void* context_structures[context_structure_num];
26 size_t context_structure_lengths[context_structure_num];
27
28 //Generate the structures.
29 for (int i=0; i<error_structure_num; i++)
30 error_structures[i] = generate_arm_error_info();
31 for (int i=0; i<context_structure_num; i++)
32 context_structure_lengths[i] = generate_arm_context_info(context_structures + i);
33
34 //Determine a random amount of vendor specific info.
35 int vendor_info_len = rand() % 16;
36
37 //Create the section as a whole.
38 size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE);
39 for (int i=0; i<context_structure_num; i++)
40 total_len += context_structure_lengths[i];
41 total_len += vendor_info_len;
42 UINT8* section = generate_random_bytes(total_len);
43
44 //Set header information.
45 UINT16* info_nums = (UINT16*)(section + 4);
46 *info_nums = error_structure_num;
47 *(info_nums + 1) = context_structure_num;
48 UINT32* section_length = (UINT32*)(section + 8);
49 *section_length = total_len;
50
51 //Error affinity.
52 *(section + 12) = rand() % 4;
53
54 //Reserved zero bytes.
55 memset(section + 13, 0, 3);
56
57 //Copy in the sections/context structures, free resources.
58 UINT8* cur_pos = section + 40;
59 for (int i=0; i<error_structure_num; i++)
60 {
61 memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE);
62 free(error_structures[i]);
63 cur_pos += ARM_ERROR_INFO_SIZE;
64 }
65 for (int i=0; i<context_structure_num; i++)
66 {
67 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]);
68 free(context_structures[i]);
69 cur_pos += context_structure_lengths[i];
70 }
71
72 //Set return values and exit.
73 *location = section;
74 return total_len;
75}
76
77//Generates a single pseudo-random ARM error info structure. Must be later freed.
78void* generate_arm_error_info()
79{
80 UINT8* error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE);
81
82 //Version (zero for revision of table referenced), length.
83 *error_info = 0;
84 *(error_info + 1) = ARM_ERROR_INFO_SIZE;
85
86 //Type of error.
87 UINT8 error_type = rand() % 4;
88 *(error_info + 4) = error_type;
89
90 //Make sure reserved bits are zero according with the type.
91 UINT64* error_subinfo = (UINT64*)(error_info + 8);
92 switch (error_type)
93 {
94 //Cache/TLB
95 case 0:
96 case 1:
97 *error_subinfo &= 0xFFFFFFF;
98 break;
99
100 //Bus
101 case 2:
102 *error_subinfo &= 0xFFFFFFFFFFF;
103 break;
104
105 //Microarch/other.
106 default:
107 break;
108 }
109
110 return error_info;
111}
112
113//Generates a single pseudo-random ARM context info structure. Must be later freed.
114size_t generate_arm_context_info(void** location)
115{
116 //Initial length is 8 bytes. Add extra based on type.
117 UINT16 reg_type = rand() % 9;
118 UINT32 reg_size = 0;
119
120 //Set register size.
121 switch (reg_type)
122 {
123 //AARCH32 GPR, AARCH32 EL2
124 case 0:
125 case 2:
126 reg_size = 64;
127 break;
128
129 //AARCH32 EL1
130 case 1:
131 reg_size = 96;
132 break;
133
134 //AARCH32 EL3
135 case 3:
136 reg_size = 8;
137 break;
138
139 //AARCH64 GPR
140 case 4:
141 reg_size = 256;
142 break;
143
144 //AARCH64 EL1
145 case 5:
146 reg_size = 136;
147 break;
148
149 //AARCH64 EL2
150 case 6:
151 reg_size = 120;
152 break;
153
154 //AARCH64 EL3
155 case 7:
156 reg_size = 80;
157 break;
158
159 //Misc. single register.
160 case 8:
161 reg_size = 10;
162 break;
163 }
164
165 //Create context structure randomly.
166 int total_size = 8 + reg_size;
167 UINT16* context_info = (UINT16*)generate_random_bytes(total_size);
168
169 //Set header information.
170 *(context_info + 1) = reg_type;
171 *((UINT32*)(context_info + 2)) = reg_size;
172
173 //Set return values and exit.
174 *location = context_info;
175 return total_size;
176}