102c801a5SLawrence Tang /** 2*efe17e2cSLawrence Tang * Functions for generating pseudo-random CPER IA32/x64 sections. 302c801a5SLawrence Tang * 402c801a5SLawrence Tang * Author: Lawrence.Tang@arm.com 502c801a5SLawrence Tang **/ 602c801a5SLawrence Tang 702c801a5SLawrence Tang #include <stdlib.h> 802c801a5SLawrence Tang #include <string.h> 902c801a5SLawrence Tang #include "../../edk/Cper.h" 1002c801a5SLawrence Tang #include "../gen-utils.h" 1167cbed6bSLawrence Tang #include "gen-sections.h" 1267cbed6bSLawrence Tang #define IA32X64_ERROR_STRUCTURE_SIZE 64 1302c801a5SLawrence Tang 1402c801a5SLawrence Tang void* generate_ia32x64_error_structure(); 1502c801a5SLawrence Tang size_t generate_ia32x64_context_structure(void** location); 1602c801a5SLawrence Tang 17*efe17e2cSLawrence Tang //Generates a single pseudo-random IA32/x64 section, saving the resulting address to the given 1802c801a5SLawrence Tang //location. Returns the size of the newly created section. 1902c801a5SLawrence Tang size_t generate_section_ia32x64(void** location) 2002c801a5SLawrence Tang { 2102c801a5SLawrence Tang //Set up for generation of error/context structures. 2202c801a5SLawrence Tang UINT16 error_structure_num = rand() % 5; 2302c801a5SLawrence Tang UINT16 context_structure_num = rand() % 5; 2402c801a5SLawrence Tang void* error_structures[error_structure_num]; 2502c801a5SLawrence Tang void* context_structures[context_structure_num]; 2602c801a5SLawrence Tang size_t context_structure_lengths[context_structure_num]; 2702c801a5SLawrence Tang 2802c801a5SLawrence Tang //Generate the structures. 2902c801a5SLawrence Tang for (int i=0; i<error_structure_num; i++) 3002c801a5SLawrence Tang error_structures[i] = generate_ia32x64_error_structure(); 3102c801a5SLawrence Tang for (int i=0; i<context_structure_num; i++) 3202c801a5SLawrence Tang context_structure_lengths[i] = generate_ia32x64_context_structure(context_structures + i); 3302c801a5SLawrence Tang 3402c801a5SLawrence Tang //Create a valid IA32/x64 section. 3502c801a5SLawrence Tang size_t total_len = 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num); 3602c801a5SLawrence Tang for (int i=0; i<context_structure_num; i++) 3702c801a5SLawrence Tang total_len += context_structure_lengths[i]; 3802c801a5SLawrence Tang UINT8* section = generate_random_bytes(total_len); 3902c801a5SLawrence Tang 40aacf0e26SLawrence Tang //Null extend the end of the CPUID in the header. 41aacf0e26SLawrence Tang for (int i=0; i<16; i++) 42aacf0e26SLawrence Tang *(section + 48 + i) = 0x0; 43aacf0e26SLawrence Tang 4402c801a5SLawrence Tang //Set header information. 4502c801a5SLawrence Tang UINT64* validation = (UINT64*)section; 4602c801a5SLawrence Tang *validation &= 0b11; 4702c801a5SLawrence Tang *validation |= error_structure_num << 2; 4802c801a5SLawrence Tang *validation |= context_structure_num << 8; 4902c801a5SLawrence Tang 5002c801a5SLawrence Tang //Copy in structures, free resources. 5102c801a5SLawrence Tang UINT8* cur_pos = section + 64; 5202c801a5SLawrence Tang for (int i=0; i<error_structure_num; i++) 5302c801a5SLawrence Tang { 5402c801a5SLawrence Tang memcpy(cur_pos, error_structures[i], IA32X64_ERROR_STRUCTURE_SIZE); 5502c801a5SLawrence Tang free(error_structures[i]); 5602c801a5SLawrence Tang cur_pos += IA32X64_ERROR_STRUCTURE_SIZE; 5702c801a5SLawrence Tang } 5802c801a5SLawrence Tang for (int i=0; i<context_structure_num; i++) 5902c801a5SLawrence Tang { 6002c801a5SLawrence Tang memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 6102c801a5SLawrence Tang free(context_structures[i]); 6202c801a5SLawrence Tang cur_pos += context_structure_lengths[i]; 6302c801a5SLawrence Tang } 6402c801a5SLawrence Tang 6502c801a5SLawrence Tang //Set return values, exist. 6602c801a5SLawrence Tang *location = section; 6702c801a5SLawrence Tang return total_len; 6802c801a5SLawrence Tang } 6902c801a5SLawrence Tang 7002c801a5SLawrence Tang //Generates a single IA32/x64 error structure. Must later be freed. 7102c801a5SLawrence Tang void* generate_ia32x64_error_structure() 7202c801a5SLawrence Tang { 7302c801a5SLawrence Tang UINT8* error_structure = generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 7402c801a5SLawrence Tang 75aacf0e26SLawrence Tang //Set error structure reserved space to zero. 76aacf0e26SLawrence Tang UINT64* validation = (UINT64*)(error_structure + 16); 77aacf0e26SLawrence Tang *validation &= 0x1F; 78aacf0e26SLawrence Tang 7902c801a5SLawrence Tang //Create a random type of error structure. 8002c801a5SLawrence Tang EFI_GUID* guid = (EFI_GUID*)error_structure; 81aacf0e26SLawrence Tang UINT64* check_info = (UINT64*)(error_structure + 24); 8202c801a5SLawrence Tang int error_structure_type = rand() % 4; 8302c801a5SLawrence Tang switch (error_structure_type) 8402c801a5SLawrence Tang { 8502c801a5SLawrence Tang //Cache 8602c801a5SLawrence Tang case 0: 87d34f2b11SLawrence Tang memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, sizeof(EFI_GUID)); 88aacf0e26SLawrence Tang 89aacf0e26SLawrence Tang //Set reserved space to zero. 90aacf0e26SLawrence Tang *check_info &= ~0xFF00; 91aacf0e26SLawrence Tang *check_info &= 0x3FFFFFFF; 9202c801a5SLawrence Tang break; 9302c801a5SLawrence Tang 9402c801a5SLawrence Tang //TLB 9502c801a5SLawrence Tang case 1: 96d34f2b11SLawrence Tang memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, sizeof(EFI_GUID)); 97aacf0e26SLawrence Tang 98aacf0e26SLawrence Tang //Set reserved space to zero. 99aacf0e26SLawrence Tang *check_info &= ~0xFF00; 100aacf0e26SLawrence Tang *check_info &= 0x3FFFFFFF; 10102c801a5SLawrence Tang break; 10202c801a5SLawrence Tang 10302c801a5SLawrence Tang //Bus 10402c801a5SLawrence Tang case 2: 105d34f2b11SLawrence Tang memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, sizeof(EFI_GUID)); 106aacf0e26SLawrence Tang 107aacf0e26SLawrence Tang //Set reserved space to zero. 108aacf0e26SLawrence Tang *check_info &= ~0xF800; 109aacf0e26SLawrence Tang *check_info &= 0x7FFFFFFFF; 11002c801a5SLawrence Tang break; 11102c801a5SLawrence Tang 11202c801a5SLawrence Tang //MS 11302c801a5SLawrence Tang case 3: 114d34f2b11SLawrence Tang memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, sizeof(EFI_GUID)); 115aacf0e26SLawrence Tang 116aacf0e26SLawrence Tang //Set reserved space to zero. 11701e3a44dSLawrence Tang *check_info &= ~0xFFE0; 118aacf0e26SLawrence Tang *check_info &= 0xFFFFFF; 11902c801a5SLawrence Tang break; 12002c801a5SLawrence Tang } 12102c801a5SLawrence Tang 12202c801a5SLawrence Tang return error_structure; 12302c801a5SLawrence Tang } 12402c801a5SLawrence Tang 12502c801a5SLawrence Tang //Generates a single IA32/x64 context structure. Must later be freed. 12602c801a5SLawrence Tang size_t generate_ia32x64_context_structure(void** location) 12702c801a5SLawrence Tang { 12802c801a5SLawrence Tang //Initial length is 16 bytes. Add extra based on type. 12902c801a5SLawrence Tang int reg_type = rand() % 8; 13002c801a5SLawrence Tang int reg_size = 0; 13102c801a5SLawrence Tang 13202c801a5SLawrence Tang //Set register size. 13302c801a5SLawrence Tang if (reg_type == 2) 13404750a9eSLawrence Tang { 13502c801a5SLawrence Tang reg_size = 92; //IA32 registers. 13604750a9eSLawrence Tang } 13704750a9eSLawrence Tang else if (reg_type == 3) 13804750a9eSLawrence Tang { 13902c801a5SLawrence Tang reg_size = 244; //x64 registers. 14004750a9eSLawrence Tang } 14102c801a5SLawrence Tang else 14204750a9eSLawrence Tang { 14304750a9eSLawrence Tang reg_size = (rand() % 5 + 1) * 32; //Not table defined. 14404750a9eSLawrence Tang } 14502c801a5SLawrence Tang 14602c801a5SLawrence Tang //Create structure randomly. 14702c801a5SLawrence Tang int total_size = 16 + reg_size; 14802c801a5SLawrence Tang UINT16* context_structure = (UINT16*)generate_random_bytes(total_size); 14902c801a5SLawrence Tang 15004750a9eSLawrence Tang //If it is x64 registers, set reserved area accordingly. 15104750a9eSLawrence Tang if (reg_type == 3) 15204750a9eSLawrence Tang { 15304750a9eSLawrence Tang UINT8* reg_bytes = (UINT8*)(context_structure + 8); 15404750a9eSLawrence Tang UINT32* reserved = (UINT32*)(reg_bytes + 140); 15504750a9eSLawrence Tang *reserved = 0; 15604750a9eSLawrence Tang } 15704750a9eSLawrence Tang 15802c801a5SLawrence Tang //Set header information. 15902c801a5SLawrence Tang *(context_structure) = reg_type; 16002c801a5SLawrence Tang *(context_structure + 1) = reg_size; 16102c801a5SLawrence Tang 16202c801a5SLawrence Tang //Set return values and exit. 16302c801a5SLawrence Tang *location = context_structure; 16402c801a5SLawrence Tang return total_size; 16502c801a5SLawrence Tang }