blob: a01d2b7c0499c365b704688cf3322ce6f9e9ff88 [file] [log] [blame]
Lawrence Tang02c801a2022-07-18 14:43:52 +01001/**
Lawrence Tangefe17e22022-08-08 09:16:23 +01002 * Functions for generating pseudo-random CPER IA32/x64 sections.
Lawrence Tang02c801a2022-07-18 14:43:52 +01003 *
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"
Lawrence Tang8f977452022-08-24 14:55:07 +010011#include "gen-section.h"
Lawrence Tang67cbed62022-07-18 16:44:51 +010012#define IA32X64_ERROR_STRUCTURE_SIZE 64
Lawrence Tang02c801a2022-07-18 14:43:52 +010013
14void* generate_ia32x64_error_structure();
15size_t generate_ia32x64_context_structure(void** location);
16
Lawrence Tangefe17e22022-08-08 09:16:23 +010017//Generates a single pseudo-random IA32/x64 section, saving the resulting address to the given
Lawrence Tang02c801a2022-07-18 14:43:52 +010018//location. Returns the size of the newly created section.
19size_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
Lawrence Tangaacf0e22022-07-20 13:28:52 +010040 //Null extend the end of the CPUID in the header.
41 for (int i=0; i<16; i++)
42 *(section + 48 + i) = 0x0;
43
Lawrence Tang02c801a2022-07-18 14:43:52 +010044 //Set header information.
45 UINT64* validation = (UINT64*)section;
46 *validation &= 0b11;
47 *validation |= error_structure_num << 2;
48 *validation |= context_structure_num << 8;
49
50 //Copy in structures, free resources.
51 UINT8* cur_pos = section + 64;
52 for (int i=0; i<error_structure_num; i++)
53 {
54 memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE);
55 free(error_structures[i]);
56 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE;
57 }
58 for (int i=0; i<context_structure_num; i++)
59 {
60 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]);
61 free(context_structures[i]);
62 cur_pos += context_structure_lengths[i];
63 }
64
65 //Set return values, exist.
66 *location = section;
67 return total_len;
68}
69
70//Generates a single IA32/x64 error structure. Must later be freed.
71void* generate_ia32x64_error_structure()
72{
73 UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
74
Lawrence Tangaacf0e22022-07-20 13:28:52 +010075 //Set error structure reserved space to zero.
76 UINT64* validation = (UINT64*)(error_structure + 16);
77 *validation &= 0x1F;
78
Lawrence Tang02c801a2022-07-18 14:43:52 +010079 //Create a random type of error structure.
80 EFI_GUID* guid = (EFI_GUID*)error_structure;
Lawrence Tangaacf0e22022-07-20 13:28:52 +010081 UINT64* check_info = (UINT64*)(error_structure + 24);
Lawrence Tang02c801a2022-07-18 14:43:52 +010082 int error_structure_type = rand() % 4;
83 switch (error_structure_type)
84 {
85 //Cache
86 case 0:
Lawrence Tangd34f2b12022-07-19 15:36:31 +010087 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +010088
89 //Set reserved space to zero.
90 *check_info &= ~0xFF00;
91 *check_info &= 0x3FFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +010092 break;
93
94 //TLB
95 case 1:
Lawrence Tangd34f2b12022-07-19 15:36:31 +010096 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +010097
98 //Set reserved space to zero.
99 *check_info &= ~0xFF00;
100 *check_info &= 0x3FFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100101 break;
102
103 //Bus
104 case 2:
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100105 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100106
107 //Set reserved space to zero.
108 *check_info &= ~0xF800;
109 *check_info &= 0x7FFFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100110 break;
111
112 //MS
113 case 3:
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100114 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100115
116 //Set reserved space to zero.
Lawrence Tang01e3a442022-07-20 15:14:50 +0100117 *check_info &= ~0xFFE0;
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100118 *check_info &= 0xFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100119 break;
120 }
121
122 return error_structure;
123}
124
125//Generates a single IA32/x64 context structure. Must later be freed.
126size_t generate_ia32x64_context_structure(void** location)
127{
128 //Initial length is 16 bytes. Add extra based on type.
129 int reg_type = rand() % 8;
130 int reg_size = 0;
131
132 //Set register size.
133 if (reg_type == 2)
Lawrence Tang04750a92022-07-20 16:45:11 +0100134 {
Lawrence Tang02c801a2022-07-18 14:43:52 +0100135 reg_size = 92; //IA32 registers.
Lawrence Tang04750a92022-07-20 16:45:11 +0100136 }
137 else if (reg_type == 3)
138 {
Lawrence Tang02c801a2022-07-18 14:43:52 +0100139 reg_size = 244; //x64 registers.
Lawrence Tang04750a92022-07-20 16:45:11 +0100140 }
Lawrence Tang02c801a2022-07-18 14:43:52 +0100141 else
Lawrence Tang04750a92022-07-20 16:45:11 +0100142 {
143 reg_size = (rand() % 5 + 1) * 32; //Not table defined.
144 }
Lawrence Tang02c801a2022-07-18 14:43:52 +0100145
146 //Create structure randomly.
147 int total_size = 16 + reg_size;
148 UINT16* context_structure = (UINT16*)generate_random_bytes(total_size);
149
Lawrence Tang04750a92022-07-20 16:45:11 +0100150 //If it is x64 registers, set reserved area accordingly.
151 if (reg_type == 3)
152 {
153 UINT8* reg_bytes = (UINT8*)(context_structure + 8);
154 UINT32* reserved = (UINT32*)(reg_bytes + 140);
155 *reserved = 0;
156 }
157
Lawrence Tang02c801a2022-07-18 14:43:52 +0100158 //Set header information.
159 *(context_structure) = reg_type;
160 *(context_structure + 1) = reg_size;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100161
162 //Set return values and exit.
163 *location = context_structure;
164 return total_size;
165}