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 "../../edk/Cper.h" 10 #include "../gen-utils.h" 11 #include "gen-section.h" 12 #define IA32X64_ERROR_STRUCTURE_SIZE 64 13 14 void *generate_ia32x64_error_structure(); 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 { 21 //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]; 27 28 //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 } 37 38 //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); 45 46 //Null extend the end of the CPUID in the header. 47 for (int i = 0; i < 16; i++) { 48 *(section + 48 + i) = 0x0; 49 } 50 51 //Set header information. 52 UINT64 *validation = (UINT64 *)section; 53 *validation &= 0x3; 54 *validation |= error_structure_num << 2; 55 *validation |= context_structure_num << 8; 56 57 //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 } 71 72 //Set return values, exist. 73 *location = section; 74 return total_len; 75 } 76 77 //Generates a single IA32/x64 error structure. Must later be freed. 78 void *generate_ia32x64_error_structure() 79 { 80 UINT8 *error_structure = 81 generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 82 83 //Set error structure reserved space to zero. 84 UINT64 *validation = (UINT64 *)(error_structure + 16); 85 *validation &= 0x1F; 86 87 //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)); 96 97 //Set reserved space to zero. 98 *check_info &= ~0x20FF00; 99 *check_info &= 0x3FFFFFFF; 100 break; 101 102 //TLB 103 case 1: 104 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, 105 sizeof(EFI_GUID)); 106 107 //Set reserved space to zero. 108 *check_info &= ~0x20FF00; 109 *check_info &= 0x3FFFFFFF; 110 break; 111 112 //Bus 113 case 2: 114 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, 115 sizeof(EFI_GUID)); 116 117 //Set reserved space to zero. 118 *check_info &= ~0x20F800; 119 *check_info &= 0x7FFFFFFFF; 120 break; 121 122 //MS 123 case 3: 124 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, 125 sizeof(EFI_GUID)); 126 127 //Set reserved space to zero. 128 *check_info &= ~0xFFE0; 129 *check_info &= 0xFFFFFF; 130 break; 131 } 132 133 return error_structure; 134 } 135 136 //Generates a single IA32/x64 context structure. Must later be freed. 137 size_t generate_ia32x64_context_structure(void **location) 138 { 139 //Initial length is 16 bytes. Add extra based on type. 140 int reg_type = rand() % 8; 141 int reg_size = 0; 142 143 //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 } 151 152 //Create structure randomly. 153 int total_size = 16 + reg_size; 154 UINT16 *context_structure = (UINT16 *)generate_random_bytes(total_size); 155 156 //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 } 162 163 //Set header information. 164 *(context_structure) = reg_type; 165 *(context_structure + 1) = reg_size; 166 167 //Set return values and exit. 168 *location = context_structure; 169 return total_size; 170 } 171