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