1*02c801a5SLawrence Tang /**
2*02c801a5SLawrence Tang  * Functions for generating psuedo-random CPER IA32/x64 sections.
3*02c801a5SLawrence Tang  *
4*02c801a5SLawrence Tang  * Author: Lawrence.Tang@arm.com
5*02c801a5SLawrence Tang  **/
6*02c801a5SLawrence Tang 
7*02c801a5SLawrence Tang #include <stdlib.h>
8*02c801a5SLawrence Tang #include <string.h>
9*02c801a5SLawrence Tang #include "../../edk/Cper.h"
10*02c801a5SLawrence Tang #include "../gen-utils.h"
11*02c801a5SLawrence Tang #include "gen-section-ia32x64.h"
12*02c801a5SLawrence Tang 
13*02c801a5SLawrence Tang void* generate_ia32x64_error_structure();
14*02c801a5SLawrence Tang size_t generate_ia32x64_context_structure(void** location);
15*02c801a5SLawrence Tang 
16*02c801a5SLawrence Tang //Generates a single psuedo-random IA32/x64 section, saving the resulting address to the given
17*02c801a5SLawrence Tang //location. Returns the size of the newly created section.
18*02c801a5SLawrence Tang size_t generate_section_ia32x64(void** location)
19*02c801a5SLawrence Tang {
20*02c801a5SLawrence Tang     //Set up for generation of error/context structures.
21*02c801a5SLawrence Tang     UINT16 error_structure_num = rand() % 5;
22*02c801a5SLawrence Tang     UINT16 context_structure_num = rand() % 5;
23*02c801a5SLawrence Tang     void* error_structures[error_structure_num];
24*02c801a5SLawrence Tang     void* context_structures[context_structure_num];
25*02c801a5SLawrence Tang     size_t context_structure_lengths[context_structure_num];
26*02c801a5SLawrence Tang 
27*02c801a5SLawrence Tang     //Generate the structures.
28*02c801a5SLawrence Tang     for (int i=0; i<error_structure_num; i++)
29*02c801a5SLawrence Tang         error_structures[i] = generate_ia32x64_error_structure();
30*02c801a5SLawrence Tang     for (int i=0; i<context_structure_num; i++)
31*02c801a5SLawrence Tang         context_structure_lengths[i] = generate_ia32x64_context_structure(context_structures + i);
32*02c801a5SLawrence Tang 
33*02c801a5SLawrence Tang     //Create a valid IA32/x64 section.
34*02c801a5SLawrence Tang     size_t total_len = 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num);
35*02c801a5SLawrence Tang     for (int i=0; i<context_structure_num; i++)
36*02c801a5SLawrence Tang         total_len += context_structure_lengths[i];
37*02c801a5SLawrence Tang     UINT8* section = generate_random_bytes(total_len);
38*02c801a5SLawrence Tang 
39*02c801a5SLawrence Tang     //Set header information.
40*02c801a5SLawrence Tang     UINT64* validation = (UINT64*)section;
41*02c801a5SLawrence Tang     *validation &= 0b11;
42*02c801a5SLawrence Tang     *validation |= error_structure_num << 2;
43*02c801a5SLawrence Tang     *validation |= context_structure_num << 8;
44*02c801a5SLawrence Tang 
45*02c801a5SLawrence Tang     //Copy in structures, free resources.
46*02c801a5SLawrence Tang     UINT8* cur_pos = section + 64;
47*02c801a5SLawrence Tang     for (int i=0; i<error_structure_num; i++)
48*02c801a5SLawrence Tang     {
49*02c801a5SLawrence Tang         memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE);
50*02c801a5SLawrence Tang         free(error_structures[i]);
51*02c801a5SLawrence Tang         cur_pos += IA32X64_ERROR_STRUCTURE_SIZE;
52*02c801a5SLawrence Tang     }
53*02c801a5SLawrence Tang     for (int i=0; i<context_structure_num; i++)
54*02c801a5SLawrence Tang     {
55*02c801a5SLawrence Tang         memcpy(cur_pos, context_structures[i], context_structure_lengths[i]);
56*02c801a5SLawrence Tang         free(context_structures[i]);
57*02c801a5SLawrence Tang         cur_pos += context_structure_lengths[i];
58*02c801a5SLawrence Tang     }
59*02c801a5SLawrence Tang 
60*02c801a5SLawrence Tang     //Set return values, exist.
61*02c801a5SLawrence Tang     *location = section;
62*02c801a5SLawrence Tang     return total_len;
63*02c801a5SLawrence Tang }
64*02c801a5SLawrence Tang 
65*02c801a5SLawrence Tang //Generates a single IA32/x64 error structure. Must later be freed.
66*02c801a5SLawrence Tang void* generate_ia32x64_error_structure()
67*02c801a5SLawrence Tang {
68*02c801a5SLawrence Tang     UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
69*02c801a5SLawrence Tang 
70*02c801a5SLawrence Tang     //Create a random type of error structure.
71*02c801a5SLawrence Tang     EFI_GUID* guid = (EFI_GUID*)error_structure;
72*02c801a5SLawrence Tang     int error_structure_type = rand() % 4;
73*02c801a5SLawrence Tang     switch (error_structure_type)
74*02c801a5SLawrence Tang     {
75*02c801a5SLawrence Tang         //Cache
76*02c801a5SLawrence Tang         case 0:
77*02c801a5SLawrence Tang             memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(guid));
78*02c801a5SLawrence Tang             memset(error_structure + 30, 0, 34);
79*02c801a5SLawrence Tang             break;
80*02c801a5SLawrence Tang 
81*02c801a5SLawrence Tang         //TLB
82*02c801a5SLawrence Tang         case 1:
83*02c801a5SLawrence Tang             memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(guid));
84*02c801a5SLawrence Tang             memset(error_structure + 30, 0, 34);
85*02c801a5SLawrence Tang             break;
86*02c801a5SLawrence Tang 
87*02c801a5SLawrence Tang         //Bus
88*02c801a5SLawrence Tang         case 2:
89*02c801a5SLawrence Tang             memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(guid));
90*02c801a5SLawrence Tang             memset(error_structure + 35, 0, 29);
91*02c801a5SLawrence Tang             break;
92*02c801a5SLawrence Tang 
93*02c801a5SLawrence Tang         //MS
94*02c801a5SLawrence Tang         case 3:
95*02c801a5SLawrence Tang             memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(guid));
96*02c801a5SLawrence Tang             memset(error_structure + 24, 0, 38);
97*02c801a5SLawrence Tang             break;
98*02c801a5SLawrence Tang     }
99*02c801a5SLawrence Tang 
100*02c801a5SLawrence Tang     return error_structure;
101*02c801a5SLawrence Tang }
102*02c801a5SLawrence Tang 
103*02c801a5SLawrence Tang //Generates a single IA32/x64 context structure. Must later be freed.
104*02c801a5SLawrence Tang size_t generate_ia32x64_context_structure(void** location)
105*02c801a5SLawrence Tang {
106*02c801a5SLawrence Tang     //Initial length is 16 bytes. Add extra based on type.
107*02c801a5SLawrence Tang     int reg_type = rand() % 8;
108*02c801a5SLawrence Tang     int reg_size = 0;
109*02c801a5SLawrence Tang 
110*02c801a5SLawrence Tang     //Set register size.
111*02c801a5SLawrence Tang     if (reg_type == 2)
112*02c801a5SLawrence Tang         reg_size = 92; //IA32 registers.
113*02c801a5SLawrence Tang     if (reg_type == 3)
114*02c801a5SLawrence Tang         reg_size = 244; //x64 registers.
115*02c801a5SLawrence Tang     else
116*02c801a5SLawrence Tang         reg_size = rand() % 64; //Not table defined.
117*02c801a5SLawrence Tang 
118*02c801a5SLawrence Tang     //Create structure randomly.
119*02c801a5SLawrence Tang     int total_size = 16 + reg_size;
120*02c801a5SLawrence Tang     UINT16* context_structure = (UINT16*)generate_random_bytes(total_size);
121*02c801a5SLawrence Tang 
122*02c801a5SLawrence Tang     //Set header information.
123*02c801a5SLawrence Tang     *(context_structure) = reg_type;
124*02c801a5SLawrence Tang     *(context_structure + 1) = reg_size;
125*02c801a5SLawrence Tang 
126*02c801a5SLawrence Tang     //Set return values and exit.
127*02c801a5SLawrence Tang     *location = context_structure;
128*02c801a5SLawrence Tang     return total_size;
129*02c801a5SLawrence Tang }