1 /** 2 * Functions for generating pseudo-random CPER IA32/x64 sections. 3 * 4 * Author: Lawrence.Tang@arm.com 5 **/ 6 7 #include <stdlib.h> 8 #include <string.h> 9 #include <libcper/Cper.h> 10 #include <libcper/generator/gen-utils.h> 11 #include <libcper/generator/sections/gen-section.h> 12 #define IA32X64_ERROR_STRUCTURE_SIZE 64 13 14 void *generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType); 15 size_t generate_ia32x64_context_structure(void **location); 16 17 //Generates a single pseudo-random IA32/x64 section, saving the resulting address to the given 18 //location. Returns the size of the newly created section. 19 size_t generate_section_ia32x64(void **location, 20 GEN_VALID_BITS_TEST_TYPE validBitsType) 21 { 22 //Set up for generation of error/context structures. 23 UINT16 error_structure_num = cper_rand() % 4 + 1; 24 UINT16 context_structure_num = cper_rand() % 4 + 1; 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] = 32 generate_ia32x64_error_structure(validBitsType); 33 } 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 } 39 40 //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); 47 48 //Null extend the end of the CPUID in the header. 49 for (int i = 0; i < 16; i++) { 50 *(section + 48 + i) = 0x0; 51 } 52 53 //Set header information. 54 UINT64 *validation = (UINT64 *)section; 55 *validation &= 0x3; 56 if (validBitsType == ALL_VALID) { 57 *validation = 0x3; 58 } else if (validBitsType == SOME_VALID) { 59 *validation = 0x2; 60 } 61 *validation |= error_structure_num << 2; 62 *validation |= context_structure_num << 8; 63 64 //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 } 78 79 //Set return values, exist. 80 *location = section; 81 return total_len; 82 } 83 84 //Generates a single IA32/x64 error structure. Must later be freed. 85 void *generate_ia32x64_error_structure(GEN_VALID_BITS_TEST_TYPE validBitsType) 86 { 87 UINT8 *error_structure = 88 generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 89 90 //Set error structure reserved space to zero. 91 UINT64 *validation = (UINT64 *)(error_structure + 16); 92 *validation &= 0x1F; 93 if (validBitsType == ALL_VALID) { 94 *validation = 0x1F; 95 } else if (validBitsType == SOME_VALID) { 96 *validation = 0x15; 97 } 98 99 //Create a random type of error structure. 100 EFI_GUID *guid = (EFI_GUID *)error_structure; 101 UINT64 *check_info = (UINT64 *)(error_structure + 24); 102 int error_structure_type = cper_rand() % 4; 103 switch (error_structure_type) { 104 //Cache 105 case 0: 106 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, 107 sizeof(EFI_GUID)); 108 109 //Set reserved space to zero. 110 *check_info = ~0x20FF00; 111 *check_info &= 0x3FFFFFFF; 112 break; 113 114 //TLB 115 case 1: 116 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, 117 sizeof(EFI_GUID)); 118 119 //Set reserved space to zero. 120 *check_info = ~0x20FF00; 121 *check_info &= 0x3FFFFFFF; 122 break; 123 124 //Bus 125 case 2: 126 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, 127 sizeof(EFI_GUID)); 128 129 //Set reserved space to zero. 130 *check_info = ~0x20F800; 131 *check_info &= 0x7FFFFFFFF; 132 break; 133 134 //MS 135 case 3: 136 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, 137 sizeof(EFI_GUID)); 138 139 //Set reserved space to zero. 140 *check_info = ~0xFFC0; 141 *check_info &= 0xFFFFFF; 142 break; 143 } 144 145 return error_structure; 146 } 147 148 //Generates a single IA32/x64 context structure. Must later be freed. 149 size_t generate_ia32x64_context_structure(void **location) 150 { 151 //Initial length is 16 bytes. Add extra based on type. 152 int reg_type = cper_rand() % 8; 153 int reg_size = 0; 154 155 //Set register size. 156 if (reg_type == 2) { 157 reg_size = 92; //IA32 registers. 158 } else if (reg_type == 3) { 159 reg_size = 244; //x64 registers. 160 } else { 161 reg_size = (cper_rand() % 5 + 1) * 32; //Not table defined. 162 } 163 164 //Create structure randomly. 165 int total_size = 16 + reg_size; 166 UINT16 *context_structure = (UINT16 *)generate_random_bytes(total_size); 167 168 //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 } 174 175 //Set header information. 176 *(context_structure) = reg_type; 177 *(context_structure + 1) = reg_size; 178 179 //Set return values and exit. 180 *location = context_structure; 181 return total_size; 182 } 183