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