167cbed6bSLawrence Tang /** 2efe17e2cSLawrence Tang * Functions for generating pseudo-random CPER ARM processor sections. 367cbed6bSLawrence Tang * 467cbed6bSLawrence Tang * Author: Lawrence.Tang@arm.com 567cbed6bSLawrence Tang **/ 667cbed6bSLawrence Tang 767cbed6bSLawrence Tang #include <stdlib.h> 867cbed6bSLawrence Tang #include <string.h> 967cbed6bSLawrence Tang #include "../../edk/BaseTypes.h" 1067cbed6bSLawrence Tang #include "../gen-utils.h" 118f977457SLawrence Tang #include "gen-section.h" 1267cbed6bSLawrence Tang #define ARM_ERROR_INFO_SIZE 32 1367cbed6bSLawrence Tang 1467cbed6bSLawrence Tang void *generate_arm_error_info(); 1567cbed6bSLawrence Tang size_t generate_arm_context_info(void **location); 1667cbed6bSLawrence Tang 17efe17e2cSLawrence Tang //Generates a single pseudo-random ARM processor section, saving the resulting address to the given 1867cbed6bSLawrence Tang //location. Returns the size of the newly created section. 1967cbed6bSLawrence Tang size_t generate_section_arm(void **location) 2067cbed6bSLawrence Tang { 2167cbed6bSLawrence Tang //Set up for generation of error/context structures. 2267cbed6bSLawrence Tang UINT16 error_structure_num = rand() % 4 + 1; //Must be at least 1. 23*f8fc7052SJohn Chung UINT16 context_structure_num = rand() % 3 + 1; 2467cbed6bSLawrence Tang void *error_structures[error_structure_num]; 2567cbed6bSLawrence Tang void *context_structures[context_structure_num]; 2667cbed6bSLawrence Tang size_t context_structure_lengths[context_structure_num]; 2767cbed6bSLawrence Tang 2867cbed6bSLawrence Tang //Generate the structures. 29*f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) { 3067cbed6bSLawrence Tang error_structures[i] = generate_arm_error_info(); 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_arm_context_info(context_structures + i); 35*f8fc7052SJohn Chung } 3667cbed6bSLawrence Tang 3767cbed6bSLawrence Tang //Determine a random amount of vendor specific info. 3867cbed6bSLawrence Tang int vendor_info_len = rand() % 16; 3967cbed6bSLawrence Tang 4067cbed6bSLawrence Tang //Create the section as a whole. 4167cbed6bSLawrence Tang size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE); 42*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) { 4367cbed6bSLawrence Tang total_len += context_structure_lengths[i]; 44*f8fc7052SJohn Chung } 4567cbed6bSLawrence Tang total_len += vendor_info_len; 4667cbed6bSLawrence Tang UINT8 *section = generate_random_bytes(total_len); 4767cbed6bSLawrence Tang 4867cbed6bSLawrence Tang //Set header information. 4967cbed6bSLawrence Tang UINT16 *info_nums = (UINT16 *)(section + 4); 5067cbed6bSLawrence Tang *info_nums = error_structure_num; 5167cbed6bSLawrence Tang *(info_nums + 1) = context_structure_num; 5267cbed6bSLawrence Tang UINT32 *section_length = (UINT32 *)(section + 8); 5367cbed6bSLawrence Tang *section_length = total_len; 5467cbed6bSLawrence Tang 5567cbed6bSLawrence Tang //Error affinity. 5667cbed6bSLawrence Tang *(section + 12) = rand() % 4; 5767cbed6bSLawrence Tang 5867cbed6bSLawrence Tang //Reserved zero bytes. 5901e3a44dSLawrence Tang UINT64 *validation = (UINT64 *)section; 60*f8fc7052SJohn Chung *validation &= 0x7; 6101e3a44dSLawrence Tang UINT32 *running_state = (UINT32 *)(section + 32); 62*f8fc7052SJohn Chung *running_state &= 0x1; 6367cbed6bSLawrence Tang memset(section + 13, 0, 3); 6467cbed6bSLawrence Tang 6567cbed6bSLawrence Tang //Copy in the sections/context structures, free resources. 6667cbed6bSLawrence Tang UINT8 *cur_pos = section + 40; 67*f8fc7052SJohn Chung for (int i = 0; i < error_structure_num; i++) { 6867cbed6bSLawrence Tang memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE); 6967cbed6bSLawrence Tang free(error_structures[i]); 7067cbed6bSLawrence Tang cur_pos += ARM_ERROR_INFO_SIZE; 7167cbed6bSLawrence Tang } 72*f8fc7052SJohn Chung for (int i = 0; i < context_structure_num; i++) { 73*f8fc7052SJohn Chung memcpy(cur_pos, context_structures[i], 74*f8fc7052SJohn Chung context_structure_lengths[i]); 7567cbed6bSLawrence Tang free(context_structures[i]); 7667cbed6bSLawrence Tang cur_pos += context_structure_lengths[i]; 7767cbed6bSLawrence Tang } 7867cbed6bSLawrence Tang 7967cbed6bSLawrence Tang //Set return values and exit. 8067cbed6bSLawrence Tang *location = section; 8167cbed6bSLawrence Tang return total_len; 8267cbed6bSLawrence Tang } 8367cbed6bSLawrence Tang 8467cbed6bSLawrence Tang //Generates a single pseudo-random ARM error info structure. Must be later freed. 8567cbed6bSLawrence Tang void *generate_arm_error_info() 8667cbed6bSLawrence Tang { 8767cbed6bSLawrence Tang UINT8 *error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE); 8867cbed6bSLawrence Tang 8967cbed6bSLawrence Tang //Version (zero for revision of table referenced), length. 9067cbed6bSLawrence Tang *error_info = 0; 9167cbed6bSLawrence Tang *(error_info + 1) = ARM_ERROR_INFO_SIZE; 9267cbed6bSLawrence Tang 9367cbed6bSLawrence Tang //Type of error. 9467cbed6bSLawrence Tang UINT8 error_type = rand() % 4; 9567cbed6bSLawrence Tang *(error_info + 4) = error_type; 9667cbed6bSLawrence Tang 9701e3a44dSLawrence Tang //Reserved bits for error information. 9801e3a44dSLawrence Tang UINT16 *validation = (UINT16 *)(error_info + 2); 9901e3a44dSLawrence Tang *validation &= 0x1F; 10001e3a44dSLawrence Tang 10167cbed6bSLawrence Tang //Make sure reserved bits are zero according with the type. 10267cbed6bSLawrence Tang UINT64 *error_subinfo = (UINT64 *)(error_info + 8); 103*f8fc7052SJohn Chung switch (error_type) { 10467cbed6bSLawrence Tang //Cache/TLB 10567cbed6bSLawrence Tang case 0: 10667cbed6bSLawrence Tang case 1: 10767cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFF; 10867cbed6bSLawrence Tang break; 10967cbed6bSLawrence Tang 11067cbed6bSLawrence Tang //Bus 11167cbed6bSLawrence Tang case 2: 11267cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFFFFFF; 11367cbed6bSLawrence Tang break; 11467cbed6bSLawrence Tang 11567cbed6bSLawrence Tang //Microarch/other. 11667cbed6bSLawrence Tang default: 11767cbed6bSLawrence Tang break; 11867cbed6bSLawrence Tang } 11967cbed6bSLawrence Tang 12067cbed6bSLawrence Tang return error_info; 12167cbed6bSLawrence Tang } 12267cbed6bSLawrence Tang 12367cbed6bSLawrence Tang //Generates a single pseudo-random ARM context info structure. Must be later freed. 12467cbed6bSLawrence Tang size_t generate_arm_context_info(void **location) 12567cbed6bSLawrence Tang { 12667cbed6bSLawrence Tang //Initial length is 8 bytes. Add extra based on type. 12767cbed6bSLawrence Tang UINT16 reg_type = rand() % 9; 12867cbed6bSLawrence Tang UINT32 reg_size = 0; 12967cbed6bSLawrence Tang 13067cbed6bSLawrence Tang //Set register size. 131*f8fc7052SJohn Chung switch (reg_type) { 13267cbed6bSLawrence Tang //AARCH32 GPR, AARCH32 EL2 13367cbed6bSLawrence Tang case 0: 13467cbed6bSLawrence Tang case 2: 13567cbed6bSLawrence Tang reg_size = 64; 13667cbed6bSLawrence Tang break; 13767cbed6bSLawrence Tang 13867cbed6bSLawrence Tang //AARCH32 EL1 13967cbed6bSLawrence Tang case 1: 14067cbed6bSLawrence Tang reg_size = 96; 14167cbed6bSLawrence Tang break; 14267cbed6bSLawrence Tang 14367cbed6bSLawrence Tang //AARCH32 EL3 14467cbed6bSLawrence Tang case 3: 14567cbed6bSLawrence Tang reg_size = 8; 14667cbed6bSLawrence Tang break; 14767cbed6bSLawrence Tang 14867cbed6bSLawrence Tang //AARCH64 GPR 14967cbed6bSLawrence Tang case 4: 15067cbed6bSLawrence Tang reg_size = 256; 15167cbed6bSLawrence Tang break; 15267cbed6bSLawrence Tang 15367cbed6bSLawrence Tang //AARCH64 EL1 15467cbed6bSLawrence Tang case 5: 15567cbed6bSLawrence Tang reg_size = 136; 15667cbed6bSLawrence Tang break; 15767cbed6bSLawrence Tang 15867cbed6bSLawrence Tang //AARCH64 EL2 15967cbed6bSLawrence Tang case 6: 16067cbed6bSLawrence Tang reg_size = 120; 16167cbed6bSLawrence Tang break; 16267cbed6bSLawrence Tang 16367cbed6bSLawrence Tang //AARCH64 EL3 16467cbed6bSLawrence Tang case 7: 16567cbed6bSLawrence Tang reg_size = 80; 16667cbed6bSLawrence Tang break; 16767cbed6bSLawrence Tang 16867cbed6bSLawrence Tang //Misc. single register. 16967cbed6bSLawrence Tang case 8: 17067cbed6bSLawrence Tang reg_size = 10; 17167cbed6bSLawrence Tang break; 17267cbed6bSLawrence Tang } 17367cbed6bSLawrence Tang 17467cbed6bSLawrence Tang //Create context structure randomly. 17567cbed6bSLawrence Tang int total_size = 8 + reg_size; 17667cbed6bSLawrence Tang UINT16 *context_info = (UINT16 *)generate_random_bytes(total_size); 17767cbed6bSLawrence Tang 17867cbed6bSLawrence Tang //Set header information. 17967cbed6bSLawrence Tang *(context_info + 1) = reg_type; 18067cbed6bSLawrence Tang *((UINT32 *)(context_info + 2)) = reg_size; 18167cbed6bSLawrence Tang 18267cbed6bSLawrence Tang //Set return values and exit. 18367cbed6bSLawrence Tang *location = context_info; 18467cbed6bSLawrence Tang return total_size; 18567cbed6bSLawrence Tang } 186