1 /** 2 * Functions for generating psuedo-random CPER IA32/x64 sections. 3 * 4 * Author: Lawrence.Tang@arm.com 5 **/ 6 7 #include <stdlib.h> 8 #include <string.h> 9 #include <stdio.h> 10 #include "../../edk/Cper.h" 11 #include "../gen-utils.h" 12 #include "gen-sections.h" 13 #define IA32X64_ERROR_STRUCTURE_SIZE 64 14 15 void* generate_ia32x64_error_structure(); 16 size_t generate_ia32x64_context_structure(void** location); 17 18 //Generates a single psuedo-random IA32/x64 section, saving the resulting address to the given 19 //location. Returns the size of the newly created section. 20 size_t generate_section_ia32x64(void** location) 21 { 22 //Set up for generation of error/context structures. 23 UINT16 error_structure_num = rand() % 5; 24 UINT16 context_structure_num = rand() % 5; 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] = generate_ia32x64_error_structure(); 32 for (int i=0; i<context_structure_num; i++) 33 context_structure_lengths[i] = generate_ia32x64_context_structure(context_structures + i); 34 35 //Create a valid IA32/x64 section. 36 size_t total_len = 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num); 37 for (int i=0; i<context_structure_num; i++) 38 total_len += context_structure_lengths[i]; 39 UINT8* section = generate_random_bytes(total_len); 40 41 //Null extend the end of the CPUID in the header. 42 for (int i=0; i<16; i++) 43 *(section + 48 + i) = 0x0; 44 45 //Set header information. 46 UINT64* validation = (UINT64*)section; 47 *validation &= 0b11; 48 *validation |= error_structure_num << 2; 49 *validation |= context_structure_num << 8; 50 51 //Copy in structures, free resources. 52 UINT8* cur_pos = section + 64; 53 for (int i=0; i<error_structure_num; i++) 54 { 55 memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE); 56 free(error_structures[i]); 57 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE; 58 } 59 for (int i=0; i<context_structure_num; i++) 60 { 61 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 62 free(context_structures[i]); 63 cur_pos += context_structure_lengths[i]; 64 } 65 66 //Set return values, exist. 67 *location = section; 68 return total_len; 69 } 70 71 //Generates a single IA32/x64 error structure. Must later be freed. 72 void* generate_ia32x64_error_structure() 73 { 74 UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 75 76 //Set error structure reserved space to zero. 77 UINT64* validation = (UINT64*)(error_structure + 16); 78 *validation &= 0x1F; 79 80 //Create a random type of error structure. 81 EFI_GUID* guid = (EFI_GUID*)error_structure; 82 UINT64* check_info = (UINT64*)(error_structure + 24); 83 int error_structure_type = rand() % 4; 84 switch (error_structure_type) 85 { 86 //Cache 87 case 0: 88 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(EFI_GUID)); 89 90 //Set reserved space to zero. 91 *check_info &= ~0xFF00; 92 *check_info &= 0x3FFFFFFF; 93 break; 94 95 //TLB 96 case 1: 97 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(EFI_GUID)); 98 99 //Set reserved space to zero. 100 *check_info &= ~0xFF00; 101 *check_info &= 0x3FFFFFFF; 102 break; 103 104 //Bus 105 case 2: 106 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(EFI_GUID)); 107 108 //Set reserved space to zero. 109 *check_info &= ~0xF800; 110 *check_info &= 0x7FFFFFFFF; 111 break; 112 113 //MS 114 case 3: 115 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(EFI_GUID)); 116 117 //Set reserved space to zero. 118 *check_info &= ~0xFFE0; 119 *check_info &= 0xFFFFFF; 120 break; 121 } 122 123 return error_structure; 124 } 125 126 //Generates a single IA32/x64 context structure. Must later be freed. 127 size_t generate_ia32x64_context_structure(void** location) 128 { 129 //Initial length is 16 bytes. Add extra based on type. 130 int reg_type = rand() % 8; 131 int reg_size = 0; 132 133 //Set register size. 134 if (reg_type == 2) 135 reg_size = 92; //IA32 registers. 136 if (reg_type == 3) 137 reg_size = 244; //x64 registers. 138 else 139 reg_size = (rand() % 5) * 32; //Not table defined. 140 141 //Create structure randomly. 142 int total_size = 16 + reg_size; 143 UINT16* context_structure = (UINT16*)generate_random_bytes(total_size); 144 145 //Set header information. 146 *(context_structure) = reg_type; 147 *(context_structure + 1) = reg_size; 148 printf("set reg size to %d (for type %d).\n", reg_size, reg_type); 149 150 //Set return values and exit. 151 *location = context_structure; 152 return total_size; 153 }