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