blob: 2fb658586f578a075609b33b36bcd6de56e10ac1 [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>
Lawrence Tang01e3a442022-07-20 15:14:50 +01009#include <stdio.h>
Lawrence Tang02c801a2022-07-18 14:43:52 +010010#include "../../edk/Cper.h"
11#include "../gen-utils.h"
Lawrence Tang67cbed62022-07-18 16:44:51 +010012#include "gen-sections.h"
13#define IA32X64_ERROR_STRUCTURE_SIZE 64
Lawrence Tang02c801a2022-07-18 14:43:52 +010014
15void* generate_ia32x64_error_structure();
16size_t generate_ia32x64_context_structure(void** location);
17
18//Generates a single psuedo-random IA32/x64 section, saving the resulting address to the given
19//location. Returns the size of the newly created section.
20size_t generate_section_ia32x64(void** location)
21{
22 //Set up for generation of error/context structures.
23 UINT16 error_structure_num = rand() % 5;
24 UINT16 context_structure_num = rand() % 5;
25 void* error_structures[error_structure_num];
26 void* context_structures[context_structure_num];
27 size_t context_structure_lengths[context_structure_num];
28
29 //Generate the structures.
30 for (int i=0; i<error_structure_num; i++)
31 error_structures[i] = generate_ia32x64_error_structure();
32 for (int i=0; i<context_structure_num; i++)
33 context_structure_lengths[i] = generate_ia32x64_context_structure(context_structures + i);
34
35 //Create a valid IA32/x64 section.
36 size_t total_len = 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num);
37 for (int i=0; i<context_structure_num; i++)
38 total_len += context_structure_lengths[i];
39 UINT8* section = generate_random_bytes(total_len);
40
Lawrence Tangaacf0e22022-07-20 13:28:52 +010041 //Null extend the end of the CPUID in the header.
42 for (int i=0; i<16; i++)
43 *(section + 48 + i) = 0x0;
44
Lawrence Tang02c801a2022-07-18 14:43:52 +010045 //Set header information.
46 UINT64* validation = (UINT64*)section;
47 *validation &= 0b11;
48 *validation |= error_structure_num << 2;
49 *validation |= context_structure_num << 8;
50
51 //Copy in structures, free resources.
52 UINT8* cur_pos = section + 64;
53 for (int i=0; i<error_structure_num; i++)
54 {
55 memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE);
56 free(error_structures[i]);
57 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE;
58 }
59 for (int i=0; i<context_structure_num; i++)
60 {
61 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]);
62 free(context_structures[i]);
63 cur_pos += context_structure_lengths[i];
64 }
65
66 //Set return values, exist.
67 *location = section;
68 return total_len;
69}
70
71//Generates a single IA32/x64 error structure. Must later be freed.
72void* generate_ia32x64_error_structure()
73{
74 UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
75
Lawrence Tangaacf0e22022-07-20 13:28:52 +010076 //Set error structure reserved space to zero.
77 UINT64* validation = (UINT64*)(error_structure + 16);
78 *validation &= 0x1F;
79
Lawrence Tang02c801a2022-07-18 14:43:52 +010080 //Create a random type of error structure.
81 EFI_GUID* guid = (EFI_GUID*)error_structure;
Lawrence Tangaacf0e22022-07-20 13:28:52 +010082 UINT64* check_info = (UINT64*)(error_structure + 24);
Lawrence Tang02c801a2022-07-18 14:43:52 +010083 int error_structure_type = rand() % 4;
84 switch (error_structure_type)
85 {
86 //Cache
87 case 0:
Lawrence Tangd34f2b12022-07-19 15:36:31 +010088 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +010089
90 //Set reserved space to zero.
91 *check_info &= ~0xFF00;
92 *check_info &= 0x3FFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +010093 break;
94
95 //TLB
96 case 1:
Lawrence Tangd34f2b12022-07-19 15:36:31 +010097 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +010098
99 //Set reserved space to zero.
100 *check_info &= ~0xFF00;
101 *check_info &= 0x3FFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100102 break;
103
104 //Bus
105 case 2:
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100106 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100107
108 //Set reserved space to zero.
109 *check_info &= ~0xF800;
110 *check_info &= 0x7FFFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100111 break;
112
113 //MS
114 case 3:
Lawrence Tangd34f2b12022-07-19 15:36:31 +0100115 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100116
117 //Set reserved space to zero.
Lawrence Tang01e3a442022-07-20 15:14:50 +0100118 *check_info &= ~0xFFE0;
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100119 *check_info &= 0xFFFFFF;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100120 break;
121 }
122
123 return error_structure;
124}
125
126//Generates a single IA32/x64 context structure. Must later be freed.
127size_t generate_ia32x64_context_structure(void** location)
128{
129 //Initial length is 16 bytes. Add extra based on type.
130 int reg_type = rand() % 8;
131 int reg_size = 0;
132
133 //Set register size.
134 if (reg_type == 2)
135 reg_size = 92; //IA32 registers.
136 if (reg_type == 3)
137 reg_size = 244; //x64 registers.
138 else
Lawrence Tang01e3a442022-07-20 15:14:50 +0100139 reg_size = (rand() % 5) * 32; //Not table defined.
Lawrence Tang02c801a2022-07-18 14:43:52 +0100140
141 //Create structure randomly.
142 int total_size = 16 + reg_size;
143 UINT16* context_structure = (UINT16*)generate_random_bytes(total_size);
144
145 //Set header information.
146 *(context_structure) = reg_type;
147 *(context_structure + 1) = reg_size;
Lawrence Tang01e3a442022-07-20 15:14:50 +0100148 printf("set reg size to %d (for type %d).\n", reg_size, reg_type);
Lawrence Tang02c801a2022-07-18 14:43:52 +0100149
150 //Set return values and exit.
151 *location = context_structure;
152 return total_size;
153}