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