167cbed6bSLawrence Tang /**
2efe17e2cSLawrence Tang * Functions for generating pseudo-random CPER ARM processor sections.
367cbed6bSLawrence Tang *
467cbed6bSLawrence Tang * Author: Lawrence.Tang@arm.com
567cbed6bSLawrence Tang **/
667cbed6bSLawrence Tang
767cbed6bSLawrence Tang #include <stdlib.h>
8ae8f6d9aSAushim Nagarkatti #include <stdio.h>
967cbed6bSLawrence Tang #include <string.h>
10e42fb487SThu Nguyen #include <libcper/BaseTypes.h>
11e42fb487SThu Nguyen #include <libcper/generator/gen-utils.h>
12e42fb487SThu Nguyen #include <libcper/generator/sections/gen-section.h>
1367cbed6bSLawrence Tang #define ARM_ERROR_INFO_SIZE 32
1467cbed6bSLawrence Tang
15ae8f6d9aSAushim Nagarkatti void *generate_arm_error_info(GEN_VALID_BITS_TEST_TYPE validBitsType);
1667cbed6bSLawrence Tang size_t generate_arm_context_info(void **location);
1767cbed6bSLawrence Tang
18efe17e2cSLawrence Tang //Generates a single pseudo-random ARM processor section, saving the resulting address to the given
1967cbed6bSLawrence Tang //location. Returns the size of the newly created section.
generate_section_arm(void ** location,GEN_VALID_BITS_TEST_TYPE validBitsType)20ae8f6d9aSAushim Nagarkatti size_t generate_section_arm(void **location,
21ae8f6d9aSAushim Nagarkatti GEN_VALID_BITS_TEST_TYPE validBitsType)
2267cbed6bSLawrence Tang {
2367cbed6bSLawrence Tang //Set up for generation of error/context structures.
24*2d4d3b65SEd Tanous UINT16 error_structure_num = cper_rand() % 4 + 1; //Must be at least 1.
25*2d4d3b65SEd Tanous UINT16 context_structure_num = cper_rand() % 3 + 1;
2667cbed6bSLawrence Tang void *error_structures[error_structure_num];
2767cbed6bSLawrence Tang void *context_structures[context_structure_num];
2867cbed6bSLawrence Tang size_t context_structure_lengths[context_structure_num];
2967cbed6bSLawrence Tang
3067cbed6bSLawrence Tang //Generate the structures.
31f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) {
32ae8f6d9aSAushim Nagarkatti error_structures[i] = generate_arm_error_info(validBitsType);
33f8fc7052SJohn Chung }
34f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) {
35f8fc7052SJohn Chung context_structure_lengths[i] =
36f8fc7052SJohn Chung generate_arm_context_info(context_structures + i);
37f8fc7052SJohn Chung }
3867cbed6bSLawrence Tang
3967cbed6bSLawrence Tang //Determine a random amount of vendor specific info.
40*2d4d3b65SEd Tanous size_t vendor_info_len = cper_rand() % 16 + 4;
4167cbed6bSLawrence Tang
4267cbed6bSLawrence Tang //Create the section as a whole.
4367cbed6bSLawrence Tang size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE);
44f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) {
4567cbed6bSLawrence Tang total_len += context_structure_lengths[i];
46f8fc7052SJohn Chung }
4767cbed6bSLawrence Tang total_len += vendor_info_len;
4867cbed6bSLawrence Tang UINT8 *section = generate_random_bytes(total_len);
4967cbed6bSLawrence Tang
5067cbed6bSLawrence Tang //Set header information.
5167cbed6bSLawrence Tang UINT16 *info_nums = (UINT16 *)(section + 4);
5267cbed6bSLawrence Tang *info_nums = error_structure_num;
5367cbed6bSLawrence Tang *(info_nums + 1) = context_structure_num;
5467cbed6bSLawrence Tang UINT32 *section_length = (UINT32 *)(section + 8);
5567cbed6bSLawrence Tang *section_length = total_len;
5667cbed6bSLawrence Tang
5767cbed6bSLawrence Tang //Error affinity.
58*2d4d3b65SEd Tanous *(section + 12) = cper_rand() % 4;
5967cbed6bSLawrence Tang
6067cbed6bSLawrence Tang //Reserved zero bytes.
61ae8f6d9aSAushim Nagarkatti UINT32 *validation = (UINT32 *)section;
62ae8f6d9aSAushim Nagarkatti *validation &= 0xF;
63ae8f6d9aSAushim Nagarkatti if (validBitsType == ALL_VALID) {
64ae8f6d9aSAushim Nagarkatti *validation = 0xF;
65ae8f6d9aSAushim Nagarkatti } else if (validBitsType == SOME_VALID) {
66ae8f6d9aSAushim Nagarkatti *validation = 0xA;
67ae8f6d9aSAushim Nagarkatti }
6801e3a44dSLawrence Tang UINT32 *running_state = (UINT32 *)(section + 32);
69f8fc7052SJohn Chung *running_state &= 0x1;
7067cbed6bSLawrence Tang memset(section + 13, 0, 3);
7167cbed6bSLawrence Tang
7267cbed6bSLawrence Tang //Copy in the sections/context structures, free resources.
7367cbed6bSLawrence Tang UINT8 *cur_pos = section + 40;
74f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) {
7567cbed6bSLawrence Tang memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE);
7667cbed6bSLawrence Tang free(error_structures[i]);
7767cbed6bSLawrence Tang cur_pos += ARM_ERROR_INFO_SIZE;
7867cbed6bSLawrence Tang }
79f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) {
80f8fc7052SJohn Chung memcpy(cur_pos, context_structures[i],
81f8fc7052SJohn Chung context_structure_lengths[i]);
8267cbed6bSLawrence Tang free(context_structures[i]);
8367cbed6bSLawrence Tang cur_pos += context_structure_lengths[i];
8467cbed6bSLawrence Tang }
8567cbed6bSLawrence Tang
86ae8f6d9aSAushim Nagarkatti //vendor specific
87ae8f6d9aSAushim Nagarkatti for (size_t i = 0; i < vendor_info_len; i++) {
88ae8f6d9aSAushim Nagarkatti //Ensure only ascii is used so we don't
89ae8f6d9aSAushim Nagarkatti // fail base64E
90*2d4d3b65SEd Tanous *cur_pos = cper_rand() % 127 + 1;
91ae8f6d9aSAushim Nagarkatti cur_pos += 1;
92ae8f6d9aSAushim Nagarkatti }
93ae8f6d9aSAushim Nagarkatti
9467cbed6bSLawrence Tang //Set return values and exit.
9567cbed6bSLawrence Tang *location = section;
9667cbed6bSLawrence Tang return total_len;
9767cbed6bSLawrence Tang }
9867cbed6bSLawrence Tang
9967cbed6bSLawrence Tang //Generates a single pseudo-random ARM error info structure. Must be later freed.
generate_arm_error_info(GEN_VALID_BITS_TEST_TYPE validBitsType)100ae8f6d9aSAushim Nagarkatti void *generate_arm_error_info(GEN_VALID_BITS_TEST_TYPE validBitsType)
10167cbed6bSLawrence Tang {
10267cbed6bSLawrence Tang UINT8 *error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE);
10367cbed6bSLawrence Tang
10467cbed6bSLawrence Tang //Version (zero for revision of table referenced), length.
10567cbed6bSLawrence Tang *error_info = 0;
10667cbed6bSLawrence Tang *(error_info + 1) = ARM_ERROR_INFO_SIZE;
10767cbed6bSLawrence Tang
10867cbed6bSLawrence Tang //Type of error.
109*2d4d3b65SEd Tanous UINT8 error_type = cper_rand() % 3;
11067cbed6bSLawrence Tang *(error_info + 4) = error_type;
11167cbed6bSLawrence Tang
11201e3a44dSLawrence Tang //Reserved bits for error information.
11301e3a44dSLawrence Tang UINT16 *validation = (UINT16 *)(error_info + 2);
11401e3a44dSLawrence Tang *validation &= 0x1F;
115ae8f6d9aSAushim Nagarkatti if (validBitsType == ALL_VALID) {
116ae8f6d9aSAushim Nagarkatti *validation = 0x1F;
117ae8f6d9aSAushim Nagarkatti } else if (validBitsType == SOME_VALID) {
118ae8f6d9aSAushim Nagarkatti *validation = 0x15;
119ae8f6d9aSAushim Nagarkatti }
12001e3a44dSLawrence Tang
12167cbed6bSLawrence Tang //Make sure reserved bits are zero according with the type.
12267cbed6bSLawrence Tang UINT64 *error_subinfo = (UINT64 *)(error_info + 8);
123f8fc7052SJohn Chung switch (error_type) {
12467cbed6bSLawrence Tang //Cache/TLB
12567cbed6bSLawrence Tang case 0:
12667cbed6bSLawrence Tang case 1:
12767cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFF;
128ae8f6d9aSAushim Nagarkatti //Reserved bits for cache/tlb.
129ae8f6d9aSAushim Nagarkatti UINT16 *val_cache = (UINT16 *)(error_info + 8);
130ae8f6d9aSAushim Nagarkatti if (validBitsType == ALL_VALID) {
131ae8f6d9aSAushim Nagarkatti *val_cache = 0x7F;
132ae8f6d9aSAushim Nagarkatti } else if (validBitsType == SOME_VALID) {
133ae8f6d9aSAushim Nagarkatti *val_cache = 0x55;
134ae8f6d9aSAushim Nagarkatti }
13567cbed6bSLawrence Tang break;
13667cbed6bSLawrence Tang
13767cbed6bSLawrence Tang //Bus
13867cbed6bSLawrence Tang case 2:
13967cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFFFFFF;
140ae8f6d9aSAushim Nagarkatti UINT16 *val_bus = (UINT16 *)(error_info + 8);
141ae8f6d9aSAushim Nagarkatti if (validBitsType == ALL_VALID) {
142ae8f6d9aSAushim Nagarkatti *val_bus = 0xFFF;
143ae8f6d9aSAushim Nagarkatti } else if (validBitsType == SOME_VALID) {
144ae8f6d9aSAushim Nagarkatti *val_bus = 0x555;
145ae8f6d9aSAushim Nagarkatti }
146ae8f6d9aSAushim Nagarkatti
14767cbed6bSLawrence Tang break;
14867cbed6bSLawrence Tang
14967cbed6bSLawrence Tang //Microarch/other.
15067cbed6bSLawrence Tang default:
15167cbed6bSLawrence Tang break;
15267cbed6bSLawrence Tang }
15367cbed6bSLawrence Tang
154ae8f6d9aSAushim Nagarkatti //flags
155ae8f6d9aSAushim Nagarkatti UINT8 *flags = (UINT8 *)(error_info + 7);
156ae8f6d9aSAushim Nagarkatti *flags &= 0xF;
157ae8f6d9aSAushim Nagarkatti
15867cbed6bSLawrence Tang return error_info;
15967cbed6bSLawrence Tang }
16067cbed6bSLawrence Tang
16167cbed6bSLawrence Tang //Generates a single pseudo-random ARM context info structure. Must be later freed.
generate_arm_context_info(void ** location)16267cbed6bSLawrence Tang size_t generate_arm_context_info(void **location)
16367cbed6bSLawrence Tang {
16467cbed6bSLawrence Tang //Initial length is 8 bytes. Add extra based on type.
165*2d4d3b65SEd Tanous UINT16 reg_type = cper_rand() % 9;
16667cbed6bSLawrence Tang UINT32 reg_size = 0;
16767cbed6bSLawrence Tang
16867cbed6bSLawrence Tang //Set register size.
169f8fc7052SJohn Chung switch (reg_type) {
17067cbed6bSLawrence Tang //AARCH32 GPR, AARCH32 EL2
17167cbed6bSLawrence Tang case 0:
17267cbed6bSLawrence Tang case 2:
17367cbed6bSLawrence Tang reg_size = 64;
17467cbed6bSLawrence Tang break;
17567cbed6bSLawrence Tang
17667cbed6bSLawrence Tang //AARCH32 EL1
17767cbed6bSLawrence Tang case 1:
17867cbed6bSLawrence Tang reg_size = 96;
17967cbed6bSLawrence Tang break;
18067cbed6bSLawrence Tang
18167cbed6bSLawrence Tang //AARCH32 EL3
18267cbed6bSLawrence Tang case 3:
18367cbed6bSLawrence Tang reg_size = 8;
18467cbed6bSLawrence Tang break;
18567cbed6bSLawrence Tang
18667cbed6bSLawrence Tang //AARCH64 GPR
18767cbed6bSLawrence Tang case 4:
18867cbed6bSLawrence Tang reg_size = 256;
18967cbed6bSLawrence Tang break;
19067cbed6bSLawrence Tang
19167cbed6bSLawrence Tang //AARCH64 EL1
19267cbed6bSLawrence Tang case 5:
19367cbed6bSLawrence Tang reg_size = 136;
19467cbed6bSLawrence Tang break;
19567cbed6bSLawrence Tang
19667cbed6bSLawrence Tang //AARCH64 EL2
19767cbed6bSLawrence Tang case 6:
19867cbed6bSLawrence Tang reg_size = 120;
19967cbed6bSLawrence Tang break;
20067cbed6bSLawrence Tang
20167cbed6bSLawrence Tang //AARCH64 EL3
20267cbed6bSLawrence Tang case 7:
20367cbed6bSLawrence Tang reg_size = 80;
20467cbed6bSLawrence Tang break;
20567cbed6bSLawrence Tang
20667cbed6bSLawrence Tang //Misc. single register.
20767cbed6bSLawrence Tang case 8:
20867cbed6bSLawrence Tang reg_size = 10;
20967cbed6bSLawrence Tang break;
21067cbed6bSLawrence Tang }
21167cbed6bSLawrence Tang
21267cbed6bSLawrence Tang //Create context structure randomly.
21367cbed6bSLawrence Tang int total_size = 8 + reg_size;
21467cbed6bSLawrence Tang UINT16 *context_info = (UINT16 *)generate_random_bytes(total_size);
21567cbed6bSLawrence Tang
216ae8f6d9aSAushim Nagarkatti //UEFI spec is not clear about bit 15 in the
217ae8f6d9aSAushim Nagarkatti // reg type 8 section. This sets it to 0 to
218ae8f6d9aSAushim Nagarkatti // avoid confusion for now.
219ae8f6d9aSAushim Nagarkatti if (reg_type == 8) {
220ae8f6d9aSAushim Nagarkatti UINT8 *reg_decode = (UINT8 *)context_info;
221ae8f6d9aSAushim Nagarkatti *(reg_decode + 9) &= 0x7F;
222ae8f6d9aSAushim Nagarkatti }
223ae8f6d9aSAushim Nagarkatti
22467cbed6bSLawrence Tang //Set header information.
22567cbed6bSLawrence Tang *(context_info + 1) = reg_type;
22667cbed6bSLawrence Tang *((UINT32 *)(context_info + 2)) = reg_size;
22767cbed6bSLawrence Tang
22867cbed6bSLawrence Tang //Set return values and exit.
22967cbed6bSLawrence Tang *location = context_info;
23067cbed6bSLawrence Tang return total_size;
23167cbed6bSLawrence Tang }
232