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 "../../edk/Cper.h" 10 #include "../gen-utils.h" 11 #include "gen-sections.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 psuedo-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 //Set header information. 41 UINT64* validation = (UINT64*)section; 42 *validation &= 0b11; 43 *validation |= error_structure_num << 2; 44 *validation |= context_structure_num << 8; 45 46 //Copy in structures, free resources. 47 UINT8* cur_pos = section + 64; 48 for (int i=0; i<error_structure_num; i++) 49 { 50 memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE); 51 free(error_structures[i]); 52 cur_pos += IA32X64_ERROR_STRUCTURE_SIZE; 53 } 54 for (int i=0; i<context_structure_num; i++) 55 { 56 memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 57 free(context_structures[i]); 58 cur_pos += context_structure_lengths[i]; 59 } 60 61 //Set return values, exist. 62 *location = section; 63 return total_len; 64 } 65 66 //Generates a single IA32/x64 error structure. Must later be freed. 67 void* generate_ia32x64_error_structure() 68 { 69 UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 70 71 //Create a random type of error structure. 72 EFI_GUID* guid = (EFI_GUID*)error_structure; 73 int error_structure_type = rand() % 4; 74 switch (error_structure_type) 75 { 76 //Cache 77 case 0: 78 memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(guid)); 79 memset(error_structure + 30, 0, 34); 80 break; 81 82 //TLB 83 case 1: 84 memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(guid)); 85 memset(error_structure + 30, 0, 34); 86 break; 87 88 //Bus 89 case 2: 90 memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(guid)); 91 memset(error_structure + 35, 0, 29); 92 break; 93 94 //MS 95 case 3: 96 memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(guid)); 97 memset(error_structure + 24, 0, 38); 98 break; 99 } 100 101 return error_structure; 102 } 103 104 //Generates a single IA32/x64 context structure. Must later be freed. 105 size_t generate_ia32x64_context_structure(void** location) 106 { 107 //Initial length is 16 bytes. Add extra based on type. 108 int reg_type = rand() % 8; 109 int reg_size = 0; 110 111 //Set register size. 112 if (reg_type == 2) 113 reg_size = 92; //IA32 registers. 114 if (reg_type == 3) 115 reg_size = 244; //x64 registers. 116 else 117 reg_size = rand() % 64; //Not table defined. 118 119 //Create structure randomly. 120 int total_size = 16 + reg_size; 121 UINT16* context_structure = (UINT16*)generate_random_bytes(total_size); 122 123 //Set header information. 124 *(context_structure) = reg_type; 125 *(context_structure + 1) = reg_size; 126 127 //Set return values and exit. 128 *location = context_structure; 129 return total_size; 130 }