blob: 8507d1bf584ef24ce1b1c7bd0d91029fd867f00e [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>
Thu Nguyene42fb482024-10-15 14:43:11 +00009#include <libcper/Cper.h>
10#include <libcper/generator/gen-utils.h>
11#include <libcper/generator/sections/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
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080014void *generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType);
John Chungf8fc7052024-05-03 20:05:29 +080015size_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.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080019size_t generate_section_ia32x64(void **location,
20 GEN_VALID_BITS_TEST_TYPE validBitsType)
Lawrence Tang02c801a2022-07-18 14:43:52 +010021{
John Chungf8fc7052024-05-03 20:05:29 +080022 //Set up for generation of error/context structures.
Ed Tanous2d4d3b62025-03-11 10:34:29 -070023 UINT16 error_structure_num = cper_rand() % 4 + 1;
24 UINT16 context_structure_num = cper_rand() % 4 + 1;
John Chungf8fc7052024-05-03 20:05:29 +080025 void *error_structures[error_structure_num];
26 void *context_structures[context_structure_num];
27 size_t context_structure_lengths[context_structure_num];
Lawrence Tang02c801a2022-07-18 14:43:52 +010028
John Chungf8fc7052024-05-03 20:05:29 +080029 //Generate the structures.
30 for (int i = 0; i < error_structure_num; i++) {
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080031 error_structures[i] =
32 generate_ia32x64_error_structure(validBitsType);
John Chungf8fc7052024-05-03 20:05:29 +080033 }
34 for (int i = 0; i < context_structure_num; i++) {
35 context_structure_lengths[i] =
36 generate_ia32x64_context_structure(context_structures +
37 i);
38 }
Lawrence Tang02c801a2022-07-18 14:43:52 +010039
John Chungf8fc7052024-05-03 20:05:29 +080040 //Create a valid IA32/x64 section.
41 size_t total_len =
42 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num);
43 for (int i = 0; i < context_structure_num; i++) {
44 total_len += context_structure_lengths[i];
45 }
46 UINT8 *section = generate_random_bytes(total_len);
Lawrence Tang02c801a2022-07-18 14:43:52 +010047
John Chungf8fc7052024-05-03 20:05:29 +080048 //Null extend the end of the CPUID in the header.
49 for (int i = 0; i < 16; i++) {
50 *(section + 48 + i) = 0x0;
51 }
Lawrence Tangaacf0e22022-07-20 13:28:52 +010052
John Chungf8fc7052024-05-03 20:05:29 +080053 //Set header information.
54 UINT64 *validation = (UINT64 *)section;
55 *validation &= 0x3;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080056 if (validBitsType == ALL_VALID) {
57 *validation = 0x3;
58 } else if (validBitsType == SOME_VALID) {
59 *validation = 0x2;
60 }
John Chungf8fc7052024-05-03 20:05:29 +080061 *validation |= error_structure_num << 2;
62 *validation |= context_structure_num << 8;
Lawrence Tang02c801a2022-07-18 14:43:52 +010063
John Chungf8fc7052024-05-03 20:05:29 +080064 //Copy in structures, free resources.
65 UINT8 *cur_pos = section + 64;
66 for (int i = 0; i < error_structure_num; i++) {
67 memcpy(cur_pos, error_structures[i],
68 IA32X64_ERROR_STRUCTURE_SIZE);
69 free(error_structures[i]);
70 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE;
71 }
72 for (int i = 0; i < context_structure_num; i++) {
73 memcpy(cur_pos, context_structures[i],
74 context_structure_lengths[i]);
75 free(context_structures[i]);
76 cur_pos += context_structure_lengths[i];
77 }
Lawrence Tang02c801a2022-07-18 14:43:52 +010078
John Chungf8fc7052024-05-03 20:05:29 +080079 //Set return values, exist.
80 *location = section;
81 return total_len;
Lawrence Tang02c801a2022-07-18 14:43:52 +010082}
83
84//Generates a single IA32/x64 error structure. Must later be freed.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080085void *generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType)
Lawrence Tang02c801a2022-07-18 14:43:52 +010086{
John Chungf8fc7052024-05-03 20:05:29 +080087 UINT8 *error_structure =
88 generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE);
Lawrence Tang02c801a2022-07-18 14:43:52 +010089
John Chungf8fc7052024-05-03 20:05:29 +080090 //Set error structure reserved space to zero.
91 UINT64 *validation = (UINT64 *)(error_structure + 16);
92 *validation &= 0x1F;
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -080093 if (validBitsType == ALL_VALID) {
94 *validation = 0x1F;
95 } else if (validBitsType == SOME_VALID) {
96 *validation = 0x15;
97 }
Lawrence Tangaacf0e22022-07-20 13:28:52 +010098
John Chungf8fc7052024-05-03 20:05:29 +080099 //Create a random type of error structure.
100 EFI_GUID *guid = (EFI_GUID *)error_structure;
101 UINT64 *check_info = (UINT64 *)(error_structure + 24);
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700102 int error_structure_type = cper_rand() % 4;
John Chungf8fc7052024-05-03 20:05:29 +0800103 switch (error_structure_type) {
104 //Cache
105 case 0:
106 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid,
107 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100108
John Chungf8fc7052024-05-03 20:05:29 +0800109 //Set reserved space to zero.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800110 *check_info = ~0x20FF00;
John Chungf8fc7052024-05-03 20:05:29 +0800111 *check_info &= 0x3FFFFFFF;
112 break;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100113
John Chungf8fc7052024-05-03 20:05:29 +0800114 //TLB
115 case 1:
116 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid,
117 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100118
John Chungf8fc7052024-05-03 20:05:29 +0800119 //Set reserved space to zero.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800120 *check_info = ~0x20FF00;
John Chungf8fc7052024-05-03 20:05:29 +0800121 *check_info &= 0x3FFFFFFF;
122 break;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100123
John Chungf8fc7052024-05-03 20:05:29 +0800124 //Bus
125 case 2:
126 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid,
127 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100128
John Chungf8fc7052024-05-03 20:05:29 +0800129 //Set reserved space to zero.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800130 *check_info = ~0x20F800;
John Chungf8fc7052024-05-03 20:05:29 +0800131 *check_info &= 0x7FFFFFFFF;
132 break;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100133
John Chungf8fc7052024-05-03 20:05:29 +0800134 //MS
135 case 3:
136 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid,
137 sizeof(EFI_GUID));
Lawrence Tangaacf0e22022-07-20 13:28:52 +0100138
John Chungf8fc7052024-05-03 20:05:29 +0800139 //Set reserved space to zero.
Aushim Nagarkattiae8f6d92025-01-29 17:34:44 -0800140 *check_info = ~0xFFC0;
John Chungf8fc7052024-05-03 20:05:29 +0800141 *check_info &= 0xFFFFFF;
142 break;
143 }
Lawrence Tang02c801a2022-07-18 14:43:52 +0100144
John Chungf8fc7052024-05-03 20:05:29 +0800145 return error_structure;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100146}
147
148//Generates a single IA32/x64 context structure. Must later be freed.
John Chungf8fc7052024-05-03 20:05:29 +0800149size_t generate_ia32x64_context_structure(void **location)
Lawrence Tang02c801a2022-07-18 14:43:52 +0100150{
John Chungf8fc7052024-05-03 20:05:29 +0800151 //Initial length is 16 bytes. Add extra based on type.
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700152 int reg_type = cper_rand() % 8;
John Chungf8fc7052024-05-03 20:05:29 +0800153 int reg_size = 0;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100154
John Chungf8fc7052024-05-03 20:05:29 +0800155 //Set register size.
156 if (reg_type == 2) {
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700157 reg_size = 92; //IA32 registers.
John Chungf8fc7052024-05-03 20:05:29 +0800158 } else if (reg_type == 3) {
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700159 reg_size = 244; //x64 registers.
John Chungf8fc7052024-05-03 20:05:29 +0800160 } else {
Ed Tanous2d4d3b62025-03-11 10:34:29 -0700161 reg_size = (cper_rand() % 5 + 1) * 32; //Not table defined.
John Chungf8fc7052024-05-03 20:05:29 +0800162 }
Lawrence Tang02c801a2022-07-18 14:43:52 +0100163
John Chungf8fc7052024-05-03 20:05:29 +0800164 //Create structure randomly.
165 int total_size = 16 + reg_size;
166 UINT16 *context_structure = (UINT16 *)generate_random_bytes(total_size);
Lawrence Tang02c801a2022-07-18 14:43:52 +0100167
John Chungf8fc7052024-05-03 20:05:29 +0800168 //If it is x64 registers, set reserved area accordingly.
169 if (reg_type == 3) {
170 UINT8 *reg_bytes = (UINT8 *)(context_structure + 8);
171 UINT32 *reserved = (UINT32 *)(reg_bytes + 140);
172 *reserved = 0;
173 }
Lawrence Tang04750a92022-07-20 16:45:11 +0100174
John Chungf8fc7052024-05-03 20:05:29 +0800175 //Set header information.
176 *(context_structure) = reg_type;
177 *(context_structure + 1) = reg_size;
Lawrence Tang02c801a2022-07-18 14:43:52 +0100178
John Chungf8fc7052024-05-03 20:05:29 +0800179 //Set return values and exit.
180 *location = context_structure;
181 return total_size;
182}