102c801a5SLawrence Tang /** 2efe17e2cSLawrence 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" 118f977457SLawrence Tang #include "gen-section.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 17efe17e2cSLawrence 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. 22*f8fc7052SJohn Chung UINT16 error_structure_num = rand() % 4 + 1; 23*f8fc7052SJohn Chung UINT16 context_structure_num = rand() % 4 + 1; 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. 29*f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) { 3002c801a5SLawrence Tang error_structures[i] = generate_ia32x64_error_structure(); 31*f8fc7052SJohn Chung } 32*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) { 33*f8fc7052SJohn Chung context_structure_lengths[i] = 34*f8fc7052SJohn Chung generate_ia32x64_context_structure(context_structures + 35*f8fc7052SJohn Chung i); 36*f8fc7052SJohn Chung } 3702c801a5SLawrence Tang 3802c801a5SLawrence Tang //Create a valid IA32/x64 section. 39*f8fc7052SJohn Chung size_t total_len = 40*f8fc7052SJohn Chung 64 + (IA32X64_ERROR_STRUCTURE_SIZE * error_structure_num); 41*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) { 4202c801a5SLawrence Tang total_len += context_structure_lengths[i]; 43*f8fc7052SJohn Chung } 4402c801a5SLawrence Tang UINT8 *section = generate_random_bytes(total_len); 4502c801a5SLawrence Tang 46aacf0e26SLawrence Tang //Null extend the end of the CPUID in the header. 47*f8fc7052SJohn Chung for (int i = 0; i < 16; i++) { 48aacf0e26SLawrence Tang *(section + 48 + i) = 0x0; 49*f8fc7052SJohn Chung } 50aacf0e26SLawrence Tang 5102c801a5SLawrence Tang //Set header information. 5202c801a5SLawrence Tang UINT64 *validation = (UINT64 *)section; 53*f8fc7052SJohn Chung *validation &= 0x3; 5402c801a5SLawrence Tang *validation |= error_structure_num << 2; 5502c801a5SLawrence Tang *validation |= context_structure_num << 8; 5602c801a5SLawrence Tang 5702c801a5SLawrence Tang //Copy in structures, free resources. 5802c801a5SLawrence Tang UINT8 *cur_pos = section + 64; 59*f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) { 60*f8fc7052SJohn Chung memcpy(cur_pos, error_structures[i], 61*f8fc7052SJohn Chung IA32X64_ERROR_STRUCTURE_SIZE); 6202c801a5SLawrence Tang free(error_structures[i]); 6302c801a5SLawrence Tang cur_pos += IA32X64_ERROR_STRUCTURE_SIZE; 6402c801a5SLawrence Tang } 65*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) { 66*f8fc7052SJohn Chung memcpy(cur_pos, context_structures[i], 67*f8fc7052SJohn Chung context_structure_lengths[i]); 6802c801a5SLawrence Tang free(context_structures[i]); 6902c801a5SLawrence Tang cur_pos += context_structure_lengths[i]; 7002c801a5SLawrence Tang } 7102c801a5SLawrence Tang 7202c801a5SLawrence Tang //Set return values, exist. 7302c801a5SLawrence Tang *location = section; 7402c801a5SLawrence Tang return total_len; 7502c801a5SLawrence Tang } 7602c801a5SLawrence Tang 7702c801a5SLawrence Tang //Generates a single IA32/x64 error structure. Must later be freed. 7802c801a5SLawrence Tang void *generate_ia32x64_error_structure() 7902c801a5SLawrence Tang { 80*f8fc7052SJohn Chung UINT8 *error_structure = 81*f8fc7052SJohn Chung generate_random_bytes(IA32X64_ERROR_STRUCTURE_SIZE); 8202c801a5SLawrence Tang 83aacf0e26SLawrence Tang //Set error structure reserved space to zero. 84aacf0e26SLawrence Tang UINT64 *validation = (UINT64 *)(error_structure + 16); 85aacf0e26SLawrence Tang *validation &= 0x1F; 86aacf0e26SLawrence Tang 8702c801a5SLawrence Tang //Create a random type of error structure. 8802c801a5SLawrence Tang EFI_GUID *guid = (EFI_GUID *)error_structure; 89aacf0e26SLawrence Tang UINT64 *check_info = (UINT64 *)(error_structure + 24); 9002c801a5SLawrence Tang int error_structure_type = rand() % 4; 91*f8fc7052SJohn Chung switch (error_structure_type) { 9202c801a5SLawrence Tang //Cache 9302c801a5SLawrence Tang case 0: 94*f8fc7052SJohn Chung memcpy(guid, &gEfiIa32x64ErrorTypeCacheCheckGuid, 95*f8fc7052SJohn Chung sizeof(EFI_GUID)); 96aacf0e26SLawrence Tang 97aacf0e26SLawrence Tang //Set reserved space to zero. 98*f8fc7052SJohn Chung *check_info &= ~0x20FF00; 99aacf0e26SLawrence Tang *check_info &= 0x3FFFFFFF; 10002c801a5SLawrence Tang break; 10102c801a5SLawrence Tang 10202c801a5SLawrence Tang //TLB 10302c801a5SLawrence Tang case 1: 104*f8fc7052SJohn Chung memcpy(guid, &gEfiIa32x64ErrorTypeTlbCheckGuid, 105*f8fc7052SJohn Chung sizeof(EFI_GUID)); 106aacf0e26SLawrence Tang 107aacf0e26SLawrence Tang //Set reserved space to zero. 108*f8fc7052SJohn Chung *check_info &= ~0x20FF00; 109aacf0e26SLawrence Tang *check_info &= 0x3FFFFFFF; 11002c801a5SLawrence Tang break; 11102c801a5SLawrence Tang 11202c801a5SLawrence Tang //Bus 11302c801a5SLawrence Tang case 2: 114*f8fc7052SJohn Chung memcpy(guid, &gEfiIa32x64ErrorTypeBusCheckGuid, 115*f8fc7052SJohn Chung sizeof(EFI_GUID)); 116aacf0e26SLawrence Tang 117aacf0e26SLawrence Tang //Set reserved space to zero. 118*f8fc7052SJohn Chung *check_info &= ~0x20F800; 119aacf0e26SLawrence Tang *check_info &= 0x7FFFFFFFF; 12002c801a5SLawrence Tang break; 12102c801a5SLawrence Tang 12202c801a5SLawrence Tang //MS 12302c801a5SLawrence Tang case 3: 124*f8fc7052SJohn Chung memcpy(guid, &gEfiIa32x64ErrorTypeMsCheckGuid, 125*f8fc7052SJohn Chung sizeof(EFI_GUID)); 126aacf0e26SLawrence Tang 127aacf0e26SLawrence Tang //Set reserved space to zero. 12801e3a44dSLawrence Tang *check_info &= ~0xFFE0; 129aacf0e26SLawrence Tang *check_info &= 0xFFFFFF; 13002c801a5SLawrence Tang break; 13102c801a5SLawrence Tang } 13202c801a5SLawrence Tang 13302c801a5SLawrence Tang return error_structure; 13402c801a5SLawrence Tang } 13502c801a5SLawrence Tang 13602c801a5SLawrence Tang //Generates a single IA32/x64 context structure. Must later be freed. 13702c801a5SLawrence Tang size_t generate_ia32x64_context_structure(void **location) 13802c801a5SLawrence Tang { 13902c801a5SLawrence Tang //Initial length is 16 bytes. Add extra based on type. 14002c801a5SLawrence Tang int reg_type = rand() % 8; 14102c801a5SLawrence Tang int reg_size = 0; 14202c801a5SLawrence Tang 14302c801a5SLawrence Tang //Set register size. 144*f8fc7052SJohn Chung if (reg_type == 2) { 14502c801a5SLawrence Tang reg_size = 92; //IA32 registers. 146*f8fc7052SJohn Chung } else if (reg_type == 3) { 14702c801a5SLawrence Tang reg_size = 244; //x64 registers. 148*f8fc7052SJohn Chung } else { 14904750a9eSLawrence Tang reg_size = (rand() % 5 + 1) * 32; //Not table defined. 15004750a9eSLawrence Tang } 15102c801a5SLawrence Tang 15202c801a5SLawrence Tang //Create structure randomly. 15302c801a5SLawrence Tang int total_size = 16 + reg_size; 15402c801a5SLawrence Tang UINT16 *context_structure = (UINT16 *)generate_random_bytes(total_size); 15502c801a5SLawrence Tang 15604750a9eSLawrence Tang //If it is x64 registers, set reserved area accordingly. 157*f8fc7052SJohn Chung if (reg_type == 3) { 15804750a9eSLawrence Tang UINT8 *reg_bytes = (UINT8 *)(context_structure + 8); 15904750a9eSLawrence Tang UINT32 *reserved = (UINT32 *)(reg_bytes + 140); 16004750a9eSLawrence Tang *reserved = 0; 16104750a9eSLawrence Tang } 16204750a9eSLawrence Tang 16302c801a5SLawrence Tang //Set header information. 16402c801a5SLawrence Tang *(context_structure) = reg_type; 16502c801a5SLawrence Tang *(context_structure + 1) = reg_size; 16602c801a5SLawrence Tang 16702c801a5SLawrence Tang //Set return values and exit. 16802c801a5SLawrence Tang *location = context_structure; 16902c801a5SLawrence Tang return total_size; 17002c801a5SLawrence Tang } 171