xref: /openbmc/libcper/generator/sections/gen-section-ia32x64.c (revision ae8f6d9aaeaf37332e8924dd2c0b6f320335548c)
1 /**
2  * Functions for generating pseudo-random CPER IA32/x64 sections.
3  *
4  * Author: Lawrence.Tang@arm.com
5  **/
6 
7 #include <stdlib.h>
8 #include <string.h>
9 #include <libcper/Cper.h>
10 #include <libcper/generator/gen-utils.h>
11 #include <libcper/generator/sections/gen-section.h>
12 #define IA32X64_ERROR_STRUCTURE_SIZE 64
13 
14 void *generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType);
15 size_t generate_ia32x64_context_structure(void **location);
16 
17 //Generates a single pseudo-random IA32/x64 section, saving the resulting address to the given
18 //location. Returns the size of the newly created section.
generate_section_ia32x64(void ** location,GEN_VALID_BITS_TEST_TYPE validBitsType)19 size_t generate_section_ia32x64(void **location,
20 				GEN_VALID_BITS_TEST_TYPE validBitsType)
21 {
22 	//Set up for generation of error/context structures.
23 	UINT16 error_structure_num = rand() % 4 + 1;
24 	UINT16 context_structure_num = rand() % 4 + 1;
25 	void *error_structures[error_structure_num];
26 	void *context_structures[context_structure_num];
27 	size_t context_structure_lengths[context_structure_num];
28 
29 	//Generate the structures.
30 	for (int i = 0; i < error_structure_num; i++) {
31 		error_structures[i] =
32 			generate_ia32x64_error_structure(validBitsType);
33 	}
34 	for (int i = 0; i < context_structure_num; i++) {
35 		context_structure_lengths[i] =
36 			generate_ia32x64_context_structure(context_structures +
37 							   i);
38 	}
39 
40 	//Create a valid IA32/x64 section.
41 	size_t total_len =
42 		64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num);
43 	for (int i = 0; i < context_structure_num; i++) {
44 		total_len += context_structure_lengths[i];
45 	}
46 	UINT8 *section = generate_random_bytes(total_len);
47 
48 	//Null extend the end of the CPUID in the header.
49 	for (int i = 0; i < 16; i++) {
50 		*(section + 48 + i) = 0x0;
51 	}
52 
53 	//Set header information.
54 	UINT64 *validation = (UINT64 *)section;
55 	*validation &= 0x3;
56 	if (validBitsType == ALL_VALID) {
57 		*validation = 0x3;
58 	} else if (validBitsType == SOME_VALID) {
59 		*validation = 0x2;
60 	}
61 	*validation |= error_structure_num << 2;
62 	*validation |= context_structure_num << 8;
63 
64 	//Copy in structures, free resources.
65 	UINT8 *cur_pos = section + 64;
66 	for (int i = 0; i < error_structure_num; i++) {
67 		memcpy(cur_pos, error_structures[i],
68 		       IA32X64_ERROR_STRUCTURE_SIZE);
69 		free(error_structures[i]);
70 		cur_pos += IA32X64_ERROR_STRUCTURE_SIZE;
71 	}
72 	for (int i = 0; i < context_structure_num; i++) {
73 		memcpy(cur_pos, context_structures[i],
74 		       context_structure_lengths[i]);
75 		free(context_structures[i]);
76 		cur_pos += context_structure_lengths[i];
77 	}
78 
79 	//Set return values, exist.
80 	*location = section;
81 	return total_len;
82 }
83 
84 //Generates a single IA32/x64 error structure. Must later be freed.
generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType)85 void *generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType)
86 {
87 	UINT8 *error_structure =
88 		generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
89 
90 	//Set error structure reserved space to zero.
91 	UINT64 *validation = (UINT64 *)(error_structure + 16);
92 	*validation &= 0x1F;
93 	if (validBitsType == ALL_VALID) {
94 		*validation = 0x1F;
95 	} else if (validBitsType == SOME_VALID) {
96 		*validation = 0x15;
97 	}
98 
99 	//Create a random type of error structure.
100 	EFI_GUID *guid = (EFI_GUID *)error_structure;
101 	UINT64 *check_info = (UINT64 *)(error_structure + 24);
102 	int error_structure_type = rand() % 4;
103 	switch (error_structure_type) {
104 	//Cache
105 	case 0:
106 		memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid,
107 		       sizeof(EFI_GUID));
108 
109 		//Set reserved space to zero.
110 		*check_info = ~0x20FF00;
111 		*check_info &= 0x3FFFFFFF;
112 		break;
113 
114 	//TLB
115 	case 1:
116 		memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid,
117 		       sizeof(EFI_GUID));
118 
119 		//Set reserved space to zero.
120 		*check_info = ~0x20FF00;
121 		*check_info &= 0x3FFFFFFF;
122 		break;
123 
124 	//Bus
125 	case 2:
126 		memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid,
127 		       sizeof(EFI_GUID));
128 
129 		//Set reserved space to zero.
130 		*check_info = ~0x20F800;
131 		*check_info &= 0x7FFFFFFFF;
132 		break;
133 
134 	//MS
135 	case 3:
136 		memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid,
137 		       sizeof(EFI_GUID));
138 
139 		//Set reserved space to zero.
140 		*check_info = ~0xFFC0;
141 		*check_info &= 0xFFFFFF;
142 		break;
143 	}
144 
145 	return error_structure;
146 }
147 
148 //Generates a single IA32/x64 context structure. Must later be freed.
generate_ia32x64_context_structure(void ** location)149 size_t generate_ia32x64_context_structure(void **location)
150 {
151 	//Initial length is 16 bytes. Add extra based on type.
152 	int reg_type = rand() % 8;
153 	int reg_size = 0;
154 
155 	//Set register size.
156 	if (reg_type == 2) {
157 		reg_size = 92;			  //IA32 registers.
158 	} else if (reg_type == 3) {
159 		reg_size = 244;			  //x64 registers.
160 	} else {
161 		reg_size = (rand() % 5 + 1) * 32; //Not table defined.
162 	}
163 
164 	//Create structure randomly.
165 	int total_size = 16 + reg_size;
166 	UINT16 *context_structure = (UINT16 *)generate_random_bytes(total_size);
167 
168 	//If it is x64 registers, set reserved area accordingly.
169 	if (reg_type == 3) {
170 		UINT8 *reg_bytes = (UINT8 *)(context_structure + 8);
171 		UINT32 *reserved = (UINT32 *)(reg_bytes + 140);
172 		*reserved = 0;
173 	}
174 
175 	//Set header information.
176 	*(context_structure) = reg_type;
177 	*(context_structure + 1) = reg_size;
178 
179 	//Set return values and exit.
180 	*location = context_structure;
181 	return total_size;
182 }
183