blob: 7412ca3b86983ff80baf45019240af29c36718ce [file] [log] [blame]
Lawrence Tang02c801a2022-07-18 14:43:52 +01001/**
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"
Lawrence Tang67cbed62022-07-18 16:44:51 +010011#include "gen-sections.h"
12#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
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.
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
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.
67void* 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.
105size_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}