blob: e1fb60d57e0bfb71e7b9b928021e201be4ff1623 [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.
Ed Tanousfedd4572024-07-12 13:56:00 -07003 *
Lawrence Tang02c801a2022-07-18 14:43:52 +01004 * Author: Lawrence.Tang@arm.com
5 **/
6
7#include <stdlib.h>
8#include <string.h>
Ed Tanousa3b7f8a2024-11-04 16:38:59 -08009#include "../../Cper.h"
Lawrence Tang02c801a2022-07-18 14:43:52 +010010#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
John Chungf8fc7052024-05-03 20:05:29 +080014void *generate_ia32x64_error_structure();
15size_t generate_ia32x64_context_structure(void **location);
Lawrence Tang02c801a2022-07-18 14:43:52 +010016
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.
John Chungf8fc7052024-05-03 20:05:29 +080019size_t generate_section_ia32x64(void **location)
Lawrence Tang02c801a2022-07-18 14:43:52 +010020{
John Chungf8fc7052024-05-03 20:05:29 +080021 //Set up for generation of error/context structures.
22 UINT16 error_structure_num = rand() % 4 + 1;
23 UINT16 context_structure_num = rand() % 4 + 1;
24 void *error_structures[error_structure_num];
25 void *context_structures[context_structure_num];
26 size_t context_structure_lengths[context_structure_num];
Lawrence Tang02c801a2022-07-18 14:43:52 +010027
John Chungf8fc7052024-05-03 20:05:29 +080028 //Generate the structures.
29 for (int i = 0; i < error_structure_num; i++) {
30 error_structures[i] = generate_ia32x64_error_structure();
31 }
32 for (int i = 0; i < context_structure_num; i++) {
33 context_structure_lengths[i] =
34 generate_ia32x64_context_structure(context_structures +
35 i);
36 }
Lawrence Tang02c801a2022-07-18 14:43:52 +010037
John Chungf8fc7052024-05-03 20:05:29 +080038 //Create a valid IA32/x64 section.
39 size_t total_len =
40 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num);
41 for (int i = 0; i < context_structure_num; i++) {
42 total_len += context_structure_lengths[i];
43 }
44 UINT8 *section = generate_random_bytes(total_len);
Lawrence Tang02c801a2022-07-18 14:43:52 +010045
John Chungf8fc7052024-05-03 20:05:29 +080046 //Null extend the end of the CPUID in the header.
47 for (int i = 0; i < 16; i++) {
48 *(section + 48 + i) = 0x0;
49 }
Lawrence Tangaacf0e22022-07-20 13:28:52 +010050
John Chungf8fc7052024-05-03 20:05:29 +080051 //Set header information.
52 UINT64 *validation = (UINT64 *)section;
53 *validation &= 0x3;
54 *validation |= error_structure_num << 2;
55 *validation |= context_structure_num << 8;
Lawrence Tang02c801a2022-07-18 14:43:52 +010056
John Chungf8fc7052024-05-03 20:05:29 +080057 //Copy in structures, free resources.
58 UINT8 *cur_pos = section + 64;
59 for (int i = 0; i < error_structure_num; i++) {
60 memcpy(cur_pos, error_structures[i],
61 IA32X64_ERROR_STRUCTURE_SIZE);
62 free(error_structures[i]);
63 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE;
64 }
65 for (int i = 0; i < context_structure_num; i++) {
66 memcpy(cur_pos, context_structures[i],
67 context_structure_lengths[i]);
68 free(context_structures[i]);
69 cur_pos += context_structure_lengths[i];
70 }
Lawrence Tang02c801a2022-07-18 14:43:52 +010071
John Chungf8fc7052024-05-03 20:05:29 +080072 //Set return values, exist.
73 *location = section;
74 return total_len;
Lawrence Tang02c801a2022-07-18 14:43:52 +010075}
76
77//Generates a single IA32/x64 error structure. Must later be freed.
John Chungf8fc7052024-05-03 20:05:29 +080078void *generate_ia32x64_error_structure()
Lawrence Tang02c801a2022-07-18 14:43:52 +010079{
John Chungf8fc7052024-05-03 20:05:29 +080080 UINT8 *error_structure =
81 generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
Lawrence Tang02c801a2022-07-18 14:43:52 +010082
John Chungf8fc7052024-05-03 20:05:29 +080083 //Set error structure reserved space to zero.
84 UINT64 *validation = (UINT64 *)(error_structure + 16);
85 *validation &= 0x1F;
Lawrence Tangaacf0e22022-07-20 13:28:52 +010086
John Chungf8fc7052024-05-03 20:05:29 +080087 //Create a random type of error structure.
88 EFI_GUID *guid = (EFI_GUID *)error_structure;
89 UINT64 *check_info = (UINT64 *)(error_structure + 24);
90 int error_structure_type = rand() % 4;
91 switch (error_structure_type) {
92 //Cache
93 case 0:
94 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid,
95 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +010096
John Chungf8fc7052024-05-03 20:05:29 +080097 //Set reserved space to zero.
98 *check_info &= ~0x20FF00;
99 *check_info &= 0x3FFFFFFF;
100 break;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100101
John Chungf8fc7052024-05-03 20:05:29 +0800102 //TLB
103 case 1:
104 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid,
105 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100106
John Chungf8fc7052024-05-03 20:05:29 +0800107 //Set reserved space to zero.
108 *check_info &= ~0x20FF00;
109 *check_info &= 0x3FFFFFFF;
110 break;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100111
John Chungf8fc7052024-05-03 20:05:29 +0800112 //Bus
113 case 2:
114 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid,
115 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100116
John Chungf8fc7052024-05-03 20:05:29 +0800117 //Set reserved space to zero.
118 *check_info &= ~0x20F800;
119 *check_info &= 0x7FFFFFFFF;
120 break;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100121
John Chungf8fc7052024-05-03 20:05:29 +0800122 //MS
123 case 3:
124 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid,
125 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100126
John Chungf8fc7052024-05-03 20:05:29 +0800127 //Set reserved space to zero.
128 *check_info &= ~0xFFE0;
129 *check_info &= 0xFFFFFF;
130 break;
131 }
Lawrence Tang02c801a2022-07-18 14:43:52 +0100132
John Chungf8fc7052024-05-03 20:05:29 +0800133 return error_structure;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100134}
135
136//Generates a single IA32/x64 context structure. Must later be freed.
John Chungf8fc7052024-05-03 20:05:29 +0800137size_t generate_ia32x64_context_structure(void **location)
Lawrence Tang02c801a2022-07-18 14:43:52 +0100138{
John Chungf8fc7052024-05-03 20:05:29 +0800139 //Initial length is 16 bytes. Add extra based on type.
140 int reg_type = rand() % 8;
141 int reg_size = 0;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100142
John Chungf8fc7052024-05-03 20:05:29 +0800143 //Set register size.
144 if (reg_type == 2) {
145 reg_size = 92; //IA32 registers.
146 } else if (reg_type == 3) {
147 reg_size = 244; //x64 registers.
148 } else {
149 reg_size = (rand() % 5 + 1) * 32; //Not table defined.
150 }
Lawrence Tang02c801a2022-07-18 14:43:52 +0100151
John Chungf8fc7052024-05-03 20:05:29 +0800152 //Create structure randomly.
153 int total_size = 16 + reg_size;
154 UINT16 *context_structure = (UINT16 *)generate_random_bytes(total_size);
Lawrence Tang02c801a2022-07-18 14:43:52 +0100155
John Chungf8fc7052024-05-03 20:05:29 +0800156 //If it is x64 registers, set reserved area accordingly.
157 if (reg_type == 3) {
158 UINT8 *reg_bytes = (UINT8 *)(context_structure + 8);
159 UINT32 *reserved = (UINT32 *)(reg_bytes + 140);
160 *reserved = 0;
161 }
Lawrence Tang04750a92022-07-20 16:45:11 +0100162
John Chungf8fc7052024-05-03 20:05:29 +0800163 //Set header information.
164 *(context_structure) = reg_type;
165 *(context_structure + 1) = reg_size;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100166
John Chungf8fc7052024-05-03 20:05:29 +0800167 //Set return values and exit.
168 *location = context_structure;
169 return total_size;
170}