1*67cbed6bSLawrence Tang /** 2*67cbed6bSLawrence Tang * Functions for generating psuedo-random CPER ARM processor sections. 3*67cbed6bSLawrence Tang * 4*67cbed6bSLawrence Tang * Author: Lawrence.Tang@arm.com 5*67cbed6bSLawrence Tang **/ 6*67cbed6bSLawrence Tang 7*67cbed6bSLawrence Tang #include <stdlib.h> 8*67cbed6bSLawrence Tang #include <string.h> 9*67cbed6bSLawrence Tang #include "../../edk/BaseTypes.h" 10*67cbed6bSLawrence Tang #include "../gen-utils.h" 11*67cbed6bSLawrence Tang #include "gen-sections.h" 12*67cbed6bSLawrence Tang #define ARM_ERROR_INFO_SIZE 32 13*67cbed6bSLawrence Tang 14*67cbed6bSLawrence Tang void* generate_arm_error_info(); 15*67cbed6bSLawrence Tang size_t generate_arm_context_info(void** location); 16*67cbed6bSLawrence Tang 17*67cbed6bSLawrence Tang //Generates a single psuedo-random ARM processor section, saving the resulting address to the given 18*67cbed6bSLawrence Tang //location. Returns the size of the newly created section. 19*67cbed6bSLawrence Tang size_t generate_section_arm(void** location) 20*67cbed6bSLawrence Tang { 21*67cbed6bSLawrence Tang //Set up for generation of error/context structures. 22*67cbed6bSLawrence Tang UINT16 error_structure_num = rand() % 4 + 1; //Must be at least 1. 23*67cbed6bSLawrence Tang UINT16 context_structure_num = rand() % 3; 24*67cbed6bSLawrence Tang void* error_structures[error_structure_num]; 25*67cbed6bSLawrence Tang void* context_structures[context_structure_num]; 26*67cbed6bSLawrence Tang size_t context_structure_lengths[context_structure_num]; 27*67cbed6bSLawrence Tang 28*67cbed6bSLawrence Tang //Generate the structures. 29*67cbed6bSLawrence Tang for (int i=0; i<error_structure_num; i++) 30*67cbed6bSLawrence Tang error_structures[i] = generate_arm_error_info(); 31*67cbed6bSLawrence Tang for (int i=0; i<context_structure_num; i++) 32*67cbed6bSLawrence Tang context_structure_lengths[i] = generate_arm_context_info(context_structures + i); 33*67cbed6bSLawrence Tang 34*67cbed6bSLawrence Tang //Determine a random amount of vendor specific info. 35*67cbed6bSLawrence Tang int vendor_info_len = rand() % 16; 36*67cbed6bSLawrence Tang 37*67cbed6bSLawrence Tang //Create the section as a whole. 38*67cbed6bSLawrence Tang size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE); 39*67cbed6bSLawrence Tang for (int i=0; i<context_structure_num; i++) 40*67cbed6bSLawrence Tang total_len += context_structure_lengths[i]; 41*67cbed6bSLawrence Tang total_len += vendor_info_len; 42*67cbed6bSLawrence Tang UINT8* section = generate_random_bytes(total_len); 43*67cbed6bSLawrence Tang 44*67cbed6bSLawrence Tang //Set header information. 45*67cbed6bSLawrence Tang UINT16* info_nums = (UINT16*)(section + 4); 46*67cbed6bSLawrence Tang *info_nums = error_structure_num; 47*67cbed6bSLawrence Tang *(info_nums + 1) = context_structure_num; 48*67cbed6bSLawrence Tang UINT32* section_length = (UINT32*)(section + 8); 49*67cbed6bSLawrence Tang *section_length = total_len; 50*67cbed6bSLawrence Tang 51*67cbed6bSLawrence Tang //Error affinity. 52*67cbed6bSLawrence Tang *(section + 12) = rand() % 4; 53*67cbed6bSLawrence Tang 54*67cbed6bSLawrence Tang //Reserved zero bytes. 55*67cbed6bSLawrence Tang memset(section + 13, 0, 3); 56*67cbed6bSLawrence Tang 57*67cbed6bSLawrence Tang //Copy in the sections/context structures, free resources. 58*67cbed6bSLawrence Tang UINT8* cur_pos = section + 40; 59*67cbed6bSLawrence Tang for (int i=0; i<error_structure_num; i++) 60*67cbed6bSLawrence Tang { 61*67cbed6bSLawrence Tang memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE); 62*67cbed6bSLawrence Tang free(error_structures[i]); 63*67cbed6bSLawrence Tang cur_pos += ARM_ERROR_INFO_SIZE; 64*67cbed6bSLawrence Tang } 65*67cbed6bSLawrence Tang for (int i=0; i<context_structure_num; i++) 66*67cbed6bSLawrence Tang { 67*67cbed6bSLawrence Tang memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 68*67cbed6bSLawrence Tang free(context_structures[i]); 69*67cbed6bSLawrence Tang cur_pos += context_structure_lengths[i]; 70*67cbed6bSLawrence Tang } 71*67cbed6bSLawrence Tang 72*67cbed6bSLawrence Tang //Set return values and exit. 73*67cbed6bSLawrence Tang *location = section; 74*67cbed6bSLawrence Tang return total_len; 75*67cbed6bSLawrence Tang } 76*67cbed6bSLawrence Tang 77*67cbed6bSLawrence Tang //Generates a single pseudo-random ARM error info structure. Must be later freed. 78*67cbed6bSLawrence Tang void* generate_arm_error_info() 79*67cbed6bSLawrence Tang { 80*67cbed6bSLawrence Tang UINT8* error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE); 81*67cbed6bSLawrence Tang 82*67cbed6bSLawrence Tang //Version (zero for revision of table referenced), length. 83*67cbed6bSLawrence Tang *error_info = 0; 84*67cbed6bSLawrence Tang *(error_info + 1) = ARM_ERROR_INFO_SIZE; 85*67cbed6bSLawrence Tang 86*67cbed6bSLawrence Tang //Type of error. 87*67cbed6bSLawrence Tang UINT8 error_type = rand() % 4; 88*67cbed6bSLawrence Tang *(error_info + 4) = error_type; 89*67cbed6bSLawrence Tang 90*67cbed6bSLawrence Tang //Make sure reserved bits are zero according with the type. 91*67cbed6bSLawrence Tang UINT64* error_subinfo = (UINT64*)(error_info + 8); 92*67cbed6bSLawrence Tang switch (error_type) 93*67cbed6bSLawrence Tang { 94*67cbed6bSLawrence Tang //Cache/TLB 95*67cbed6bSLawrence Tang case 0: 96*67cbed6bSLawrence Tang case 1: 97*67cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFF; 98*67cbed6bSLawrence Tang break; 99*67cbed6bSLawrence Tang 100*67cbed6bSLawrence Tang //Bus 101*67cbed6bSLawrence Tang case 2: 102*67cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFFFFFF; 103*67cbed6bSLawrence Tang break; 104*67cbed6bSLawrence Tang 105*67cbed6bSLawrence Tang //Microarch/other. 106*67cbed6bSLawrence Tang default: 107*67cbed6bSLawrence Tang break; 108*67cbed6bSLawrence Tang } 109*67cbed6bSLawrence Tang 110*67cbed6bSLawrence Tang return error_info; 111*67cbed6bSLawrence Tang } 112*67cbed6bSLawrence Tang 113*67cbed6bSLawrence Tang //Generates a single pseudo-random ARM context info structure. Must be later freed. 114*67cbed6bSLawrence Tang size_t generate_arm_context_info(void** location) 115*67cbed6bSLawrence Tang { 116*67cbed6bSLawrence Tang //Initial length is 8 bytes. Add extra based on type. 117*67cbed6bSLawrence Tang UINT16 reg_type = rand() % 9; 118*67cbed6bSLawrence Tang UINT32 reg_size = 0; 119*67cbed6bSLawrence Tang 120*67cbed6bSLawrence Tang //Set register size. 121*67cbed6bSLawrence Tang switch (reg_type) 122*67cbed6bSLawrence Tang { 123*67cbed6bSLawrence Tang //AARCH32 GPR, AARCH32 EL2 124*67cbed6bSLawrence Tang case 0: 125*67cbed6bSLawrence Tang case 2: 126*67cbed6bSLawrence Tang reg_size = 64; 127*67cbed6bSLawrence Tang break; 128*67cbed6bSLawrence Tang 129*67cbed6bSLawrence Tang //AARCH32 EL1 130*67cbed6bSLawrence Tang case 1: 131*67cbed6bSLawrence Tang reg_size = 96; 132*67cbed6bSLawrence Tang break; 133*67cbed6bSLawrence Tang 134*67cbed6bSLawrence Tang //AARCH32 EL3 135*67cbed6bSLawrence Tang case 3: 136*67cbed6bSLawrence Tang reg_size = 8; 137*67cbed6bSLawrence Tang break; 138*67cbed6bSLawrence Tang 139*67cbed6bSLawrence Tang //AARCH64 GPR 140*67cbed6bSLawrence Tang case 4: 141*67cbed6bSLawrence Tang reg_size = 256; 142*67cbed6bSLawrence Tang break; 143*67cbed6bSLawrence Tang 144*67cbed6bSLawrence Tang //AARCH64 EL1 145*67cbed6bSLawrence Tang case 5: 146*67cbed6bSLawrence Tang reg_size = 136; 147*67cbed6bSLawrence Tang break; 148*67cbed6bSLawrence Tang 149*67cbed6bSLawrence Tang //AARCH64 EL2 150*67cbed6bSLawrence Tang case 6: 151*67cbed6bSLawrence Tang reg_size = 120; 152*67cbed6bSLawrence Tang break; 153*67cbed6bSLawrence Tang 154*67cbed6bSLawrence Tang //AARCH64 EL3 155*67cbed6bSLawrence Tang case 7: 156*67cbed6bSLawrence Tang reg_size = 80; 157*67cbed6bSLawrence Tang break; 158*67cbed6bSLawrence Tang 159*67cbed6bSLawrence Tang //Misc. single register. 160*67cbed6bSLawrence Tang case 8: 161*67cbed6bSLawrence Tang reg_size = 10; 162*67cbed6bSLawrence Tang break; 163*67cbed6bSLawrence Tang } 164*67cbed6bSLawrence Tang 165*67cbed6bSLawrence Tang //Create context structure randomly. 166*67cbed6bSLawrence Tang int total_size = 8 + reg_size; 167*67cbed6bSLawrence Tang UINT16* context_info = (UINT16*)generate_random_bytes(total_size); 168*67cbed6bSLawrence Tang 169*67cbed6bSLawrence Tang //Set header information. 170*67cbed6bSLawrence Tang *(context_info + 1) = reg_type; 171*67cbed6bSLawrence Tang *((UINT32*)(context_info + 2)) = reg_size; 172*67cbed6bSLawrence Tang 173*67cbed6bSLawrence Tang //Set return values and exit. 174*67cbed6bSLawrence Tang *location = context_info; 175*67cbed6bSLawrence Tang return total_size; 176*67cbed6bSLawrence Tang }