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() % 5; 23 UINT16 context_structure_num = rand() % 5; 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 for (int i=0; i<context_structure_num; i++) 32 context_structure_lengths[i] = generate_ia32x64_context_structure(context_structures + i); 33 34 //Create a valid IA32/x64 section. 35 size_t total_len = 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num); 36 for (int i=0; i<context_structure_num; i++) 37 total_len += context_structure_lengths[i]; 38 UINT8* section = generate_random_bytes(total_len); 39 40 //Null extend the end of the CPUID in the header. 41 for (int i=0; i<16; i++) 42 *(section + 48 + i) = 0x0; 43 44 //Set header information. 45 UINT64* validation = (UINT64*)section; 46 *validation &= 0b11; 47 *validation |= error_structure_num << 2; 48 *validation |= context_structure_num << 8; 49 50 //Copy in structures, free resources. 51 UINT8* cur_pos = section + 64; 52 for (int i=0; i<error_structure_num; i++) 53 { 54 memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE); 55 free(error_structures[i]); 56 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE; 57 } 58 for (int i=0; i<context_structure_num; i++) 59 { 60 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 61 free(context_structures[i]); 62 cur_pos += context_structure_lengths[i]; 63 } 64 65 //Set return values, exist. 66 *location = section; 67 return total_len; 68 } 69 70 //Generates a single IA32/x64 error structure. Must later be freed. 71 void* generate_ia32x64_error_structure() 72 { 73 UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 74 75 //Set error structure reserved space to zero. 76 UINT64* validation = (UINT64*)(error_structure + 16); 77 *validation &= 0x1F; 78 79 //Create a random type of error structure. 80 EFI_GUID* guid = (EFI_GUID*)error_structure; 81 UINT64* check_info = (UINT64*)(error_structure + 24); 82 int error_structure_type = rand() % 4; 83 switch (error_structure_type) 84 { 85 //Cache 86 case 0: 87 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(EFI_GUID)); 88 89 //Set reserved space to zero. 90 *check_info &= ~0xFF00; 91 *check_info &= 0x3FFFFFFF; 92 break; 93 94 //TLB 95 case 1: 96 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(EFI_GUID)); 97 98 //Set reserved space to zero. 99 *check_info &= ~0xFF00; 100 *check_info &= 0x3FFFFFFF; 101 break; 102 103 //Bus 104 case 2: 105 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(EFI_GUID)); 106 107 //Set reserved space to zero. 108 *check_info &= ~0xF800; 109 *check_info &= 0x7FFFFFFFF; 110 break; 111 112 //MS 113 case 3: 114 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(EFI_GUID)); 115 116 //Set reserved space to zero. 117 *check_info &= ~0xFFE0; 118 *check_info &= 0xFFFFFF; 119 break; 120 } 121 122 return error_structure; 123 } 124 125 //Generates a single IA32/x64 context structure. Must later be freed. 126 size_t generate_ia32x64_context_structure(void** location) 127 { 128 //Initial length is 16 bytes. Add extra based on type. 129 int reg_type = rand() % 8; 130 int reg_size = 0; 131 132 //Set register size. 133 if (reg_type == 2) 134 { 135 reg_size = 92; //IA32 registers. 136 } 137 else if (reg_type == 3) 138 { 139 reg_size = 244; //x64 registers. 140 } 141 else 142 { 143 reg_size = (rand() % 5 + 1) * 32; //Not table defined. 144 } 145 146 //Create structure randomly. 147 int total_size = 16 + reg_size; 148 UINT16* context_structure = (UINT16*)generate_random_bytes(total_size); 149 150 //If it is x64 registers, set reserved area accordingly. 151 if (reg_type == 3) 152 { 153 UINT8* reg_bytes = (UINT8*)(context_structure + 8); 154 UINT32* reserved = (UINT32*)(reg_bytes + 140); 155 *reserved = 0; 156 } 157 158 //Set header information. 159 *(context_structure) = reg_type; 160 *(context_structure + 1) = reg_size; 161 162 //Set return values and exit. 163 *location = context_structure; 164 return total_size; 165 }