167cbed6bSLawrence Tang /** 267cbed6bSLawrence Tang * Functions for generating psuedo-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" 1167cbed6bSLawrence Tang #include "gen-sections.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 1767cbed6bSLawrence Tang //Generates a single psuedo-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. 2367cbed6bSLawrence Tang UINT16 context_structure_num = rand() % 3; 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. 2967cbed6bSLawrence Tang for (int i=0; i<error_structure_num; i++) 3067cbed6bSLawrence Tang error_structures[i] = generate_arm_error_info(); 3167cbed6bSLawrence Tang for (int i=0; i<context_structure_num; i++) 3267cbed6bSLawrence Tang context_structure_lengths[i] = generate_arm_context_info(context_structures + i); 3367cbed6bSLawrence Tang 3467cbed6bSLawrence Tang //Determine a random amount of vendor specific info. 3567cbed6bSLawrence Tang int vendor_info_len = rand() % 16; 3667cbed6bSLawrence Tang 3767cbed6bSLawrence Tang //Create the section as a whole. 3867cbed6bSLawrence Tang size_t total_len = 40 + (error_structure_num * ARM_ERROR_INFO_SIZE); 3967cbed6bSLawrence Tang for (int i=0; i<context_structure_num; i++) 4067cbed6bSLawrence Tang total_len += context_structure_lengths[i]; 4167cbed6bSLawrence Tang total_len += vendor_info_len; 4267cbed6bSLawrence Tang UINT8* section = generate_random_bytes(total_len); 4367cbed6bSLawrence Tang 4467cbed6bSLawrence Tang //Set header information. 4567cbed6bSLawrence Tang UINT16* info_nums = (UINT16*)(section + 4); 4667cbed6bSLawrence Tang *info_nums = error_structure_num; 4767cbed6bSLawrence Tang *(info_nums + 1) = context_structure_num; 4867cbed6bSLawrence Tang UINT32* section_length = (UINT32*)(section + 8); 4967cbed6bSLawrence Tang *section_length = total_len; 5067cbed6bSLawrence Tang 5167cbed6bSLawrence Tang //Error affinity. 5267cbed6bSLawrence Tang *(section + 12) = rand() % 4; 5367cbed6bSLawrence Tang 5467cbed6bSLawrence Tang //Reserved zero bytes. 55*01e3a44dSLawrence Tang UINT64* validation = (UINT64*)section; 56*01e3a44dSLawrence Tang *validation &= 0b111; 57*01e3a44dSLawrence Tang UINT32* running_state = (UINT32*)(section + 32); 58*01e3a44dSLawrence Tang *running_state &= 0b1; 5967cbed6bSLawrence Tang memset(section + 13, 0, 3); 6067cbed6bSLawrence Tang 6167cbed6bSLawrence Tang //Copy in the sections/context structures, free resources. 6267cbed6bSLawrence Tang UINT8* cur_pos = section + 40; 6367cbed6bSLawrence Tang for (int i=0; i<error_structure_num; i++) 6467cbed6bSLawrence Tang { 6567cbed6bSLawrence Tang memcpy(cur_pos, error_structures[i], ARM_ERROR_INFO_SIZE); 6667cbed6bSLawrence Tang free(error_structures[i]); 6767cbed6bSLawrence Tang cur_pos += ARM_ERROR_INFO_SIZE; 6867cbed6bSLawrence Tang } 6967cbed6bSLawrence Tang for (int i=0; i<context_structure_num; i++) 7067cbed6bSLawrence Tang { 7167cbed6bSLawrence Tang memcpy(cur_pos, context_structures[i], context_structure_lengths[i]); 7267cbed6bSLawrence Tang free(context_structures[i]); 7367cbed6bSLawrence Tang cur_pos += context_structure_lengths[i]; 7467cbed6bSLawrence Tang } 7567cbed6bSLawrence Tang 7667cbed6bSLawrence Tang //Set return values and exit. 7767cbed6bSLawrence Tang *location = section; 7867cbed6bSLawrence Tang return total_len; 7967cbed6bSLawrence Tang } 8067cbed6bSLawrence Tang 8167cbed6bSLawrence Tang //Generates a single pseudo-random ARM error info structure. Must be later freed. 8267cbed6bSLawrence Tang void* generate_arm_error_info() 8367cbed6bSLawrence Tang { 8467cbed6bSLawrence Tang UINT8* error_info = generate_random_bytes(ARM_ERROR_INFO_SIZE); 8567cbed6bSLawrence Tang 8667cbed6bSLawrence Tang //Version (zero for revision of table referenced), length. 8767cbed6bSLawrence Tang *error_info = 0; 8867cbed6bSLawrence Tang *(error_info + 1) = ARM_ERROR_INFO_SIZE; 8967cbed6bSLawrence Tang 9067cbed6bSLawrence Tang //Type of error. 9167cbed6bSLawrence Tang UINT8 error_type = rand() % 4; 9267cbed6bSLawrence Tang *(error_info + 4) = error_type; 9367cbed6bSLawrence Tang 94*01e3a44dSLawrence Tang //Reserved bits for error information. 95*01e3a44dSLawrence Tang UINT16* validation = (UINT16*)(error_info + 2); 96*01e3a44dSLawrence Tang *validation &= 0x1F; 97*01e3a44dSLawrence Tang 9867cbed6bSLawrence Tang //Make sure reserved bits are zero according with the type. 9967cbed6bSLawrence Tang UINT64* error_subinfo = (UINT64*)(error_info + 8); 10067cbed6bSLawrence Tang switch (error_type) 10167cbed6bSLawrence Tang { 10267cbed6bSLawrence Tang //Cache/TLB 10367cbed6bSLawrence Tang case 0: 10467cbed6bSLawrence Tang case 1: 10567cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFF; 10667cbed6bSLawrence Tang break; 10767cbed6bSLawrence Tang 10867cbed6bSLawrence Tang //Bus 10967cbed6bSLawrence Tang case 2: 11067cbed6bSLawrence Tang *error_subinfo &= 0xFFFFFFFFFFF; 11167cbed6bSLawrence Tang break; 11267cbed6bSLawrence Tang 11367cbed6bSLawrence Tang //Microarch/other. 11467cbed6bSLawrence Tang default: 11567cbed6bSLawrence Tang break; 11667cbed6bSLawrence Tang } 11767cbed6bSLawrence Tang 11867cbed6bSLawrence Tang return error_info; 11967cbed6bSLawrence Tang } 12067cbed6bSLawrence Tang 12167cbed6bSLawrence Tang //Generates a single pseudo-random ARM context info structure. Must be later freed. 12267cbed6bSLawrence Tang size_t generate_arm_context_info(void** location) 12367cbed6bSLawrence Tang { 12467cbed6bSLawrence Tang //Initial length is 8 bytes. Add extra based on type. 12567cbed6bSLawrence Tang UINT16 reg_type = rand() % 9; 12667cbed6bSLawrence Tang UINT32 reg_size = 0; 12767cbed6bSLawrence Tang 12867cbed6bSLawrence Tang //Set register size. 12967cbed6bSLawrence Tang switch (reg_type) 13067cbed6bSLawrence Tang { 13167cbed6bSLawrence Tang //AARCH32 GPR, AARCH32 EL2 13267cbed6bSLawrence Tang case 0: 13367cbed6bSLawrence Tang case 2: 13467cbed6bSLawrence Tang reg_size = 64; 13567cbed6bSLawrence Tang break; 13667cbed6bSLawrence Tang 13767cbed6bSLawrence Tang //AARCH32 EL1 13867cbed6bSLawrence Tang case 1: 13967cbed6bSLawrence Tang reg_size = 96; 14067cbed6bSLawrence Tang break; 14167cbed6bSLawrence Tang 14267cbed6bSLawrence Tang //AARCH32 EL3 14367cbed6bSLawrence Tang case 3: 14467cbed6bSLawrence Tang reg_size = 8; 14567cbed6bSLawrence Tang break; 14667cbed6bSLawrence Tang 14767cbed6bSLawrence Tang //AARCH64 GPR 14867cbed6bSLawrence Tang case 4: 14967cbed6bSLawrence Tang reg_size = 256; 15067cbed6bSLawrence Tang break; 15167cbed6bSLawrence Tang 15267cbed6bSLawrence Tang //AARCH64 EL1 15367cbed6bSLawrence Tang case 5: 15467cbed6bSLawrence Tang reg_size = 136; 15567cbed6bSLawrence Tang break; 15667cbed6bSLawrence Tang 15767cbed6bSLawrence Tang //AARCH64 EL2 15867cbed6bSLawrence Tang case 6: 15967cbed6bSLawrence Tang reg_size = 120; 16067cbed6bSLawrence Tang break; 16167cbed6bSLawrence Tang 16267cbed6bSLawrence Tang //AARCH64 EL3 16367cbed6bSLawrence Tang case 7: 16467cbed6bSLawrence Tang reg_size = 80; 16567cbed6bSLawrence Tang break; 16667cbed6bSLawrence Tang 16767cbed6bSLawrence Tang //Misc. single register. 16867cbed6bSLawrence Tang case 8: 16967cbed6bSLawrence Tang reg_size = 10; 17067cbed6bSLawrence Tang break; 17167cbed6bSLawrence Tang } 17267cbed6bSLawrence Tang 17367cbed6bSLawrence Tang //Create context structure randomly. 17467cbed6bSLawrence Tang int total_size = 8 + reg_size; 17567cbed6bSLawrence Tang UINT16* context_info = (UINT16*)generate_random_bytes(total_size); 17667cbed6bSLawrence Tang 17767cbed6bSLawrence Tang //Set header information. 17867cbed6bSLawrence Tang *(context_info + 1) = reg_type; 17967cbed6bSLawrence Tang *((UINT32*)(context_info + 2)) = reg_size; 18067cbed6bSLawrence Tang 18167cbed6bSLawrence Tang //Set return values and exit. 18267cbed6bSLawrence Tang *location = context_info; 18367cbed6bSLawrence Tang return total_size; 18467cbed6bSLawrence Tang }