xref: /openbmc/libcper/generator/sections/gen-section-arm.c (revision 2d4d3b65396596d8939bacaea54ed529530362f9)
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