blob: ded953d8be00f0dd751a35354615f097fbb38541 [file] [log] [blame]
Lawrence Tang67cbed62022-07-18 16:44:51 +01001/**
Lawrence Tangefe17e22022-08-08 09:16:23 +01002 * Functions for generating pseudo-random CPER ARM processor sections.
Ed Tanousfedd4572024-07-12 13:56:00 -07003 *
Lawrence Tang67cbed62022-07-18 16:44:51 +01004 * Author: Lawrence.Tang@arm.com
5 **/
6
7#include <stdlib.h>
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -08008#include <stdio.h>
Lawrence Tang67cbed62022-07-18 16:44:51 +01009#include <string.h>
Thu Nguyene42fb482024-10-15 14:43:11 +000010#include <libcper/BaseTypes.h>
11#include <libcper/generator/gen-utils.h>
12#include <libcper/generator/sections/gen-section.h>
Lawrence Tang67cbed62022-07-18 16:44:51 +010013#define ARM_ERROR_INFO_SIZE 32
14
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080015void *generate_arm_error_info(GEN_VALID_BITS_TEST_TYPE validBitsType);
John Chungf8fc7052024-05-03 20:05:29 +080016size_t generate_arm_context_info(void **location);
Lawrence Tang67cbed62022-07-18 16:44:51 +010017
Lawrence Tangefe17e22022-08-08 09:16:23 +010018//Generates a single pseudo-random ARM processor section, saving the resulting address to the given
Lawrence Tang67cbed62022-07-18 16:44:51 +010019//location. Returns the size of the newly created section.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080020size_t generate_section_arm(void **location,
21 GEN_VALID_BITS_TEST_TYPE validBitsType)
Lawrence Tang67cbed62022-07-18 16:44:51 +010022{
John Chungf8fc7052024-05-03 20:05:29 +080023 //Set up for generation of error/context structures.
Ed Tanous2d4d3b62025-03-11 10:34:29 -070024 UINT16 error_structure_num = cper_rand() % 4 + 1; //Must be at least 1.
25 UINT16 context_structure_num = cper_rand() % 3 + 1;
John Chungf8fc7052024-05-03 20:05:29 +080026 void *error_structures[error_structure_num];
27 void *context_structures[context_structure_num];
28 size_t context_structure_lengths[context_structure_num];
Lawrence Tang67cbed62022-07-18 16:44:51 +010029
John Chungf8fc7052024-05-03 20:05:29 +080030 //Generate the structures.
31 for (int i = 0; i < error_structure_num; i++) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080032 error_structures[i] = generate_arm_error_info(validBitsType);
John Chungf8fc7052024-05-03 20:05:29 +080033 }
34 for (int i = 0; i < context_structure_num; i++) {
35 context_structure_lengths[i] =
36 generate_arm_context_info(context_structures + i);
37 }
Lawrence Tang67cbed62022-07-18 16:44:51 +010038
John Chungf8fc7052024-05-03 20:05:29 +080039 //Determine a random amount of vendor specific info.
Ed Tanous2d4d3b62025-03-11 10:34:29 -070040 size_t vendor_info_len = cper_rand() % 16 + 4;
Lawrence Tang67cbed62022-07-18 16:44:51 +010041
John Chungf8fc7052024-05-03 20:05:29 +080042 //Create the section as a whole.
43 size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE);
44 for (int i = 0; i < context_structure_num; i++) {
45 total_len += context_structure_lengths[i];
46 }
47 total_len += vendor_info_len;
48 UINT8 *section = generate_random_bytes(total_len);
Lawrence Tang67cbed62022-07-18 16:44:51 +010049
John Chungf8fc7052024-05-03 20:05:29 +080050 //Set header information.
51 UINT16 *info_nums = (UINT16 *)(section + 4);
52 *info_nums = error_structure_num;
53 *(info_nums + 1) = context_structure_num;
54 UINT32 *section_length = (UINT32 *)(section + 8);
55 *section_length = total_len;
Lawrence Tang67cbed62022-07-18 16:44:51 +010056
John Chungf8fc7052024-05-03 20:05:29 +080057 //Error affinity.
Ed Tanous2d4d3b62025-03-11 10:34:29 -070058 *(section + 12) = cper_rand() % 4;
Lawrence Tang67cbed62022-07-18 16:44:51 +010059
John Chungf8fc7052024-05-03 20:05:29 +080060 //Reserved zero bytes.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080061 UINT32 *validation = (UINT32 *)section;
62 *validation &= 0xF;
63 if (validBitsType == ALL_VALID) {
64 *validation = 0xF;
65 } else if (validBitsType == SOME_VALID) {
66 *validation = 0xA;
67 }
John Chungf8fc7052024-05-03 20:05:29 +080068 UINT32 *running_state = (UINT32 *)(section + 32);
69 *running_state &= 0x1;
70 memset(section + 13, 0, 3);
Lawrence Tang67cbed62022-07-18 16:44:51 +010071
John Chungf8fc7052024-05-03 20:05:29 +080072 //Copy in the sections/context structures, free resources.
73 UINT8 *cur_pos = section + 40;
74 for (int i = 0; i < error_structure_num; i++) {
75 memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE);
76 free(error_structures[i]);
77 cur_pos += ARM_ERROR_INFO_SIZE;
78 }
79 for (int i = 0; i < context_structure_num; i++) {
80 memcpy(cur_pos, context_structures[i],
81 context_structure_lengths[i]);
82 free(context_structures[i]);
83 cur_pos += context_structure_lengths[i];
84 }
85
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080086 //vendor specific
87 for (size_t i = 0; i < vendor_info_len; i++) {
88 //Ensure only ascii is used so we don't
89 // fail base64E
Ed Tanous2d4d3b62025-03-11 10:34:29 -070090 *cur_pos = cper_rand() % 127 + 1;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080091 cur_pos += 1;
92 }
93
John Chungf8fc7052024-05-03 20:05:29 +080094 //Set return values and exit.
95 *location = section;
96 return total_len;
Lawrence Tang67cbed62022-07-18 16:44:51 +010097}
98
99//Generates a single pseudo-random ARM error info structure. Must be later freed.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800100void *generate_arm_error_info(GEN_VALID_BITS_TEST_TYPE validBitsType)
Lawrence Tang67cbed62022-07-18 16:44:51 +0100101{
John Chungf8fc7052024-05-03 20:05:29 +0800102 UINT8 *error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE);
Lawrence Tang67cbed62022-07-18 16:44:51 +0100103
John Chungf8fc7052024-05-03 20:05:29 +0800104 //Version (zero for revision of table referenced), length.
105 *error_info = 0;
106 *(error_info + 1) = ARM_ERROR_INFO_SIZE;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100107
John Chungf8fc7052024-05-03 20:05:29 +0800108 //Type of error.
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700109 UINT8 error_type = cper_rand() % 3;
John Chungf8fc7052024-05-03 20:05:29 +0800110 *(error_info + 4) = error_type;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100111
John Chungf8fc7052024-05-03 20:05:29 +0800112 //Reserved bits for error information.
113 UINT16 *validation = (UINT16 *)(error_info + 2);
114 *validation &= 0x1F;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800115 if (validBitsType == ALL_VALID) {
116 *validation = 0x1F;
117 } else if (validBitsType == SOME_VALID) {
118 *validation = 0x15;
119 }
Lawrence Tang01e3a442022-07-20 15:14:50 +0100120
John Chungf8fc7052024-05-03 20:05:29 +0800121 //Make sure reserved bits are zero according with the type.
122 UINT64 *error_subinfo = (UINT64 *)(error_info + 8);
123 switch (error_type) {
124 //Cache/TLB
125 case 0:
126 case 1:
127 *error_subinfo &= 0xFFFFFFF;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800128 //Reserved bits for cache/tlb.
129 UINT16 *val_cache = (UINT16 *)(error_info + 8);
130 if (validBitsType == ALL_VALID) {
131 *val_cache = 0x7F;
132 } else if (validBitsType == SOME_VALID) {
133 *val_cache = 0x55;
134 }
John Chungf8fc7052024-05-03 20:05:29 +0800135 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100136
John Chungf8fc7052024-05-03 20:05:29 +0800137 //Bus
138 case 2:
139 *error_subinfo &= 0xFFFFFFFFFFF;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800140 UINT16 *val_bus = (UINT16 *)(error_info + 8);
141 if (validBitsType == ALL_VALID) {
142 *val_bus = 0xFFF;
143 } else if (validBitsType == SOME_VALID) {
144 *val_bus = 0x555;
145 }
146
John Chungf8fc7052024-05-03 20:05:29 +0800147 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100148
John Chungf8fc7052024-05-03 20:05:29 +0800149 //Microarch/other.
150 default:
151 break;
152 }
Lawrence Tang67cbed62022-07-18 16:44:51 +0100153
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800154 //flags
155 UINT8 *flags = (UINT8 *)(error_info + 7);
156 *flags &= 0xF;
157
John Chungf8fc7052024-05-03 20:05:29 +0800158 return error_info;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100159}
160
161//Generates a single pseudo-random ARM context info structure. Must be later freed.
John Chungf8fc7052024-05-03 20:05:29 +0800162size_t generate_arm_context_info(void **location)
Lawrence Tang67cbed62022-07-18 16:44:51 +0100163{
John Chungf8fc7052024-05-03 20:05:29 +0800164 //Initial length is 8 bytes. Add extra based on type.
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700165 UINT16 reg_type = cper_rand() % 9;
John Chungf8fc7052024-05-03 20:05:29 +0800166 UINT32 reg_size = 0;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100167
John Chungf8fc7052024-05-03 20:05:29 +0800168 //Set register size.
169 switch (reg_type) {
170 //AARCH32 GPR, AARCH32 EL2
171 case 0:
172 case 2:
173 reg_size = 64;
174 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100175
John Chungf8fc7052024-05-03 20:05:29 +0800176 //AARCH32 EL1
177 case 1:
178 reg_size = 96;
179 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100180
John Chungf8fc7052024-05-03 20:05:29 +0800181 //AARCH32 EL3
182 case 3:
183 reg_size = 8;
184 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100185
John Chungf8fc7052024-05-03 20:05:29 +0800186 //AARCH64 GPR
187 case 4:
188 reg_size = 256;
189 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100190
John Chungf8fc7052024-05-03 20:05:29 +0800191 //AARCH64 EL1
192 case 5:
193 reg_size = 136;
194 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100195
John Chungf8fc7052024-05-03 20:05:29 +0800196 //AARCH64 EL2
197 case 6:
198 reg_size = 120;
199 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100200
John Chungf8fc7052024-05-03 20:05:29 +0800201 //AARCH64 EL3
202 case 7:
203 reg_size = 80;
204 break;
Lawrence Tang67cbed62022-07-18 16:44:51 +0100205
John Chungf8fc7052024-05-03 20:05:29 +0800206 //Misc. single register.
207 case 8:
208 reg_size = 10;
209 break;
210 }
Lawrence Tang67cbed62022-07-18 16:44:51 +0100211
John Chungf8fc7052024-05-03 20:05:29 +0800212 //Create context structure randomly.
213 int total_size = 8 + reg_size;
214 UINT16 *context_info = (UINT16 *)generate_random_bytes(total_size);
Lawrence Tang67cbed62022-07-18 16:44:51 +0100215
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800216 //UEFI spec is not clear about bit 15 in the
217 // reg type 8 section. This sets it to 0 to
218 // avoid confusion for now.
219 if (reg_type == 8) {
220 UINT8 *reg_decode = (UINT8 *)context_info;
221 *(reg_decode + 9) &= 0x7F;
222 }
223
John Chungf8fc7052024-05-03 20:05:29 +0800224 //Set header information.
225 *(context_info + 1) = reg_type;
226 *((UINT32 *)(context_info + 2)) = reg_size;
227
228 //Set return values and exit.
229 *location = context_info;
230 return total_size;
231}